В режиме bash vi отобразите jk для выхода из режима вставки

11

Я использую свежую установку 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 для более подробного объяснения

mbigras
источник
1
Что вы подразумеваете под переназначением jk? Это какая-то специальная клавиша на клавиатуре?
Стивен Харрис
см. редактирование
mbigras
Во-первых, .bashrcобычно вызывается в каждой оболочке (например, если вы используете оболочку vi), но .bash_profileвызывается только в оболочках входа в систему. Так .bashrcчто это правильное место для set -o vi. У меня нет ответа на ваш исправленный 2-й вопрос :-(
Стивен Харрис
Как вы начинаете свою оболочку Bash? Вот хорошее объяснение разницы между .bashrc и .bash_profile
the_velour_fog
set -o viЗаходите .bashrc, посмотрите, почему мой ~ / .bash_profile не работает?
Жиль "ТАК - перестань быть злым"

Ответы:

10

TL; DR

Bash имеет такую же функциональность, zsh«S 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).

Несколько дистрибутивов поставляются со .bash_profileскелетом, который выглядит следующим образом:

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

Это хороший контент, .bash_profileпотому что вы можете просто забыть о его существовании.

Теперь на карту , jkчтобы Escв сессии оболочки, которая на самом деле не возможно. Когда вы делаете:

inoremap jk <esc>

В Vim после ввода jVim знает, что ему нужно немного подождать, чтобы увидеть, печатаете ли вы 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поэтому могут быть некоторые редкие системы, которые имеют bash, которые не поддерживают bind(будьте внимательны). Для сопоставления jkс <esc>в bashвам нужно сделать:

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

(да, это двойной уровень цитирования, это необходимо)

Опять же, это делает набор текста jдовольно раздражающим. Но как-то менее раздражает, чем zshрешение на моей машине (вероятно, время ожидания по умолчанию короче).


Обходной путь (для оболочек не bash и не 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функция называется «Escape». Теперь мы можем сделать:

# 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не увидят карту.

Рекомендации и дополнительное чтение:

grochmal
источник
спасибо за подробное объяснение. Хотели бы вы проиллюстрировать тот же процесс, кроме картирования jkвместо CapsLock? Я установил его на моей машине OSX; однако, у меня нет этого до конца выходных, и я не могу вспомнить, как я это сделал :)
mbigras
@mbigras - Ты уверен, что сделал это в bash? Bash не имеет двусмысленных карт. Я знаю способ сделать это в zsh: bindkey -v; bindkey -s jk \\e. Но это то , что вернется и укусит вас обратно , когда вам нужно jk, потому что таймер не настраивается и у вас нет <leader>в zsh.
горький
Я определенно сделал это в zshи нет bash, это не возможно в Bash?
Мбиграс
@mbigras - Подожди, я ошибся! Читая, man bashя обнаружил, bindчто эта работа очень похожа на zshроссийскую bindkey. Я обновлю ответ. Вот, пожалуйста, я использую zshслишком много.
Грохмал
2
@Jason - Эй, это Vi SE, здесь каждый пишет слово ALL CAPS с помощью: «type word» <Esc> viwU :). Завершение не требуется
grochmal
2

Спасибо за предыдущие ответы, я использую это в моем ~ / .zshrc для vi-подобных ярлыков в моем терминале. Надеюсь, это кому-нибудь поможет.

bindkey -v
bindkey 'jk' vi-cmd-mode
om2c0de
источник
Я пришел сюда в поисках ответа, который работает для привязки клавиши '^ G' для входа в "обычный режим" в zsh с поддержкой vi, и это единственный, который сработал.
Далкер