In bash vi mode, mappare jk per uscire dalla modalità insert


11

Sto usando una nuova installazione di Ubuntu 16.04, con la shell bash. Ci sono due cose che voglio fare:

  1. Imposta la modalità vi in ​​modo da poter avere movimenti simili a vim dal terminale
  2. uscire dalla modalità di inserimento digitando jk

Ho letto in un altro post come è possibile farlo zsh, come posso farlo bash?

tl; dr

inserisci bind '"jk":vi-movement-mode'nel tuo .bashrcfile dopo set -o vi:)

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

per favore vedi la risposta di @ grochmal per una spiegazione più dettagliata


1
Cosa intendi rimappando jk? È un tasto speciale sulla tastiera?
Stephen Harris,

per favore vedi modifica
mbigras

Per la prima volta, in .bashrcgenere viene chiamato su ogni shell (ad esempio se si esegue il shell out vi) ma .bash_profileviene chiamato solo su shell di login. Quindi .bashrcè il posto giusto per set -o vi. Non ho una risposta per la tua seconda domanda rivista :-(
Stephen Harris,

Come stai iniziando la tua shell bash? Ecco una buona spiegazione della differenza tra .bashrc e .bash_profile
the_velour_fog

Risposte:


10

TL; DR

Bash ha una funzionalità simile a zsh's bindkeyattraverso bind, ma non avere diverse vimodalità come zsh. Dopo set -o viche puoi fare:

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

che è l'equivalente di zsh'sbindkey -M <all vi modes> jk vi-movement-mode

Le vi-movement-modefunzioni provengono da inputrc(vedi /etc/inputrcper un elenco di esse).

Testo intero

Come sottolinea Stephen Harris nel suo commento:

  • .bashrcviene chiamato da bashsempre (e in particolare non da altre shell).

  • .bash_profile viene chiamato solo sulle shell di login (e ancora, solo bash).

Diverse distribuzioni sono dotate di uno .bash_profilescheletro che ha il seguente aspetto:

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

Il che è un buon contenuto, .bash_profiledal momento che puoi semplicemente dimenticare che esiste.

Ora, per mappare jkper Escla sessione di shell, che non è davvero possibile. Quando lo fai:

inoremap jk <esc>

In Vim, dopo aver digitato j, Vim sa che è necessario attendere un po 'per vedere se si digita ksuccessivamente e dovrebbe invocare la mappatura (o che si digita un'altra chiave e la mappatura non deve essere attivata). Come addendum, questo è controllato da :set timeoutlen=<miliseconds>in Vim (vedi :h timeoutlen).

Diverse shell o X11 non dispongono di tale controllo di timeout e non consentono più mapping di caratteri. È consentita solo la mappatura di una singola chiave (ma vedi le note di supporto di seguito).

set -o vi

Non legge .vimrc, imita solo alcune combinazioni di tasti vi(nemmeno pari vim) che possono essere utilizzate nella shell. Lo stesso si può dire -o emacs, non arriva con il pieno potere di emacs.


supporto zsh

zshin realtà supporta il timeout della mappa. E puoi usare quanto segue per mappare jka <esc>:

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

(Questo dovrà andare a ~/.zshrcnon ~/.bashrc)

Tuttavia, sconsiglio. Uso vime il zshpiù delle volte. Ho inoremap jk <esc>nel mio vimrce ho provato a usare la bindkeycombinazione sopra. zshaspetta troppo tempo per stamparlo jquando lo uso, e questo mi ha infastidito molto.


bash support

bashsupporta readline bind. Credo che bashpossa essere compilato senza readilnequindi potrebbero esserci alcuni rari sistemi che hanno bash che non supportano bind(attenzione). Per mappare jka <esc>in bashquello che devi fare:

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

(sì, è un doppio livello di quotazione, è necessario)

Ancora una volta, questo rende la digitazione jabbastanza fastidiosa. Ma in qualche modo meno fastidioso della zshsoluzione sulla mia macchina (probabilmente il timeout predefinito è più breve).


Soluzione alternativa (per shell non bash e non zsh)

Il motivo per rimappare il Esctasto è che si trova abbastanza lontano sulla tastiera e digitarlo richiede tempo. Un trucco che può essere preso in prestito dai emacsragazzi è rimappare CapsLockpoiché è comunque una chiave inutile. emacsragazzi lo rimappiamo Ctrlma lo rifaremo a Esc.

Usiamo xev -event keyboardper controllare il codice chiave di 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

E per controllare la funzione di 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

Molto buono, CapsLockè il keycode 66 e Escla funzione si chiama "Escape". Ora possiamo fare:

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

Quanto sopra deve essere fatto in questo ordine. Ora ogni volta che premi CapsLockfunziona come una Escchiave.


La parte difficile è dove impostare questo. Un file ~/.Xmodmapcon il contenuto:

remove lock = Caps_Lock
keycode 66 = Escape

Dovrebbe essere rispettato dalla maggior parte delle distro (in realtà i display manager, ma sto dicendo distro per semplicità), ma ho visto quelli che non rispettano diversi ~/X*file. Per tali distro potresti provare qualcosa del tipo:

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

Nel tuo .bashrc.

(In teoria sarebbe meglio posizionarlo ~/.xinitrcma se un display manager non lo rispetta .Xmodmapsicuramente non lo rispetterà ~/.xnintrc.)

Nota Extra: Questo rimappa solamente CapsLockad Escuna sessione di X11, quindi, la mappa sarà solo lavoro in emulatori di terminale. Actual ttynon vedrà la mappa.

Riferimenti e letture extra:


Grazie per la spiegazione dettagliata. Saresti disposto a illustrare lo stesso processo ad eccezione della mappatura jkanziché CapsLock? L'ho impostato sulla mia macchina osx; tuttavia, non ce l'ho per il resto del weekend e non ricordo come ho fatto :)
mbigras

@mbigras - Sei sicuro di averlo fatto a Bash? Bash non ha mappe ambiguos. So di un modo di farlo in zsh: bindkey -v; bindkey -s jk \\e. Ma questo è qualcosa che tornerà e mordere indietro quando è necessario jk, perché il timer non è configurabile e non si hanno <leader>a zsh.
grochmal

L'ho fatto sicuramente zshe no bash, non è possibile in bash?
mbigras,

@mbigras - Aspetta, ho sbagliato! Leggendo man bashho scoperto bindche il lavoro molto simile a zsh's bindkey. Aggiornerò la risposta. Ecco qua, sto usando zshtroppo.
grochmal

2
@Jason - Ehi, questo è il SE SE, qui tutti scrivono una parola TUTTO MAIUSCOLO con: "digitare la parola" <Esc> viwU :). Nessun completamento necessario
grochmal

2

Grazie, per le risposte precedenti, lo uso nel mio ~ / .zshrc per scorciatoie simili a vi nel mio terminale. Spero che possa aiutare qualcuno.

bindkey -v
bindkey 'jk' vi-cmd-mode

Sono venuto qui alla ricerca di una risposta che funzioni per associare il tasto '^ G' per entrare in "modalità normale" in zsh abilitato per vi, e questo è l'unico che ha funzionato.
Dalker,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.