У режимі bash vi, карта jk, щоб вийти з режиму вставки


12

Я використовую свіжу установку ubuntu 16.04, з оболонкою bash. Я хочу зробити дві речі:

  1. Налаштуйте режим vi, щоб я міг рухатись з терміналу, що нагадує vim
  2. вихід в режим вставки, ввівши jk

Я читав в іншому дописі, як це можна зробити zsh, як це зробити bash?

тл; д-р

помістити bind '"jk":vi-movement-mode'у свій .bashrcфайл після set -o vi:)

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

див. відповідь @ grochmal для більш детального пояснення


1
Що ви маєте на увазі під перестановкою jk? Це якась спеціальна клавіша на вашій клавіатурі?
Стівен Гарріс

дивіться, будь ласка, редагувати
mbigras

По-перше, .bashrcтипово викликається в кожній оболонці (наприклад, якщо ви працюєте з оболонки vi), але .bash_profileвикликається лише в оболонках для входу. Тож .bashrcправильне місце для set -o vi. У мене немає відповіді на ваше переглянуте 2-е питання :-(
Стівен Харріс

Як ви починаєте свою башму? Ось гарне пояснення різниці між .bashrc та .bash_profile
the_velour_fog

Відповіді:


11

TL; DR

Bash має функціонал, подібний до zsh" bindkeyчерез" bind, але він не має декількох viрежимів, як zsh. Після set -o viтого як ви можете зробити:

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

що еквівалент zsh'sbindkey -M <all vi modes> jk vi-movement-mode

У vi-movement-modeфункції походить від inputrc(див /etc/inputrcдля списку з них).

Повний текст

Як зазначає Стівен Гарріс у своєму коментарі:

  • .bashrcназивається bashзавжди (і особливо не іншими оболонками).

  • .bash_profile викликається тільки на оболонках входу (і знову ж таки, лише на башти).

Кілька дистрибутивів оснащені .bash_profileскелетом, який виглядає так:

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

Це хороший зміст, .bash_profileоскільки ви можете просто забути, що він існує.

Тепер, щоб зробити карту jkна Escсеанс оболонки, це насправді неможливо. Коли ви робите:

inoremap jk <esc>

У Vim, після введення j, Vim знає, що потрібно трохи почекати, щоб побачити, чи ви введете kнаступне, і воно повинно викликати відображення (або що ви введете інший ключ, і відображення не повинно бути запущеним). Як додаток це контролюється :set timeoutlen=<miliseconds>у Vim (див. :h timeoutlen).

Кілька оболонок або X11 не мають такого контролю часу та не дозволяють проводити кілька відображень символів. Допускається лише відображення одного ключа (Але дивіться примітки про підтримку нижче).

set -o vi

Не читає .vimrc, він лише імітує деякі vi(навіть не vim) комбінації клавіш, які можна використовувати в оболонці. Те саме можна сказати і про те -o emacs, що воно не йде з повною силою emacs.


підтримка zsh

zshнасправді підтримує тайм-аут карти. І ви можете використовувати наступну команду, щоб відобразити jkна <esc>:

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

(На це потрібно піти ~/.zshrcне ~/.bashrc)

Але я раджу проти цього. Я використовую vimі zshбільшу частину часу. У мене inoremap jk <esc>на мою , vimrcі я намагаюся , використовуючи bindkeyкомбінацію вище. zshзанадто довго чекає друку jпри його використанні, і це мене дуже дратувало.


підтримка bash

bashопори readline bind. Я вважаю, що це bashможна скласти без цього, readilneтому можуть бути деякі рідкісні системи, які мають баш, які не підтримують bind(будьте уважні). Для зіставлення jkз <esc>в bashвам потрібно зробити:

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

(так, це подвійний рівень цитування, це потрібно)

Знову ж таки, це робить набриднення jдосить дратівливим. Але якось менш дратівливо, ніж zshрішення на моїй машині (можливо, час затримки за замовчуванням коротший).


Обхід (для не-баш і не-зш-снарядів)

Причина повторного перезаключення Escклавіші полягає в тому, що він лежить досить далеко на клавіатурі, а для введення тексту потрібен час. Трюк, який можна запозичити у emacsхлопців, - це перезапис, CapsLockоскільки це все одно марний ключ. emacsхлопці, перезавантажте його, Ctrlале ми перезавантажимо його Esc.

Давайте скористаємося, xev -event keyboardщоб перевірити код коду 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

І перевірити функцію 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

Дуже добре, CapsLockє клавішний код 66, а Escфункція 'називається "Втеча". Тепер ми можемо зробити:

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

Сказане повинно бути зроблено в цьому порядку. Тепер кожен раз, коли ви натискаєте, CapsLockце працює як Escключ.


Хитра частина - де це встановити. Файл ~/.Xmodmapіз вмістом:

remove lock = Caps_Lock
keycode 66 = Escape

Слід поважати більшість дистрибутивів (насправді менеджери дисплеїв, але я кажу, що дистрибутив для простоти), але я побачив такі, які не поважають декілька ~/X*файлів. Для таких дистрибутивів ви можете спробувати щось на кшталт:

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

У вашому .bashrc.

(Теоретично це було б краще, ~/.xinitrcале якщо диспетчер дисплеїв не поважає, .Xmodmapвін точно не поважатиметься ~/.xnintrc.)

Додаткова примітка: Це тільки перерозподіляє , CapsLockщоб Escв сеансі X11, тому карта буде працювати тільки в емуляторах терміналу. Фактичні особи ttyне побачать карту.

Список літератури та додаткове читання:


дякую за детальне пояснення. Чи готові ви проілюструвати той самий процес, за винятком картографування, jkа не CapsLock? У мене він встановлений на моїй машині osx; однак у мене немає решти вихідних, і я не можу згадати, як я це зробив :)
mbigras

@mbigras - Ви впевнені, що зробили це в башті? Баш не має двозначних карт. Я знаю спосіб зробити це в zsh: bindkey -v; bindkey -s jk \\e. Але це те, що повернеться і відкусить вас назад, коли вам потрібно jk, тому що таймер не налаштований і у вас немає <leader>входу zsh.
грочмал

Я, безумовно, робив це в zshні bash, чи не можливо в баш?
mbigras

@mbigras - Зачекайте, я помилився! Читаючи, man bashя виявив, bindщо робота досить схожа на zsh's bindkey. Я оновлю відповідь. Там ви йдете, я zshзанадто багато використовую.
грохмаль

2
@Jason - Гей, це Vi SE, тут всі пишуть ВСЕ слово CAPS з: "type type" <Esc> viwU :). Не потрібно завершення
grochmal

2

Дякую, за попередні відповіді я використовую це у своєму ~ / .zshrc для vi-подібних ярликів у своєму терміналі. Я сподіваюся, що це комусь допоможе.

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

Я прийшов сюди, шукаючи відповідь, яка працює для прив’язки клавіші '^ G' для входу в "нормальний режим" в режимі zsh з підтримкою vi, і це єдиний, хто працював.
Далкер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.