En zsh (así como bash) puede usar algunas expansiones de palabras del historial para denotar argumentos de comandos anteriores.
Este ejemplo muestra cómo obtener el segundo parámetro del comando anterior en el historial con !:#
expansión:
% echo foo bar baz
foo bar baz
% echo !:2
echo bar
bar
A menudo olvido exactamente qué parámetro # es un argumento en particular y escribir !:#
no siempre es tan rápido cuando recuerdo qué argumento es. Sé a punto meta-.
de reemplazar el último argumento, pero a veces no es el último argumento que quiero.
Me gustaría agregar los argumentos del comando anterior como sugerencias para completar cualquier comando que estoy escribiendo en zsh.
Pude descubrir cómo crear una función de shell que pueda crear una matriz de argumentos (0..N) desde el último comando y vincularlo a un comando en particular.
_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
Esto es lo que parece completar solo foo donde presioné la tecla tab en <TAB>
:
% echo bar baz qux
bar baz qux
% foo <TAB>
bar baz echo qux
Esto funciona muy bien para completar el comando "foo", pero me gustaría que sean opciones en cualquier expansión de zsh que haga. Creo que tiene algo que ver con las cosas completadoras de zstyle, pero después de unas horas de pirateo me di cuenta de que estaba fuera de mi alcance.
¿Cómo puedo obtener los argumentos de mi comando anterior como finalizaciones sugeridas para cualquier comando en zsh?
Tengo mi archivo completo de compilación zshrc compartido en bitbucket si eso ayuda. Mucho de esto se basa en una variedad de fuentes y algunas de ellas las he pirateado yo mismo.
ACTUALIZAR:
La respuesta de @Julien Nicoulaud me acercó, lo marqué como aceptado ya que me llevó a donde necesitaba llegar.
Con mi configuración particular, usando lo sugerido:
zstyle ':completion:*' completer _last_command_args _complete
No funcionó para mí, ya que estaba causando que la finalización de la pestaña solo mostrara la lista de argumentos del último comando (aunque en realidad también se completaría con los nombres de los archivos, pero no los mostraría). Cambiar el orden a _complete _last_command_args
hizo lo contrario. Mostraría los nombres de archivo normales, pero no last_command_args
Supongo que esto tiene algo que ver con la forma en que funciona el completer. Creo que solo muestra la salida del primer método que regresa con éxito, pero tengo problemas para analizar la fuente zsh para comprender completamente lo que está sucediendo. Pude ajustar mi método para incluir una llamada para _complete
que mostrara tanto los últimos comandos de argumento como las cosas de autocompletar normales. No tan separados, pero funciona lo suficientemente bien para mí.
Aquí está la función completa que utilicé junto con otras cosas de zstyle que tengo:
# 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
Otras líneas de zstyle que tengo, no son necesarias para que esto funcione, pero podrían afectar por qué esto funciona para mí:
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
Ahora, si estoy en un directorio con file1.txt
y file2.txt
, y mi último comando fue echo foo bar baz
, obtengo esto para autocompletar, que es justo lo que quería:
% ls
bar baz echo foo
- files -
file1.txt file2.txt
^[ .
( insert-last-word
), me gusta copy-earlier-word
, que alterna entre las palabras de la línea alcanzada por insert-last-word
. Para su .zshrc
:autoload copy-earlier-word && zle -N copy-earlier-word && bindkey '^[,' copy-earlier-word