No zsh (assim como no bash), você pode usar algumas expansões de palavras do histórico para denotar argumentos de comandos anteriores.
Este exemplo mostra como obter o segundo parâmetro do comando anterior no histórico com !:#
expansão:
% echo foo bar baz
foo bar baz
% echo !:2
echo bar
bar
Costumo esquecer exatamente o que # parâmetro é um argumento específico e a digitação !:#
nem sempre é tão rápida quando me lembro qual é o argumento. Eu sei sobre meta-.
substituir o último argumento, mas às vezes não é o último argumento que eu quero.
Eu gostaria de adicionar os argumentos do comando anterior como sugestões para concluir qualquer comando que eu estou digitando no zsh.
Consegui descobrir como criar uma função shell que pode criar uma matriz de argumentos (0..N) a partir do último comando e vinculá-la a um comando específico.
_last_command_args() {
last_command=$history[$[HISTCMD-1]]
last_command_array=("${(s/ /)last_command}")
_sep_parts last_command_array
}
# trying to get last_command_args to be suggested for any command, this just works for foo
compdef _last_command_args foo
Isto é o que parece para completar apenas onde eu apertei a tecla tab em <TAB>
:
% echo bar baz qux
bar baz qux
% foo <TAB>
bar baz echo qux
Isso funciona muito bem para a conclusão do comando "foo", mas eu gostaria que fossem opções em qualquer expansão zsh que eu faça. Eu acho que tem algo a ver com as coisas completas do zstyle, mas depois de algumas horas de hackers, percebi que estava fora do meu alcance.
Como posso obter os argumentos do meu comando anterior como conclusões sugeridas para qualquer comando no zsh?
Eu tenho meu arquivo completo de instalação do zshrc compartilhado no bitbucket, se isso ajudar. Muito disso é extraído de uma variedade de fontes e algumas delas foram hackeadas.
ATUALIZAR:
A resposta de @Julien Nicoulaud me aproximou, estou marcando-a como aceita como me levou aonde eu precisava chegar.
Com minha configuração específica, usando o sugerido:
zstyle ':completion:*' completer _last_command_args _complete
Não funcionou para mim, pois estava fazendo com que a conclusão da guia exibisse apenas a lista de argumentos do último comando (embora na verdade fosse concluída com nomes de arquivos, mas não apenas). Alterar a ordem para _complete _last_command_args
fazer o inverso. Seria exibir os nomes de arquivos normais, mas não last_command_args
Acho que isso tem algo a ver com a maneira como o completer funciona. Eu acho que apenas exibe a saída do primeiro método que retorna com êxito, mas estou tendo problemas para analisar a fonte zsh para entender completamente o que está acontecendo. Consegui ajustar meu método para incluir uma chamada para _complete
que mostrasse os comandos do último argumento e o material de preenchimento automático regular. Não é tão separado, mas funciona bem o suficiente para mim.
Aqui está a função completa que usei, juntamente com as outras coisas do zstyle que tenho:
# adds the arguments from the last commadn to the autocomplete list
# I wasn't able to get this to work standalone and still print out both regular
# completion plus the last args, but this works well enough.
_complete_plus_last_command_args() {
last_command=$history[$[HISTCMD-1]]
last_command_array=("${(s/ /)last_command}")
_sep_parts last_command_array
_complete
}
_force_rehash() {
(( CURRENT == 1 )) && rehash
return 1 # Because we didn't really complete anything
}
zstyle ':completion:::::' completer _force_rehash _complete_plus_last_command_args _approximate
Outras linhas do zstyle que eu tenho, não são necessárias para que isso funcione, mas podem afetar por que isso funciona para mim:
zstyle -e ':completion:*:approximate:*' max-errors 'reply=( $(( ($#PREFIX + $#SUFFIX) / 3 )) )'
zstyle ':completion:*:descriptions' format "- %d -"
zstyle ':completion:*:corrections' format "- %d - (errors %e})"
zstyle ':completion:*:default' list-prompt '%S%M matches%s'
zstyle ':completion:*' group-name ''
zstyle ':completion:*:manuals' separate-sections true
zstyle ':completion:*' menu select
zstyle ':completion:*' verbose yes
Agora, se eu estiver em um diretório com file1.txt
e file2.txt
, e meu último comando foi echo foo bar baz
, eu recebo isso para preenchimento automático, que é exatamente o que eu queria:
% ls
bar baz echo foo
- files -
file1.txt file2.txt
^[ .
( insert-last-word
), eu gosto copy-earlier-word
, que alterna entre as palavras da linha alcançada por insert-last-word
. Para o seu .zshrc
:autoload copy-earlier-word && zle -N copy-earlier-word && bindkey '^[,' copy-earlier-word