Raccourci clavier de l'historique Bash pour! *

8

Dans Bash, il existe des opérateurs pratiques pour répéter des parties de la dernière commande:

  • !^ se développe au premier argument de la commande précédente, par exemple,

    $ echo one "two three"
    one two three
    $ echo !^
    echo one
    one
  • !$ se développe jusqu'au dernier argument de la commande précédente, par exemple,

    $ echo one "two three"
    one two three
    $ echo !$
    echo "two three"
    two three
  • !* se développe à tous les arguments de la commande précédente, par exemple,

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

(Pour autant que je sache, ce sont du sucre syntaxique pour !!:^, !!:$et !!:*respectivement, où se !!trouve un désignateur d'événement qui se développe à la commande précédente, et ^, $et *sont des désignateurs de mots, voir le manuel de référence Bash ou man bash.)

Ce sont souvent très pratiques. Mais cela devient encore plus cool avec des raccourcis clavier:

  • Lorsque vous appuyez sur Alt+ .ou Alt+ _, le dernier argument de la commande précédente est inséré dans la commande actuelle, de la même manière que si vous aviez écrit !$à ce stade.

  • Il est également possible d'appuyer sur Alt+ Ctrl+ ypour insérer le premier argument de la commande précédente, comme si vous l'aviez écrit !^à ce moment-là.

(Voir la bibliothèque GNU Readline ou info readline.)

J'ai tendance à préférer les raccourcis clavier aux opérateurs d'historique de Bash, car je peux voir ce que j'insère avant d'exécuter la commande. Cependant, il ne semble pas y avoir de raccourci qui me permette d'insérer tous les mots de la commande précédente, c'est-à-dire celui qui fait !*l'affaire. Au moins, je ne pouvais pas le trouver.

Existe-t-il un tel raccourci? Sinon, est-il possible de configurer la bibliothèque readline pour en ajouter une, et comment?

Malte Skoruppa
la source
AFAIK, les raccourcis clavier sont gérés par l'émulateur de terminal. Donc je suppose que vous utilisez gnome-terminal?
Seth
1
Dans zsh, si vous tapez echo !*et appuyez sur TAB, vous obtenez l'effet souhaité. En général, TAB en ligne de lecture étendra tous les éléments extensibles. Très utile; bash aura probablement une configuration au même effet? @Seth, je pense que c'est la ligne de lecture dans bash, pas l'émulateur de terminal - pas sûr cependant.
Rmano
2
@Seth Non, les raccourcis du Q sont gérés par bash. Vous pouvez rechercher des «Commandes pour manipuler l'histoire» dans man bash(quelque part sur la ligne 3030)
Radu Rădeanu
@ RaduRădeanu Oh intéressant! Je ne le savais pas. Mon mauvais pour de mauvaises hypothèses.
Seth
1
\e.et \e_sont mappés à la fonction readline yank-last-arget \e\C-ysont mappés à yank-nth-arg. Malheureusement, il ne semble pas y avoir de commande (unique) qui ajoute plusieurs arguments précédents à la fois.
Adaephon

Réponses:

5

Si vous regardez la sortie de la commande suivante:

bind -l

ou mieux pour:

bind -l | grep arg

vous pouvez voir qu'il n'existe aucune fonction de ligne de lecture pour tous les arguments comme l'est, par exemple, yank-last-argpour le dernier argument - qui peut insérer le dernier argument à la commande précédente (le dernier mot de l'entrée d'historique précédente). Donc, si une telle fonction n'existe pas, il n'existe probablement pas de raccourci pour accomplir ce que vous souhaitez.

Essayons de créer une approche à votre demande ...

Tout d'abord, regardez par exemple la sortie de la commande suivante:

bind -p | grep yank-nth-arg

La sortie est:

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

et peut être traduit comme suit: yank-nth-arg(qui insère le premier argument de la commande précédente - avec un argument n, insère le nième argument de la commande précédente) est lié à Alt+ Ctrl+ y.

De la même manière peut être interprétée n'importe quelle ligne de la sortie de la bind -pcommande.

Faites maintenant attention aux scénarios suivants:

  • Si vous définissez la liaison suivante:

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

    Alt+ Asera mappé sur Alt+ 2Alt+ .qui est mappé pour insérer le deuxième argument de la commande précédente. Ainsi, après avoir appuyé sur Alt+ A, le deuxième argument de la commande précédente est inséré dans la commande actuelle.

  • Si vous définissez:

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

    Après avoir appuyé sur Alt+ A, les deux premiers arguments de la commande précédente sont insérés dans la commande actuelle. Si le nombre d'arguments de la commande précédente est au maximum 2, bien sûr, toute la commande précédente est insérée dans la commande actuelle.

  • Si vous définissez:

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

    Après avoir appuyé sur Alt+ A, les trois premiers arguments de la commande précédente sont insérés dans la commande actuelle. Si le nombre d'arguments de la commande précédente est au maximum de 3 (comme dans votre cas), bien sûr, toute la commande précédente est insérée dans la commande actuelle.

  • Etc.

Pour les 10 premiers arguments, vous pouvez utiliser:

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

Et je pense que c'est assez long dans la mesure où je n'utilise pas trop souvent des commandes avec autant d'arguments.

Pour le rendre persistant, ajoutez la ligne suivante à votre ~/.inputrcfichier:

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

Dans cet exemple, j'ai choisi Alt+ Apour insérer tous les arguments (si le nombre d'arguments n'est pas supérieur à 10) de la commande précédente, mais vous pouvez choisir n'importe quelle autre combinaison avec en remplaçant dans la commande précédente la \eachaîne.

Ressources:

Radu Rădeanu
la source
Eh bien, c'est un peu hack, et cela ne fonctionnera que pour un nombre limité d'arguments, mais il semble que ce soit le plus proche que nous pouvons facilement obtenir - je le prends;) En fait, je viens de jeter un œil au code source de readline. À première vue, il ressemble au fichier funmap.c, la fonction yank-nth-argest mappée à la fonction C rl_yank_nth_arg, qui à son tour est définie dans kill.c. Analogiquement pour yank-last-arg. Bien sûr, il serait possible d'étendre readline avec une telle fonctionnalité, mais je ne veux pas le faire; Je préfère que ma ligne de lecture soit gérée par apt, et cette fonctionnalité n'est pas si importante;)
Malte Skoruppa