W trybie bash vi mapuj jk, aby wyjść z trybu wstawiania

12

Używam świeżej instalacji Ubuntu 16.04 z powłoką bash. Są dwie rzeczy, które chcę zrobić:

  1. Ustaw tryb vi, aby móc wykonywać ruchy podobne do vima z terminala
  2. wyjdź z trybu wstawiania, pisząc jk

W innym poście przeczytałem, jak to zrobić zsh, jak to zrobić bash?

tl; dr

umieść bind '"jk":vi-movement-mode'w swoim .bashrcpliku po set -o vi:)

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

Bardziej szczegółowe wyjaśnienia znajdują się w odpowiedzi @ grochmal

Mbigras
źródło
1
Co masz na myśli przez zmianę mapowania jk? Czy to jakiś specjalny klawisz na klawiaturze?
Stephen Harris,
zobacz edycję
mbigras
Po pierwsze, .bashrcjest zwykle wywoływany przy każdej powłoce (np. Jeśli się nie wydostajesz vi), ale .bash_profilejest wywoływany tylko przy powłokach logowania. To .bashrcjest właściwe miejsce dla set -o vi. Nie mam odpowiedzi na twoje poprawione drugie pytanie :-(
Stephen Harris
Jak zaczynasz swoją powłokę bash? Oto dobre wyjaśnienie różnicy między .bashrc i .bash_profile
the_velour_fog 14.08.16
set -o viwchodzi .bashrc, zobacz Dlaczego mój ~ / .bash_profile nie działa?
Gilles „SO- przestań być zły”

Odpowiedzi:

11

TL; DR

Bash ma podobną funkcjonalność zsh„s bindkeydzięki bind, ale nie posiada kilka vitrybów, takich jak zsh. Po set -o vitym, jak możesz:

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

co jest odpowiednikiem zsh'sbindkey -M <all vi modes> jk vi-movement-mode

Te vi-movement-modefunkcje pochodzi inputrc(patrz /etc/inputrcna listy z nich).

Pełny tekst

Jak zauważa Stephen Harris w swoim komentarzu:

  • .bashrcjest wywoływany przez bashalways (a zwłaszcza nie przez inne powłoki).

  • .bash_profile jest wywoływany tylko w powłokach logowania (i ponownie, tylko bash).

Kilka dystrybucji ma .bash_profileszkielet wyglądający następująco:

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

Jest to dobra treść, .bash_profileponieważ można po prostu zapomnieć, że istnieje.

Teraz do mapy jk, aby Escw sesji powłoki, to nie jest w ogóle możliwe. Kiedy to zrobisz:

inoremap jk <esc>

W Vimie po wpisaniu jVim wie, że musi trochę poczekać, aby sprawdzić, czy piszesz kdalej, i powinien wywołać mapowanie (lub że wpiszesz inny klucz i mapowanie nie powinno zostać uruchomione). Jako dodatek jest to kontrolowane przez :set timeoutlen=<miliseconds>Vima (patrz :h timeoutlen).

Kilka powłok lub X11 nie ma takiej kontroli limitu czasu i nie pozwala na mapowanie wielu znaków. Dozwolone jest tylko mapowanie jednego klucza (ale patrz uwagi pomocy technicznej poniżej).

set -o vi

Nie czyta .vimrc, imituje tylko niektóre vi(nawet vim) kombinacje klawiszy, które mogą być użyte w powłoce. To samo można powiedzieć -o emacs, nie ma pełnej mocy emacs.


obsługa zsh

zshfaktycznie obsługuje limit czasu mapy. Możesz użyć następujących map jkdo <esc>:

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

(Trzeba będzie przejść do ~/.zshrcnie ~/.bashrc)

Jednak odradzam to. Używam vimi przez zshwiększość czasu. Mam inoremap jk <esc>w sobie vimrci próbowałem użyć bindkeypowyższej kombinacji. zshzbyt długo czeka na wydrukowanie j, a to mnie bardzo denerwuje.


wsparcie bash

bashobsługuje readline bind. Wierzę, że bashmożna to skompilować bez, readilnedlatego mogą istnieć niektóre rzadkie systemy, które mają bash, które nie obsługują bind(bądź czujny). Aby odwzorować jkaby <esc>w bashtrzeba zrobić:

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

(tak, to podwójny poziom cytowania, jest potrzebny)

Ponownie sprawia to, że pisanie jest jdość denerwujące. Ale w jakiś sposób mniej irytujące niż zshrozwiązanie na moim komputerze (prawdopodobnie domyślny limit czasu jest krótszy).


Obejście (dla powłok innych niż bash i nie-zsh)

Powodem ponownego przypisania Escklawisza jest to, że leży on dość daleko na klawiaturze, a wpisanie zajmuje trochę czasu. Sztuką, którą można pożyczyć od emacsfacetów, jest remap, CapsLockponieważ i tak jest to bezużyteczny klucz. emacschłopaki to odwzorowujemy, Ctrlale my zmienimy to Esc.

Użyjmy, xev -event keyboardaby sprawdzić kod 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

I aby sprawdzić funkcję 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

Bardzo dobrze, CapsLockma kod 66 i Escjego funkcja nazywa się „Escape”. Teraz możemy zrobić:

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

Powyższe należy wykonać w tej kolejności. Teraz za każdym razem, CapsLockgdy naciskasz , działa jak Escklucz.


Trudną częścią jest to, gdzie to ustawić. Plik ~/.Xmodmapz zawartością:

remove lock = Caps_Lock
keycode 66 = Escape

Powinny być respektowane przez większość dystrybucji (tak naprawdę menedżery wyświetlania, ale mówię o dystrybucji dla uproszczenia), ale widziałem takie, które nie szanują kilku ~/X*plików. W przypadku takich dystrybucji możesz wypróbować coś takiego:

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

W twoim .bashrc.

(Teoretycznie byłoby lepiej, ~/.xinitrcale jeśli menedżer wyświetlania nie przestrzega .Xmodmapgo, to na pewno nie uszanuje ~/.xnintrc.)

Dodatkowa uwaga: Ten remaps tylko CapsLockaby Escw sesji X11, dlatego że mapa będzie działać tylko w emulatory terminali. Rzeczywiste ttynie zobaczą mapy.

Referencje i dodatkowe lektury:

grochmal
źródło
dzięki za szczegółowe wyjaśnienie. Czy zechciałbyś zilustrować ten sam proces oprócz mapowania jkzamiast CapsLock? Mam to ustawione na mojej maszynie OSX; jednak nie mam go przez resztę weekendu i nie pamiętam, jak to zrobiłem :)
mbigras
@mbigras - Czy na pewno zrobiłeś to w bash? Bash nie ma map niejednoznacznych. Znam sposób robi to w zsh: bindkey -v; bindkey -s jk \\e. Ale to jest coś, że wróci i ugryzie cię z powrotem, kiedy trzeba jk, bo zegar nie jest konfigurowalny, a ty nie masz <leader>w zsh.
grochmal
Zdecydowanie to zrobiłem zshi nie bash, czy nie jest to możliwe w bash?
mbigras
@mbigras - Czekaj, myliłem się! Czytając man bashznalazłam bindtę pracę bardzo podobny do zsh„s bindkey. Zaktualizuję odpowiedź. Proszę bardzo, używam zshza dużo.
grochmal
2
@Jason - Hej, to jest Vi SE, tutaj wszyscy piszą słowo CAPS CAPS z: "wpisz słowo" <Esc> viwU :). Nie wymaga ukończenia
grochmal
2

Dzięki, za poprzednie odpowiedzi, używam tego w moim ~ / .zshrc dla skrótów vi w moim terminalu. Mam nadzieję, że to komuś pomoże.

bindkey -v
bindkey 'jk' vi-cmd-mode
om2c0de
źródło
Przybyłem tutaj, szukając odpowiedzi, która działa w celu powiązania klawisza „^ G”, aby przejść do „trybu normalnego” w zsh z obsługą vi, i to jest jedyna, która zadziałała.
Dalker