Zsh / git: O preenchimento automático de tabulação não funciona se “HEAD ^” estiver ao lado da última palavra na linha de entrada

2

Problema

Eu tenho o seguinte

git reset HEAD^ half_entered_file_n<Tab>

Neste ponto, gostaria que o half_entered_file_name.txt fosse preenchido por Tab.

Minha própria investigação

Eu posso fazer a conclusão do Tab funcionar se eu escrever

git reset HEAD\^ ...

em vez disso, escapando do "^".

Escrevendo um "^" como o último caractere não parece afetar o preenchimento automático, a menos que HEAD também esteja presente:

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

Configuração do Zsh

Estou usando o Oh-my-zsh. Em cima de oh-my-zsh, eu configurei o seguinte que pode ser relevante:

# 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)

Para completar, aqui está minha configuração

Estou executando isso no OSX no iTerm2.

Obrigado!

Atualizar

Encontrei algumas semi-soluções, mas nenhuma que leve a um status "respondido" ainda, o que basicamente faz com que elas não sejam soluções.

  1. defina compdef -d git em .zshrc como proposto por" homem das cavernas "
    • Resolve: Agora o HEAD ^ não quebra mais o preenchimento automático de arquivos.
    • Desvantagem: o preenchimento automático do comando git não funciona mais.
  2. Use o aceito responder por "ralphtheninja" desta questão
    • Resolve: deve substituir a forma como a lista de conclusão de arquivos é gerada, o que resolveria o problema.
    • Desvantagem: não funciona. Parece que o git-completion.zsh / .bash mudou a sintaxe.

Eu não conheço o shell script o suficiente para entender exatamente o que está acontecendo em git-completion.zsh / .bash, e se essa é a razão pela qual as coisas estão quebrando.

    
por Erik Zivkovic 15.10.2015 / 16:27

1 resposta

1

Por que você não deve assumir

Durante muito tempo, presumi que a conclusão do git na minha configuração de zsh vinha de /usr/local/share/git-core/contrib/completion/ , especificamente de git-completion.zsh ou mesmo git-completion.bash . Eu acho que eu estava assumindo isso porque a maioria das pesquisas irá produzir resultados falando sobre esses arquivos. No entanto, não incluí explicitamente nenhum desses arquivos e, por mais tempo, estava apenas supondo que o oh-my-zsh os estava incluindo.

Mas ...

Não estamos mais no Kansas

Não foi até eu usar o rastreamento do método zsh, ativado via setopt xtrace , que percebi (pesquisando alguns nomes de método) que o script sendo usado era, de fato, /usr/local/share/zsh/functions/_git . Eu tinha usado anteriormente XCode Instruments.app para monitorar quais scripts estavam sendo acessados no sistema de arquivos, mas não os identificaram (a saída é bastante tagarela e também mostra acessos de outros aplicativos).

O que está acontecendo?

Os traços mostraram isso (traços parciais à frente!)

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 )

e

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+=( )

Esse vazio tree_files parece suspeito.

Na linha 6058 em /usr/local/share/zsh/functions/_git , encontramos

tree_files+=(${(ps:
tree_files+=(${(ps:
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 )
:)"$(_call_program tree-files git ls-tree $extra_args --name-only -z ${(q)tree} $Path 2>/dev/null)"})
:)"$(_call_program tree-files git ls-tree $extra_args --name-only -z $tree $Path 2>/dev/null)"})

Definitivamente precisamos escapar dessa variável $tree . Dito e feito:

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+=( )

Epílogo

Existem mais alguns bugs neste script (por exemplo, a lista de arquivos de git reset <tree-ish> é baseada no <tree-ish> , quando deveria ser baseado no HEAD. Agora eu sei onde corrigi-los!

Atualizar

Existe também a possibilidade de executar os scripts de conclusão do git. Você pode fazer isso seguindo esta resposta .

    
por 17.10.2015 / 20:34