Проблема
У меня есть следующее
git reset HEAD^ half_entered_file_n<Tab>
На этом этапе я бы хотел, чтобы half_entered_file_name.txt был дополнен клавишей Tab.
Мое собственное расследование
Я могу заставить работать автодополнение 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.
Спасибо!
Обновлять
Я нашел несколько полурешений, но ни одно из них пока не приводит к статусу «решено», что по сути делает их нерешенными.
- установить
compdef -d git
в .zshrcкак предложил "пещерный человек"- Решено: Теперь HEAD^ больше не нарушает автодополнение файлов.
- Недостаток: автодополнение команд git больше не работает.
- Использоватьпринятый ответ от "ralphtheninja" на этот вопрос
- Решает: Следует заменить способ формирования списка завершения файлов, что решит проблему.
- Недостаток: Не работает. Похоже, git-completion.zsh/.bash изменил синтаксис.
Я недостаточно хорошо знаю скриптинг оболочки, чтобы точно понять, что происходит в git-completion.zsh/.bash, и является ли это причиной сбоев.
решение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.приложениедля отслеживания того, к каким скриптам осуществляется доступ в файловой системе, но тогда я в этом не разобрался (вывод довольно болтливый и показывает также доступы из других приложений).
Что происходит?
Следы показали это (частичные следы впереди!)
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.Вы можете сделать это, следуя этому ответу.