En mode bash vi, mappez jk pour quitter le mode insertion

11

J'utilise une nouvelle installation d'ubuntu 16.04, avec le shell bash. Il y a deux choses que je veux faire:

  1. Configurer le mode vi pour que je puisse avoir des mouvements de type vim depuis le terminal
  2. quitter le mode d'insertion en tapant jk

J'ai lu dans un autre article comment cela peut être fait zsh, comment puis-je le faire bash?

tl; dr

mettre bind '"jk":vi-movement-mode'dans votre .bashrcdossier après set -o vi:)

server@thinkpad:~$ tail -n 2 .bashrc
set -o vi
bind '"jk":vi-movement-mode'

veuillez voir la réponse de @ grochmal pour une explication plus détaillée

mbigras
la source
1
Que voulez-vous dire par remappage jk? Est-ce une touche spéciale sur votre clavier?
Stephen Harris
s'il vous plaît voir modifier
mbigras
Pour votre premier, .bashrcest généralement appelé sur chaque shell (par exemple si vous sortez de shell vi) mais .bash_profilen'est appelé que sur les shells de connexion. C'est donc .bashrcle bon endroit pour set -o vi. Je n'ai pas de réponse pour votre deuxième question révisée :-(
Stephen Harris
Comment démarrez-vous votre shell bash? Voici une bonne explication de la différence entre .bashrc et .bash_profile
the_velour_fog
set -o vientre .bashrc, voir Pourquoi mon ~ / .bash_profile ne fonctionne pas?
Gilles 'SO- arrête d'être méchant'

Réponses:

10

TL; DR

Bash a une fonctionnalité similaire à celle de zsh's bindkeythrough' bind, mais il n'a pas plusieurs vimodes comme zsh. Après set -o vivous pouvez faire:

bind '"jk":vi-movement-mode'

qui est l'équivalent de zsh« sbindkey -M <all vi modes> jk vi-movement-mode

Les vi-movement-modefonctions viennent de inputrc(voir /etc/inputrcpour une liste d'entre elles).

Texte intégral

Comme le souligne Stephen Harris dans son commentaire:

  • .bashrcest appelé par bashtoujours (et notamment pas par d'autres coques).

  • .bash_profile est uniquement appelé sur les shells de connexion (et encore, bash uniquement).

Plusieurs distributions sont livrées avec un .bash_profilesquelette qui se présente comme suit:

# ~/.bash_profile
[[ -f ~/.bashrc ]] && . ~/.bashrc

C'est un bon contenu .bash_profilecar vous pouvez simplement oublier qu'il existe.

Maintenant, à la carte jkà Escla session shell, qui est pas vraiment possible. Quand vous faites:

inoremap jk <esc>

Dans Vim, après avoir jtapé, Vim sait qu'il doit attendre un peu pour voir si vous tapez kensuite et il doit invoquer le mappage (ou que vous tapez une autre clé et le mappage ne doit pas être déclenché). En tant qu'addendum, cela est contrôlé par :set timeoutlen=<miliseconds>dans Vim (voir :h timeoutlen).

Plusieurs shell ou X11 n'ont pas un tel contrôle de timeout et ne permettent pas de mappages de caractères multiples. Seul un mappage d'une seule clé est autorisé (mais voir les notes de support ci-dessous.).

set -o vi

Ne lit pas .vimrc, il imite seulement certaines combinaisons de touches vi(pas même vim) qui peuvent être utilisées dans le shell. La même chose peut être dite -o emacs, elle ne vient pas avec toute la puissance de emacs.


support zsh

zshprend en charge le délai d'expiration de la carte. Et vous pouvez utiliser les éléments suivants pour mapper jksur <esc>:

bindkey -v  # instead of set -o vi
bindkey -e jk \\e

(Cela devra aller ~/.zshrcnon ~/.bashrc)

Pourtant, je déconseille cela. J'utilise vimet la zshplupart du temps. J'ai inoremap jk <esc>dans mon vimrcet j'ai essayé d'utiliser la bindkeycombinaison ci-dessus. zshattend trop longtemps pour imprimer jlors de son utilisation, ce qui m'a énervé beaucoup.


support bash

bashprend en charge readline bind. Je crois que cela bashpeut être compilé sans readilnedonc il peut y avoir quelques systèmes rares qui ont bash qui ne supportent pas bind(soyez vigilant). Pour la carte jkà <esc>en que bashvous devez faire:

set -o vi
bind '"jk":"\e"'

(oui c'est un double niveau de citation, c'est nécessaire)

Encore une fois, cela rend la frappe jassez ennuyeuse. Mais en quelque sorte moins ennuyeux que la zshsolution sur ma machine (le délai par défaut est probablement plus court).


Solution (pour les shells non bash et non zsh)

La raison du remappage de la Esctouche est qu'elle se trouve assez loin sur le clavier et que la saisie prend du temps. Une astuce qui peut être empruntée aux emacsgars est de remapper CapsLockcar c'est une clé inutile de toute façon. emacsles gars le remappent Ctrlmais nous le remapperons Esc.

Utilisons xev -event keyboardpour vérifier le code clé de CapsLock:

KeyPress event, serial 25, synthetic NO, window 0x1c00001,
    root 0x496, subw 0x0, time 8609026, (764,557), root:(765,576),
    state 0x0, keycode 66 (keysym 0xffe5, Caps_Lock), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

Et pour vérifier la fonction de Esc:

KeyPress event, serial 25, synthetic NO, window 0x1c00001,
    root 0x496, subw 0x0, time 9488531, (571,525), root:(572,544),
    state 0x0, keycode 9 (keysym 0xff1b, Escape), same_screen YES,
    XLookupString gives 1 bytes: (1b) "
    XmbLookupString gives 1 bytes: (1b) "
    XFilterEvent returns: False

Très bien, CapsLockc'est le keycode 66 et sa Escfonction s'appelle "Escape". Maintenant, nous pouvons faire:

# diable caps lock
xmodmap -e "remove lock = Caps_Lock"
# make an Esc key from the keycode 66
xmodmap -e "keycode 66 = Escape"

Ce qui précède doit être fait dans cet ordre. Maintenant, chaque fois que vous appuyez, CapsLockcela fonctionne comme une Escclé.


La partie délicate est de savoir où régler cela. Un fichier ~/.Xmodmapavec le contenu:

remove lock = Caps_Lock
keycode 66 = Escape

Devrait être respecté par la plupart des distributions (en fait les gestionnaires d'affichage, mais je dis les distributions pour plus de simplicité), mais j'ai vu celles qui ne respectent pas plusieurs ~/X*fichiers. Pour de telles distributions, vous pouvez essayer quelque chose comme:

if [ "x" != "x$DISPLAY" ]; then
    xmodmap -e "remove lock = Caps_Lock"
    xmodmap -e "keycode 66 = Escape"
fi

Dans votre .bashrc.

(En théorie, ce serait mieux placé, ~/.xinitrcmais si un gestionnaire d'affichage ne respecte pas, .Xmodmapil ne respectera certainement pas ~/.xnintrc.)

Note supplémentaire: Ce ne remappe CapsLockà Escune séance X11, par conséquent , la carte ne fonctionnera que dans émulateurs. Les réels ttyne verront pas la carte.

Références et lectures supplémentaires:

grochmal
la source
Merci pour l'explication détaillée. Seriez-vous prêt à illustrer le même processus, sauf pour la cartographie jkau lieu de CapsLock? Je l'ai installé sur ma machine osx; cependant, je ne l'ai pas pour le reste du week-end et je ne me souviens pas comment je l'ai fait :)
mbigras
@mbigras - Êtes-vous sûr de l'avoir fait en bash? Bash n'a pas de cartes ambiguës. Je sais d'une façon de le faire dans zsh: bindkey -v; bindkey -s jk \\e. Mais c'est quelque chose qui va revenir et vous mordre quand vous avez besoin jk, car la minuterie n'est pas configurable et vous n'avez pas <leader>dans zsh.
grochmal du
Je l'ai définitivement fait zshet non bash, n'est-ce pas possible en bash?
mbigras
@mbigras - Attendez, j'avais tort! En lisant, man bashj'ai trouvé bindce travail assez similaire à celui zshde bindkey. Je mettrai à jour la réponse. Voilà, j'en utilise zshtrop.
grochmal
2
@Jason - Hé, c'est le Vi SE, ici tout le monde écrit un mot en MAJUSCULES avec: "type mot" <Esc> viwU :). Aucun achèvement nécessaire
grochmal
2

Merci, pour les réponses précédentes, je l'utilise dans mes ~ / .zshrc pour les raccourcis de type vi dans mon terminal. J'espère que ça va aider quelqu'un.

bindkey -v
bindkey 'jk' vi-cmd-mode
om2c0de
la source
Je suis venu ici à la recherche d'une réponse qui fonctionne pour lier la touche '^ G' pour entrer en "mode normal" dans zsh activé par vi, et c'est la seule qui a fonctionné.
Dalker