問題

問題

問題

我有以下內容

git reset HEAD^ half_entered_file_n<Tab>

此時,我希望 half_entered_file_name.txt 以製表符完成。

我自己的調查

如果我寫,我可以讓製表符完成工作

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-completion.zsh/.bash 改變了文法。

我不太了解 shell 腳本,無法準確理解 git-completion.zsh/.bash 中發生的情況,以及這是否是事情發生的原因。

答案1

為什麼你不應該假設

在最長的時間裡,我假設我的 zsh 配置中的 git 補全來自/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 運行完成腳本。您可以按照這個答案來做到這一點

相關內容