mbi*_*ras 15 bash keyboard-shortcuts vi
我正在使用带有 bash shell 的全新安装的 ubuntu 16.04。我想做两件事:
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'
Run Code Online (Sandbox Code Playgroud)
请参阅@grochmal 的回答以获得更详细的解释
gro*_*mal 15
Bash 具有与zsh
's bindkey
through类似的功能bind
,但它没有vi
像zsh
. 之后set -o vi
你可以:
bind '"jk":vi-movement-mode'
Run Code Online (Sandbox Code Playgroud)
这相当于zsh
'sbindkey -M <all vi modes> jk vi-movement-mode
这些vi-movement-mode
函数来自inputrc
(/etc/inputrc
有关它们的列表,请参阅)。
正如斯蒂芬哈里斯在他的评论中指出的那样:
.bashrc
由bash
always调用(特别是不被其他 shell调用)。
.bash_profile
仅在登录外壳上调用(再次,仅 bash)。
几个发行版带有一个.bash_profile
如下所示的骨架:
# ~/.bash_profile
[[ -f ~/.bashrc ]] && . ~/.bashrc
Run Code Online (Sandbox Code Playgroud)
这是一个很好的内容,.bash_profile
因为您可以简单地忘记它的存在。
现在,要映射jk到Escshell 会话中,这是不可能的。当你这样做时:
inoremap jk <esc>
Run Code Online (Sandbox Code Playgroud)
在 Vim 中,在您键入 之后j,Vim 知道它需要稍等片刻,看看您是否键入knext 并且它应该调用映射(或者您键入另一个键并且不应该触发映射)。作为附录,这由:set timeoutlen=<miliseconds>
Vim控制(请参阅 参考资料:h timeoutlen
)。
一些 shell 或 X11 没有这样的超时控制并且不允许多个字符映射。只允许映射单个键(但请参阅下面的支持说明。)。
set -o vi
Run Code Online (Sandbox Code Playgroud)
不读.vimrc
,它只模仿一些vi
(甚至不是vim
)可以在 shell 中使用的组合键。可以说是一样的-o emacs
,它并没有带着全部的力量而来emacs
。
zsh
实际上支持地图超时。您可以使用以下内容映射jk
到<esc>
:
bindkey -v # instead of set -o vi
bindkey -e jk \\e
Run Code Online (Sandbox Code Playgroud)
(那将需要去~/.zshrc
不~/.bashrc
)
然而,我建议不要这样做。我使用vim
和zsh
大部分时间。我inoremap jk <esc>
在我vimrc
和我确实尝试使用bindkey
上面的组合。 zsh
使用时等待打印太久j
,这让我很恼火。
bash
支持readline
bind
. 我相信bash
可以在没有的情况下进行编译,readilne
因此可能会有一些罕见的系统不支持bind
(注意)bash 。要映射jk
到<esc>
在bash
你需要做的:
set -o vi
bind '"jk":"\e"'
Run Code Online (Sandbox Code Playgroud)
(是的,这是双重引用,这是必需的)
同样,这使得打字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
Run Code Online (Sandbox Code Playgroud)
并检查以下功能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
Run Code Online (Sandbox Code Playgroud)
很好,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"
Run Code Online (Sandbox Code Playgroud)
以上必须按此顺序进行。现在每次你点击CapsLock它都像一把Esc钥匙。
棘手的部分是在哪里设置它。~/.Xmodmap
包含以下内容的文件:
remove lock = Caps_Lock
keycode 66 = Escape
Run Code Online (Sandbox Code Playgroud)
大多数发行版都应该尊重(实际上是显示管理器,但为了简单起见,我说的是发行版),但我看到了不尊重多个~/X*
文件的发行版。对于此类发行版,您可以尝试以下操作:
if [ "x" != "x$DISPLAY" ]; then
xmodmap -e "remove lock = Caps_Lock"
xmodmap -e "keycode 66 = Escape"
fi
Run Code Online (Sandbox Code Playgroud)
在您的.bashrc
.
(理论上这会更好,~/.xinitrc
但如果显示管理器不尊重.Xmodmap
它肯定不会尊重~/.xnintrc
。)
附加说明:本仅重映射CapsLock到Esc一个X11会话,因此地图只能在终端仿真器的工作。实际tty
的不会看到地图。
参考资料和额外阅读: