我想为我的终端提供类似 vim 的导航,所以我添加了:
set editing-mode vi
set keymap vi
以我的文件.inputrc
为基础。添加 vi 导航。有什么作用,为什么我需要它?editing-mode vi
keymap vi
来自man readline
(我的重点):
合法的键映射名称集是 emacs、emacs-standard、emacs-meta、emacs-ctlx、vi、vi-move、vi-command 和 vi-insert。 vi 等价于 vi 命令
因此,在您inputrc
的模式中,您可以为不同的模式指定不同的键绑定,例如,在command
模式中,您可以使用 拉取上一个命令中的最后一个参数Altp,但是此键绑定在模式中无效insert
(无论如何,在这个简单的设置中):
set editing-mode vi
set keymap vi-command
# these are for vi-command mode
"\e[A": history-search-backward
"\e[B": history-search-forward
"\ep": yank-last-arg
set keymap vi-insert
# these are for vi-insert mode
"\e[A": history-search-backward
"\e[B": history-search-forward
Control-l: clear-screen
TL;博士
如果您不想更改/添加默认键盘映射中的绑定,则不需要keymap vi
.
什么keymap vi
是声明在该点之后列出的任何绑定都适用于该键映射(与和完全相同的键映射)。vi-command
vi-move
如果您想更改插入键映射(例如,添加Ctrl-A
绑定以在您键入时转到行首),您需要在keymap vi-insert
一行下方执行此操作。
如果您想了解有关vi
模式和地图的更多信息,请跳至标题editing-mode vi
(最后一个)。
可是等等!不过,可能需要一些背景信息:例如,anediting-mode
和 a之间的区别keymap
。
特别有用的是混合emacs
键盘映射的概念,用于插入文本,同时仍然很容易vi-command
进行更改。
editing-mode
a 和 a 和有什么不一样keymap
?
只有两个editing-mode
s:(emacs
默认)和vi
.
editing-mode The editing-mode variable controls which default set of key bindings is used. By default, Readline starts up in Emacs editing mode, where the keystrokes are most similar to Emacs. This variable can be set to either `emacs' or `vi'.
editing-mode
注意和之间的区别keymap
:在editing-mode vi
这两个(是的,只有两个,请继续阅读)中,键映射被交换进出以模拟vi
编辑器的不同模式。所有这些emacs
都在同一时间运行editing-mode emacs
(稍后解释)。
那么editing-mode
实际上是做什么的呢?它只是将 shell 启动时的活动键盘映射设置为emacs
或vi-insert
。
什么是独特的键盘映射?
Acceptable keymap names are emacs, emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move, vi-command, and vi-insert. vi is equivalent to vi-command; emacs is equivalent to emacs-standard.
虽然没有记录,但vi
/vi-command
和vi-move
键映射也是等价的:
+ravi@boxy:~$ diff <(bind -pm vi) <(bind -pm vi-move)
+ravi@boxy:~$
这给我们留下了:emacs
, emacs-meta
, emacs-ctlx
, vi
, 和vi-insert
作为唯一的键映射来解释。区分键盘映射可能最好通过检查它们来完成......
什么是键盘映射默认绑定?
要查看(示例)emacs(默认)的默认键绑定,请使用:
INPUTRC=~/dev/null bash -c 'bind -pm emacs' | grep -v '^#
您可以在上面的示例中替换emacs
为任何其他键盘映射名称。
有很多行说self-insert
或do-lowercase-version
不是很有用,所以删除它们:
INPUTRC=~/dev/null bash -c 'bind -pm emacs' | grep -vE '^#|: (do-lowercase-version|self-insert)$' | sort
各种键盘映射有什么区别emacs
?
TL;DR:它们是对应用于editing-mode emacs
.
如果你将第二条命令的输出放到名为emacs-standard
, emacs-meta
, emacs-ctlx
, , 的文件中vi-command
,并vi-insert
为它们对应keymap
的 s ,你可以发现:
没有映射的命令emacs-meta
,emacs-ctlx
也没有出现在emacs-standard
:
$ comm -13 <(sed -r 's/.*: (\S+)/\1/' emacs-standard|sort) <(sed -r 's/.*: (\S+)/\1/' emacs-ctlx|sort)
$ comm -13 <(sed -r 's/.*: (\S+)/\1/' emacs-standard|sort) <(sed -r 's/.*: (\S+)/\1/' emacs-meta|sort)
$
所以emacs
/emacs-standard
是两者的行为功能超集emacs-ctlx
和emacs-meta
这意味着:
keymap emacs
"\eg": glob-expand-word
"\C-x\C-r": re-read-init-file
在功能上等同于:
keymap emacs-meta
"g": glob-expand-word
keymap emacs-ctlx
"\C-r": re-read-init-file
你可能会争辩说第二种形式更容易阅读。
插入文本:emacs
vsvi-insert
emacs-standard
not in 中有 28 个命令vi-insert
+ravi@boxy:~/lib/readline$ comm -12 vi-insert emacs-standard |wc -l
28
+ravi@boxy:~/lib/readline$
emacs
/emacs-standard
基本上是vi-insert
. 因此,对于键入文本,最好使用emacs-standard
键盘映射vi-insert
,只要您可以轻松地在和之间切换emacs
vi-command
。
vi-insert
not in中唯一的附加绑定emacs-standard
是:
+ravi@boxy:~/lib/readline$ comm -23 vi-insert emacs-standard
"\C-d": vi-eof-maybe
"\C-n": menu-complete
"\C-p": menu-complete-backward
"\e": vi-movement-mode
这四个中的前三个与emacs
绑定冲突:
"\C-d": delete-char
"\C-n": next-history
"\C-p": previous-history
我解决如下:
set keymap emacs
"\e": "kj" # see https://unix.stackexchange.com/questions/303631/how-can-i-setup-a-hybrid-readline-with-emacs-insert-mode-and-vi-command-mode
"\C-d": delete-char # eof-maybe: ^D does nothing if there is text on the line
"\C-n": menu-complete
"\C-p": menu-complete-backward
"\C-y": previous-history # historY
"\e\C-y": previous-history
editing-mode vi
正如我们在上面看到的vi
,vi-command
和vi-move
是同一个键映射:
+ravi@boxy:~$ diff <(bind -pm vi) <(bind -pm vi-move)
+ravi@boxy:~$
请注意,总共只有两个不同的地图,默认情况下与editing-mode vi
.
当 in 时editing-mode vi
,keymap
使用的 s 是vi
//vi-command
和vi-move
(vi-insert
起始键映射)。一次只有这两张地图中的一张处于活动状态。
editing-mode vi
只是在 shell 启动时设置一个默认的键盘映射,标记为vi-insert
. 同样,一次只有一个键盘映射处于活动状态。此vi-insert
键盘映射将大多数键映射到,self-insert
因此当您按下键盘上的塑料按钮时,印在其上的符号会出现在屏幕上。
vi-insert
键盘映射允许自己通过使用命令交换到称为//的文本操作键盘映射,默认vi-command
绑定vi
到键盘映射中的键。vi-move
vi-movement-mode
ESCvi-insert
实际上,即使是emacs
键盘映射也可以vi
通过使用命令将类似文本操作的键盘映射设置为活动状态vi-movement-mode
,就像上面提到的混合解决方案一样。
或者用更简单的语言...
默认情况下,当键盘映射处于活动状态时,按下ESC可更改为键盘映射。vi-command
vi-insert
键盘映射使用标准的vi-command
单个按键,如a,b和c来移动文本并与之交互,就像vi
编辑器的默认或命令模式一样。通常没有Ctrl+key组合。您不能在此模式下插入文本;字母键映射到编辑/移动命令。要输入文本,请切换到vi-insert
键盘映射(例如:按下i“插入”)。
输入文本是使用键盘映射完成的,如果你的文件中vi-insert
有,它在 shell 启动时是活动的。通过按下“插入”来切换到键盘映射(或以许多其他方式启动进入)。editing-mode vi
.inputrc
vi-insert
ivi-command
vi
除非您了解vi
编辑器,否则一开始您可能会发现vi-command
键很难使用,但如果您熟练使用它,您可以像大胡子巫师一样编辑文本。