Atajo de teclado del historial de Bash para! *

8

En Bash, hay algunos operadores útiles para repetir partes del último comando:

  • !^ se expande al primer argumento del comando anterior, por ejemplo,

    $ echo one "two three"
    one two three
    $ echo !^
    echo one
    one
    
  • !$ se expande al último argumento del comando anterior, por ejemplo,

    $ echo one "two three"
    one two three
    $ echo !$
    echo "two three"
    two three
    
  • !* se expande a todos los argumentos del comando anterior, por ejemplo,

    $ echo one "two three"
    one two three
    $ echo !*
    echo one "two three"
    one two three
    

(Según tengo entendido, estos son azúcar sintáctica para !!:^, !!:$y !!:*respectivamente, donde !!hay un designador de eventos que se expande al comando anterior y ^, $y *son designadores de palabras, consulte el Manual de referencia de Bash o man bash.)

Estos son a menudo bastante útiles. Pero se vuelve aún más genial con los atajos de teclado:

  • Cuando presiona Alt+ .o Alt+ _, el último argumento del comando anterior se inserta en el comando actual, de manera similar como si hubiera escrito !$en ese punto.

  • También es posible presionar Alt+ Ctrl+ ypara insertar el primer argumento del comando anterior, como si hubiera escrito !^en ese punto.

(Consulte la Biblioteca de línea de lectura de GNU o info readline.)

Tiendo a preferir los atajos de teclado sobre los operadores de historia de Bash, porque puedo ver lo que estoy insertando antes de ejecutar el comando. Sin embargo, no parece haber un atajo que me permita insertar todas las palabras del comando anterior, es decir, uno que !*funcione. Al menos no pude encontrarlo.

¿Hay tal atajo? Si no, ¿es posible configurar la biblioteca readline para agregar una, y cómo?

Malte Skoruppa
fuente
AFAIK, los atajos de teclado son manejados por el emulador de terminal. ¿Entonces supongo que estás usando gnome-terminal?
Seth
1
En zsh, si escribe echo !*y luego presiona TAB, tiene el efecto deseado. En general, TAB mientras está en readline expandirá todos los expandibles. Muy útil; probablemente bash tendrá alguna configuración para el mismo efecto? @Seth, creo que esta es la línea de lectura en bash, no el emulador de terminal, aunque no estoy seguro.
Rmano
2
@Seth No, los accesos directos de la Q son manejados por bash. Puede buscar 'Comandos para manipular la historia' en man bash( en algún lugar de la línea 3030)
Radu Rădeanu
@ RaduRădeanu ¡Oh, interesante! No lo sabia. Mi mal por malas suposiciones.
Seth
1
\e.y \e_se asignan a la función readline yank-last-argy \e\C-yse asignan a yank-nth-arg. Lamentablemente, parece que no hay un comando (único) que agregue múltiples argumentos anteriores a la vez.
Adaephon

Respuestas:

5

Si nos fijamos en la salida del siguiente comando:

bind -l

o mejor para:

bind -l | grep arg

puede ver que no existe ninguna función de línea de lectura para todos los argumentos como es, por ejemplo, yank-last-argpara el último argumento, que puede insertar el último argumento en el comando anterior (la última palabra de la entrada del historial anterior). Entonces, si tal función no existe, lo más probable es que no exista un acceso directo para lograr lo que desea.

Tratemos de preparar una aproximada a su solicitud ...

Primero, mira por ejemplo la salida del siguiente comando:

bind -p | grep yank-nth-arg

El resultado es:

"\e\C-y": yank-nth-arg

y se puede traducir de la siguiente manera: yank-nth-arg(que inserta el primer argumento del comando anterior; con un argumento n, inserte el enésimo argumento del comando anterior) está vinculado a Alt+ Ctrl+ y.

Del mismo modo se puede interpretar cualquier línea desde la salida del bind -pcomando.

Ahora preste atención a los siguientes escenarios:

  • Si establece el siguiente enlace:

    bind '"\ea": "\e2\e."'

    Alt+ Ase asignará a Alt+ 2Alt+ .que se asigna para insertar el segundo argumento del comando anterior. Entonces, después de presionar Alt+ A, el segundo argumento del comando anterior se inserta en el comando actual.

  • Si configura:

    bind '"\ea": "\e1\e. \e2\e."'

    Después de presionar Alt+ A, se insertan los dos primeros argumentos del comando anterior en el comando actual. Si el número de argumentos del comando anterior es máximo 2, por supuesto, todo el comando anterior se inserta en el comando actual.

  • Si configura:

    bind '"\ea": "\e1\e. \e2\e. \e3\e."'

    Luego, cuando presiona Alt+ A, los primeros tres argumentos del comando anterior se insertan en el comando actual. Si el número de argumentos del comando anterior es máximo 3 (como en su caso), por supuesto, todo el comando anterior se inserta en el comando actual.

  • Y así.

Para los primeros 10 argumentos, puede usar:

bind '"\ea": "\e1\e. \e2\e. \e3\e. \e4\e. \e5\e. \e6\e. \e7\e. \e8\e. \e9\e. \e1\e0\e."'

Y creo que esto es lo suficientemente largo en la medida en que no uso comandos con demasiada frecuencia con tantos argumentos.

Para hacerlo persistente, agregue la siguiente línea a su ~/.inputrcarchivo:

"\ea": "\e1\e. \e2\e. \e3\e. \e4\e. \e5\e. \e6\e. \e7\e. \e8\e. \e9\e. \e1\e0\e."

En este ejemplo, elegí Alt+ Apara insertar todos los argumentos (si el número de argumentos no es mayor que 10) del comando anterior, pero puede elegir cualquier otra combinación con la que reemplace en el comando anterior la \eacadena.

Recursos:

Radu Rădeanu
fuente
Bueno, es algo hack, y solo funcionará para un número limitado de argumentos, pero parece ser lo más cercano que podemos llegar fácilmente, lo tomaré;) En realidad, acabo de echar un vistazo al código fuente de readline. A primera vista, parece que en el archivo funmap.c, la función yank-nth-argse asigna a la función C rl_yank_nth_arg, que a su vez se define en kill.c. Análogamente para yank-last-arg. Por supuesto, sería posible extender readline con tal funcionalidad, pero no quiero hacer eso; Prefiero que mi línea de lectura sea administrada apt, y esta característica no es tan importante;)
Malte Skoruppa