Dans bash, comment lier une touche de fonction à une commande?

91

Exemple: je veux lier la F12clé à la commande de echo "foobar"telle sorte que chaque fois que je frappe F12le message "foobar" sera imprimé à l'écran. Idéalement, il pourrait s'agir de n'importe quelle commande shell arbitraire, pas seulement de commandes internes. Comment s'y prend-on?

SiegeX
la source

Réponses:

163

Vous pouvez déterminer la séquence de caractères émise par une touche en appuyant sur Ctrl- vsur la ligne de commande, puis en appuyant sur la touche qui vous intéresse. Sur mon système pour F12, je reçois ^[[24~. Le ^[représente Esc. Différents types de terminaux ou d'émulateurs de terminaux peuvent émettre des codes différents pour la même clé.

À une invite Bash, vous pouvez entrer une commande comme celle-ci pour activer la macro clé afin que vous puissiez l'essayer.

bind '"\e[24~":"foobar"'

Maintenant, lorsque vous appuyez sur F12, vous obtenez "foobar" sur la ligne de commande prêt pour une édition ultérieure. Si vous souhaitez qu'une touche pour saisir une commande immédiatement, vous pouvez ajouter une nouvelle ligne:

bind '"\e[24~":"pwd\n"'

Maintenant, lorsque vous appuyez sur F12, vous obtenez le répertoire actuel affiché sans avoir à appuyer sur Enter. Que faire si vous avez déjà tapé quelque chose sur la ligne et que vous utilisez ce qui s'exécute automatiquement? Cela pourrait devenir compliqué. Cependant, vous pouvez effacer la ligne dans le cadre de votre macro:

bind '"\e[24~":"\C-k \C-upwd\n"'

L'espace permet de s'assurer que le Ctrl- ua quelque chose à supprimer pour empêcher la cloche de sonner.

Une fois que vous avez fait fonctionner la macro comme vous le souhaitez, vous pouvez la rendre persistante en l'ajoutant à votre ~/.inputrcfichier. Il n'y a pas besoin de la bindcommande ou de l'ensemble extérieur de guillemets simples:

"\e[24~":"\C-k \C-upwd\n"

Éditer:

Vous pouvez également créer une liaison de clé qui exécutera quelque chose sans perturber la ligne de commande actuelle.

bind -x '"\eW":"who"'

Ensuite, pendant que vous tapez une commande qui nécessite un nom d'utilisateur, par exemple, et que vous avez besoin de connaître les noms des utilisateurs qui sont connectés, vous pouvez appuyer sur Alt- Shift- Wet la sortie de whosera affichée et l'invite sera réémise avec votre commande partielle intacte et le curseur à la même position dans la ligne.

Malheureusement, cela ne fonctionne pas correctement pour les clés telles que celles F12qui produisent plus de deux caractères. Dans certains cas, cela peut être contourné.

La commande ( whodans ce cas) peut être n'importe quel exécutable - un programme, un script ou une fonction.

Suspendu jusqu'à nouvel ordre.
la source
2
Que faire si je veux ajouter une liaison à "ctrl + q"?
kubudi
5
@kubudi: bind '"\C-q": menu-complete'par exemple (ou dans votre ~/.inputrc: "\C-q": menu-complete). Vous pouvez aussi avoir besoin stty -ixondans votre ~/.bashrcpour désactiver le contrôle de flux et faire ^ S et ^ Q disponibles.
Suspendu jusqu'à nouvel ordre.
Vous dites que cela ^[représente escet ensuite vous semblez le remplacer \edans votre exemple. Pouvez-vous expliquer pourquoi s'il vous plaît?
Remover
1
@Remover: Le ^[est la représentation de sortie. C'est \eune façon de le saisir ( ^[ne fonctionne pas pour cela).
Suspendu jusqu'à nouvel ordre.
Comment puis-je lier "\ Cz"? J'aimerais obtenir quelque chose comme ce qui est décrit pour zsh sur sheerun.net/2014/03/21/how-to-boost-your-vim-productivity
pkoch
19

Vous pouvez définir les raccourcis clavier bash dans ~/.inputrc(fichier de configuration pour la bibliothèque GNU Readline). La syntaxe est

<nom de clé ou nom de clé>: macro

par exemple:

Control-o: "> output"

va créer une macro qui insère "> sortie" lorsque vous appuyez sur ControlO

 "\e[11~": "echo foobar"

va créer une macro qui insère "echo foobar" lorsque vous appuyez sur F1... Je ne sais pas à quoi F11sert le keysym .

Éditer:

.inputrccomprend la \nséquence d'échappement pour le saut de ligne, vous pouvez donc utiliser

 "\e[11~": "echo foobar\n"

Ce qui va effectivement «appuyer sur Entrée» après l'émission de la commande.

Barton Chittenden
la source
4
vous pouvez utiliser "\ n" dans une macro, pour ajouter un caractère de nouvelle ligne:
Barton Chittenden
Cela fonctionne mieux pour moi car il définit le mappage des touches à l'ouverture d'un terminal.
Heldraug
Pour Alt, utilisez \e, par exemple "\eo": "> output".
Jānis Elmeris le
Pour un didacticiel plus détaillé sur l'utilisation, .inputrcconsultez hackaday.com/2018/01/19/linux-fu-custom-bash-command-completion
Josh Habdas
1
@ArthurHenriqueDellaFraga J'ai édité la réponse; ce sera dans votre répertoire personnel. S'il n'existe pas, vous pouvez le créer.
Barton Chittenden
7

Cette solution est spécifique aux environnements X11 et n'a rien à voir avec bash, mais en ajoutant ce qui suit à vos .Xmodmaps

 % loadkeys
 keycode 88 = F12
 string F12 = "foobar"
 %

enverra la chaîne "foobar" au terminal en appuyant sur F12.

Wesley Rice
la source
Gardez à l'esprit que ce n'est pas la même chose que le shell exécutant une commande. Si vous voulez réellement exécuter une commande, vous devrez appuyer sur Entrée (ou demander à la chaîne envoyée de le faire pour vous). Vous voulez probablement aussi être sûr et effacer la ligne en premier.
Cascabel
2
Ce serait génial, mais cela ne semble pas fonctionner à partir de Fedora 20 de toute façon. J'ai même essayé d'utiliser xev pour trouver d'abord le code clé approprié pour F12 (dans mon cas, 96) et l'utiliser au lieu de 88. Aucun des deux ne fonctionne.
BobDoolittle
2

Je voulais me lier Ctrl+Bà une commande. Inspiré par une réponse ci-dessus, j'ai essayé d'utiliser bindmais je n'ai pas pu comprendre à quelle série de gribouillis cryptiques ( \e[24~?) Se traduisaient Ctrl+B.

Sur un Mac, allez dans Paramètres de l'application Terminal, Profils -> Clavier -> +puis appuyez sur le raccourci clavier que vous recherchez et il sort. Pour moi , a Ctrl+Bdonné lieu à \002laquelle je lié avec succès à la commande

bind '"\002":"echo command"'

De plus, si vous souhaitez que la commande soit exécutée immédiatement (pas simplement insérée dans l'invite), vous pouvez ajouter la touche Entrée à la fin de votre commande, comme ceci:

bind '"\002":"echo command\015"'

Peter Perháč
la source