Terminal macOS: forma rápida de editar opciones de comando después de autocompletar bash/zsh

La cuestión

Utilizo mucho la función de autocompletar desde el historial, ya sea con up-arrowo escribiendo las primeras letras y completando todo el comando, incluidos todos los argumentos (opciones y otros) con right-arrow.

Muy a menudo tengo que ejecutar el mismo comando varias veces en el mismo archivo pero con diferentes opciones. Sin embargo, al presionar up-arrowo right-arrow, completo hasta el final del comando y es más rápido escribirlo todo manualmente que regresar el cursor a las opciones, editar y luego volver a ingresar.

Básicamente, me gustaría saber si hay alguna forma de usar el autocompletado para volver a ingresar un comando del historial pero llevar el cursor de regreso a la primera opción/argumento . Alternativamente, un atajo de teclado para completar los argumentos restantes como antes después de escribir uno diferente.

p.ej

Opción 1

Escribo e ingreso:

$ command -opt1 reallyverylongindeedarg1

Presionar la flecha hacia arriba produce $ command -opt1 reallyverylongindeedarg1con mi cursor al final de la línea.

Me gustaría tener un método abreviado de teclado diferente que me permita tener el cursor en algún lugar -opt1para poder cambiarlo -differntopt2y volver a ejecutar el comando que ahora diría:

$ command -differntopt2 really.verylong.indeed.arg1

O bien, habiendo tecleado y ejecutado previamente:

$ command -opt1 really.verylong.indeed.arg1

Escribir commany luego presionar right-arrowcompleta el comando completo $ command -opt1 reallyverylongindeedarg1(nuevamente con mi cursor al final de la línea). Me encantaría saber si hay un atajo de teclado para saltar al primer argumento/opción cuando se completa automáticamente.

opcion 2

Otro método sería que escriba y $ command -differntopt2luego presione la flecha derecha para completar el argumento really.verylong.indeed.arg1como anteriormente cuando ejecuté este comando por última vez. Resultando en:

$ command -differntopt2 really.verylong.indeed.arg1

¿Qué hay de simplemente navegar con el teclado y retroceder por palabra?

Bueno, en primer lugar, eso está lejos de ser ideal ya que los argumentos tienen mucha puntuación, por lo que cada uno requiere varias (y diferentes cantidades) de pulsaciones de teclas y es lento retroceder la cantidad correcta de palabras cada vez para llegar a la opción que quiero editar.

En segundo lugar, no puedo encontrar una manera de configurar atajos de teclado normales para navegar hacia adelante y hacia atrás por palabra.

En iTerm2 he probado:

Secuencias de escape como [1;5D, [1;5C, \033b, \033f, etc.

Escribir manualmente Esc, Fy Esc, Bfunciona pero es muy lento. Ctrl + Apara ir al inicio de la línea selecciona todo. Ctrl + <-y Ctrl + ->solo producir [Dy [C.

tl; dr

  1. ¿Cómo puedo autocompletar y terminar con el cursor en el primer argumento en lugar del final de la línea?, o
  2. ¿Cómo configuro atajos de teclado para saltar hacia adelante y hacia atrás por argumento en iTerm2?
Recupere el comando, presione ⌃X⌃E, eso cargará la línea de comando en $EDITOR, le permitirá hacer lo que quiera. En cuanto a retroceder y avanzar por argumento, eso es para que lo haga su shell, no para que lo haga la terminal. Probablemente ya los tenga.

Respuestas (1)

Para ZSH otra opción es poner el cursor al principio y no al final de la línea (esto lo hace más como mkshu otros). El valor por defecto:

% PS1='%% ' zsh -f
% bindkey | grep up-line-or
"^[OA" up-line-or-history
"^[[A" up-line-or-history

Lo uso set -o vi, por lo que es posible que deba traducir las bindkeyclaves a lo que se adapte a sus necesidades:

bindkey -M vicmd "j" vi-down-line-or-history
bindkey -M vicmd "k" vi-up-line-or-history

no realmente quiero saltar al primer argumento

Esto requiere un widget personalizado, que podría ejecutar algo como

function up-line-first-arg {
    local first offset
    zle vi-up-line-or-history
    first=${BUFFER%% *}
    CURSOR+=$(( 1 + ${#first} ))
}
zle -N up-line-first-arg
autoload -U up-line-first-arg
autoload -U compinit
compinit
set -o vi
bindkey -M vicmd "k" up-line-first-arg

Esta versión colocará el cursor en el primer argumento o al final del nombre del comando (a menos que haya varios espacios entre el primer argumento y el siguiente, lo cual no es común). Docs zshexpn(1)y zshzle(1)puede ayudar a explicar los detalles, pero la esencia es moverse hacia arriba como lo hace ZSH, obtener la primera palabra (si corresponde) y mover el cursor sobre esa longitud, más uno para pasar el espacio. ZSH es inteligente, no moverá el cursor más allá del final del BUFFERcaso en el que no haya espacio en el comando.

pero espera hay mas

La siguiente versión maneja casos (quizás poco comunes) como ls -aly en caso de falla colocará el cursor al comienzo de la línea.

function up-line-first-arg {
    zle vi-up-line-or-history
    [[ $BUFFER =~ "^[^ ]+[ ]+" ]] && CURSOR+=${#MATCH}
}

Básicamente, una expresión regular "desde el comienzo del BUFFERpartido, una o más cosas que no son espacios seguidas de una o más cosas que son espacios" y luego se mueve CURSORtanto en el partido.

No quiero que esto suceda todo el tiempo, solo cuando quiero. ¿Es posible lograr esto quizás con una tecla meta o presionando otra combinación de teclas después de completar?
¿Sí? bindkeypuede vincular la mayoría de las combinaciones de teclas, no solo las que se muestran.
Si desea usar combos con la tecla de comando, puede usar iterm y bindkey como se muestra en esta respuesta: superuser.com/a/740174/1294587