readline(3) 手册页列出了这四个(vi、vi-move、vi-command、vi-insert)作为设置的可能选项keymap
。我尝试设置这些不同的选项,但它们似乎没有产生任何效果set editing-mode vi
。
回答这个问题最简洁的方法可能是举一个例子来说明改变keymap
会带来什么不同。
引用自手册页:
keymap (emacs)
Set the current readline keymap. The set of legal keymap names
is emacs, emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,
vi-command, and vi-insert. vi is equivalent to vi-command;
<<snip>>
答案1
它们是 vi 模式中的不同键映射。例如,我的.inputrc
设置keymap
为在不同模式下绑定键。摘录:
# insert mode bindings
set keymap vi-insert
"\C-p": previous-history
"\C-n": next-history
# command mode bindings
set keymap vi-command
"|": beginning-of-line
"_": vi-first-print
答案2
总结
如果您想要了解要点,请跳至标题editing-mode vi
(最后一个)。
但请稍等!不过,可能需要一些背景信息:例如, anediting-mode
和 a之间的区别keymap
。
混合键映射的概念特别有用,它emacs
用于插入文本,同时仍可轻松进行vi-command
更改。
editing-mode
an和 a有什么区别keymap
?
有仅有的两个editing-mode
: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
文件,你会发现:
中没有映射任何命令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
不在的附加绑定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
。
在 中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 启动时键盘映射处于活动状态。在中按“insert”可切换到键盘映射(对于已启动 的用户,可以使用许多其他方法)。editing-mode vi
.inputrc
vi-insert
ivi-command
vi
除非您了解vi
编辑器,否则一开始您可能会发现vi-command
按键很难使用,但如果您熟练掌握它,您就可以像长胡子的巫师一样编辑文本。