2

проблема

У меня есть следующее

git reset HEAD^ half_entered_file_n<Tab>

На этом этапе я бы хотел, чтобы half_entered_file_name.txt был завершен.

Мое собственное расследование

Я могу получить завершение Tab, если я напишу

git reset HEAD\^ ...

вместо этого, избегая "^".

Запись «^» в качестве последнего символа, похоже, не влияет на автозаполнение, если только не присутствует HEAD:

#autocomplete works
git reset RANDOM^ half_entered_file_n<Tab> #works

Конфигурация Zsh

Я пользуюсь Oh-my-zsh. Помимо oh-my-zsh я настроил следующее, что может иметь отношение к делу:

# Let <TAB> auto completion add a slash at the end instead of space (like BASH)
zstyle ':completion:*' special-dirs true 

# Unless this option is set, you can't write git checkout HEAD^^ without escaping ^ as \^ in zsh
setopt NO_NOMATCH 

# Standard git plugins
plugins=(git git-extras)

Для полноты вот моя конфигурация

Я запускаю это на OSX в iTerm2.

Спасибо!

Обновить

Я нашел несколько полу-решений, но ни одно из них еще не привело к статусу "отвечено", что в основном делает их нерешительными.

  1. установить compdef -d git в .zshrc как предложено "пещерным человеком"
    • Решает: теперь HEAD ^ больше не прерывает автозаполнение файла.
    • Недостаток: автозаполнение команды git больше не работает.
  2. Воспользуйтесь принятым ответом "ralphtheninja" из этого вопроса
    • Решает: Должен заменить способ создания списка завершения файла, который решит проблему.
    • Недостаток: не работает. Похоже, git-extension.zsh/.bash изменил синтаксис.

Я не знаю сценариев оболочки достаточно хорошо, чтобы точно понять, что происходит в git-creation.zsh/.bash, и, если это причина, то что-то ломается.

1 ответ1

1

Почему вы не должны предполагать

Долгое время я предполагал, что завершение git в моей конфигурации zsh происходит из /usr/local/share/git-core/contrib/completion/ , в частности из git-completion.zsh или даже из git-completion.bash . Я предполагаю, что я предполагал это, потому что большинство поисков даст результаты, говоря об этих файлах. Однако я явно не включил ни один из этих файлов, и долгое время я просто предполагал, что oh-my-zsh включает их.

Но...

Мы больше не в Канзасе

До тех пор, пока я не использовал трассировку методов zsh, активированную с помощью setopt xtrace , я понял (путем поиска имен некоторых методов), что используемый скрипт на самом деле был /usr/local/share/zsh/functions/_git . Ранее я использовал XCode Instruments.app для отслеживания того, к каким сценариям обращались в файловой системе, но потом не понял (вывод довольно болтливый и показывает доступ из других приложений).

В чем дело?

Следы показали это (частичные следы впереди!)

git reset HEAD <TAB>
...
+__git_tree_files:17> tree=HEAD
+__git_tree_files:18> tree_files+=+__git_tree_files:18> _call_program tree-files git ls-tree --name-only -z HEAD ./
+__git_tree_files:18> tree_files+=( first second third )

А также

git reset HEAD^ <TAB>
...
+__git_tree_files:17> tree=HEAD^
+__git_tree_files:18> tree_files+=+__git_tree_files:18> _call_program tree-files git ls-tree --name-only -z 'HEAD^' ./
+__git_tree_files:18> tree_files+=( )

Эти пустые tree_files выглядят подозрительно.

В строке 6058 в /usr/local/share/zsh/functions/_git мы находим

tree_files+=(${(ps:\0:)"$(_call_program tree-files git ls-tree $extra_args --name-only -z $tree $Path 2>/dev/null)"})

Нам определенно нужно экранировать эту переменную $tree . Сказано и сделано:

tree_files+=(${(ps:\0:)"$(_call_program tree-files git ls-tree $extra_args --name-only -z ${(q)tree} $Path 2>/dev/null)"}) 

эпилог

В этом скрипте происходит еще несколько ошибок (например, список файлов для git reset <tree-ish> основан на <tree-ish> , когда он должен быть основан на HEAD. Теперь я знаю, где их исправить!

Обновить

Существует также возможность запуска сценариев завершения из git. Вы можете сделать это, следуя этому ответу.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .