Bash

在 bash vi 模式下,映射 jk 以退出插入模式

  • December 20, 2019

我正在使用帶有 bash shell 的全新安裝的 ubuntu 16.04。我想做兩件事:

  1. 設置 vi 模式,這樣我就可以從終端進行類似 vim 的動作
  2. 通過鍵入退出插入模式jk

我在另一篇文章中讀到如何zsh做到這一點,我該怎麼做bash

tl;博士

之後放入bind '"jk":vi-movement-mode'你的.bashrc文件set -o vi:)

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

請參閱@grochmal 的答案以獲得更詳細的解釋

TL; 博士

Bash 具有與zsh’s bindkeythrough類似的功能bind,但它沒有vizsh. 之後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(尤其是不被其他 shell 呼叫)。
  • .bash_profile僅在登錄 shell 上呼叫(同樣,僅 bash)。

一些發行版帶有.bash_profile如下所示的骨架:

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

這是一個很好的內容,.bash_profile因為您可以簡單地忘記它的存在。

現在,要映射j``kEscshell 會話中,這是不可能的。當你這樣做時:

inoremap jk <esc>

在 Vim 中,在你鍵入 之後j,Vim 知道它需要稍等片刻,看看你是否鍵入k下一個,它應該呼叫映射(或者你鍵入另一個鍵並且不應該觸發映射)。作為附錄,這是由:set timeoutlen=<miliseconds>Vim 控制的(請參閱 參考資料:h timeoutlen)。

一些 shell 或 X11 沒有這樣的超時控制,並且不允許多個字元映射。只允許映射單個鍵(但請參閱下面的支持說明。)。

set -o vi

不讀.vimrc,它只是模仿一些vi(甚至不是vim)可以在shell中使用的組合鍵。差不多可以這麼說-o emacs,它並沒有自帶全部威力emacs


zsh 支持

zsh實際上支持地圖超時。您可以使用以下內容映射jk<esc>

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

(那將需要~/.zshrc不去~/.bashrc

然而,我建議不要這樣做。我大部分時間都在使用vimzsh我有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 shell)

重新映射鍵的原因Esc是它位於鍵盤上很遠的地方,並且鍵入它需要時間。可以從這些emacs傢伙那裡借鑒的一個技巧是重新映射CapsLock,因為無論如何它都是無用的鍵。 emacs伙計們將其重新映射到,Ctrl但我們會將其重新映射到Esc.

讓我們xev -event keyboard來檢查一下 keycode 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是keycode 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。)

額外說明:這僅在 X11 會話中重新映射CapsLockEsc因此該映射僅適用於終端仿真器。實際tty的將看不到地圖。

參考資料和額外閱讀:

引用自:https://unix.stackexchange.com/questions/303282