readline:vi、vi-move、vi-command、vi-insert 键盘映射之间的区别

readline:vi、vi-move、vi-command、vi-insert 键盘映射之间的区别

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-modean和 a有什么区别keymap

仅有的两个editing-modeemacs(默认) 和vi

GNU Readline 库文档说:

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 启动时将活动键映射设置为emacsvi-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-commandvi-move键盘映射也是等效的:

+ravi@boxy:~$ diff <(bind -pm vi) <(bind -pm vi-move)
+ravi@boxy:~$ 

这给我们留下了:emacsemacs-metaemacs-ctlxvivi-insert作为独特的键盘映射来解释。区分键盘映射的最好方法是检查它们...

键盘映射的默认绑定有哪些?

要查看(例如)emacs(默认)的默认键绑定,请使用:

INPUTRC=~/dev/null bash -c 'bind -pm emacs' | grep -v '^#

您可以emacs用上面示例中的任何其他键映射名称进行替换。

有很多行说self-insertdo-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-metaemacs-ctlx、和的文件中vi-commandvi-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-ctlxemacs-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

您可能会认为第二种形式更易于阅读。

插入文本:emacsvsvi-insert

emacs-standardnot 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-insertemacs轻松切换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

正如我们上面看到的vivi-commandvi-move同一个键盘映射:

+ravi@boxy:~$ diff <(bind -pm vi) <(bind -pm vi-move)
+ravi@boxy:~$ 

请注意,总共只有默认情况下与之关联的不同地图editing-mode vi

在 中editing-mode vikeymap使用的 s 是vi/ vi-command/vi-movevi-insert(起始键映射)。这两个映射中只有一个处于活动状态。

editing-mode vi所做的只是在 shell 启动时设置一个默认的键映射,标记为vi-insert。同样,一次只有一个键映射处于活动状态。此vi-insert键映射将大多数键映射到 ,self-insert因此当您按下键盘上的塑料按钮时,屏幕上将显示其上印刷的符号。

键盘映射允许使用命令将其自身交换为名为//的vi-insert文本操作键盘映射,该命令默认绑定到键盘映射中的键。vi-commandvivi-movevi-movement-modeESCvi-insert

实际上,即使是emacs键盘映射也可以vi通过使用命令来将类似的文本操作键盘映射设置为活动状态vi-movement-mode,就像上面提到的混合解决方案一样。

或者用更简单的语言...

默认情况下,当键盘映射处于活动状态时,按下ESC即可更改为键盘映射。vi-commandvi-insert

键盘vi-command映射使用标准的单个按键(如 、 和abc移动和与文本交互,就像vi编辑器的默认模式或命令模式一样。通常没有Ctrl+key组合。您无法在此模式下插入文本;字母键映射到编辑/移动命令。要输入文本,请切换到键盘映射vi-insert(例如:按i表示“插入”)。

使用键盘映射输入文本,如果文件中vi-insert有,则在 shell 启动时键盘映射处于活动状态。在中按“insert”可切换到键盘映射(对于已启动 的用户,可以使用许多其他方法)。editing-mode vi.inputrcvi-insertivi-commandvi

除非您了解vi编辑器,否则一开始您可能会发现vi-command按键很难使用,但如果您熟练掌握它,您就可以像长胡子的巫师一样编辑文本。

相关内容