什么是 readline 的模式、键盘映射及其默认绑定?

Tom*_*ale 6 shell readline

readline的模式和键盘映射之间有什么区别?

如何找到每种模式的默认键绑定?

Tom*_*ale 9

TL; 博士

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

INPUTRC=~/dev/null bash -c 'bind -pm emacs' | grep -vE '^#|: (do-lowercase-version|self-insert)$'
Run Code Online (Sandbox Code Playgroud)

vivi-command并且vi-move同一个键盘映射。

这两个emacs-metaemacs-ctlx的子集的意见到emacs键盘映射。

如果您想了解有关vi模式和地图的更多信息,请跳至标题editing-mode vi(最后一个)。

可是等等!不过,可能需要一些背景信息:例如, anediting-mode和 a之间的区别keymap

特别有用的是emacs用于插入文本的混合键盘映射的概念,同时仍然可以轻松vi-command进行更改。

anediting-mode和 a 和有keymap什么不一样?

只有2分editing-modeS: emacs(默认)和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'.
Run Code Online (Sandbox Code Playgroud)

注意区别之间editing-modekeymap:在editing-mode vi两个(是有只有两个,请继续阅读)键盘映射和移出交换效仿的模式不同vi的编辑器。所有这些emacs同时运行editing-mode emacs(稍后解释)。

那么editing-mode实际上有什么作用呢?它只是将 shell 启动时的活动键盘映射设置为emacsor 或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.
Run Code Online (Sandbox Code Playgroud)

虽然没有记录,vi/vi-commandvi-move键盘映射也是等效的:

+ravi@boxy:~$ diff <(bind -pm vi) <(bind -pm vi-move)
+ravi@boxy:~$ 
Run Code Online (Sandbox Code Playgroud)

这给我们留下了:emacs, emacs-meta, emacs-ctlx, vi, 和vi-insert作为唯一键映射来解释。区分键映射可能最好通过检查它们来完成...

什么是键盘映射默认绑定?

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

INPUTRC=~/dev/null bash -c 'bind -pm emacs' | grep -v '^#
Run Code Online (Sandbox Code Playgroud)

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

有很多行说self-insertordo-lowercase-version不是很有用,所以要删除它们:

INPUTRC=~/dev/null bash -c 'bind -pm emacs' | grep -vE '^#|: (do-lowercase-version|self-insert)$' | sort
Run Code Online (Sandbox Code Playgroud)

各种emacs键盘映射之间有什么区别?

TL;DR:它们是对应用于editing-mode emacs.

如果您将第二个命令的输出放入名为emacs-standard, emacs-meta, emacs-ctlx, vi-command, 和vi-insert它们对应keymap的文件中,您可以发现:

有没有命令映射emacs-metaemacs-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)
$
Run Code Online (Sandbox Code Playgroud)

所以,emacs/emacs-standard是两者的行为上的功能超集emacs-ctlxemacs-meta这意味着:

keymap emacs
"\eg": glob-expand-word
"\C-x\C-r": re-read-init-file
Run Code Online (Sandbox Code Playgroud)

在功能上等同于:

keymap emacs-meta
"g": glob-expand-word

keymap emacs-ctlx
"\C-r": re-read-init-file
Run Code Online (Sandbox Code Playgroud)

您可能会争辩说第二种形式更容易阅读。

插入文本: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$
Run Code Online (Sandbox Code Playgroud)

emacs/emacs-standard基本上是vi-insert. 因此,对于输入文本,最好使用emacs-standard键盘映射vi-insert,只要您可以轻松地在emacs和之间切换vi-command

vi-insertnot inemacs-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
Run Code Online (Sandbox Code Playgroud)

这四个中的前三个与emacs绑定冲突:

"\C-d": delete-char
"\C-n": next-history
"\C-p": previous-history
Run Code Online (Sandbox Code Playgroud)

我解决如下:

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
Run Code Online (Sandbox Code Playgroud)

editing-mode vi

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

+ravi@boxy:~$ diff <(bind -pm vi) <(bind -pm vi-move)
+ravi@boxy:~$ 
Run Code Online (Sandbox Code Playgroud)

请注意,总共只有两个不同的地图,它们默认与editing-mode vi.

editing-mode vi时,keymap在使用中s为vi/ vi-command/vi-movevi-insert(起始键映射)。一次只有这两张地图中的一张处于活动状态。

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

所述vi-insert键映射允许自身被交换到称为文本操纵键映射vi-command/ vi/vi-move通过使用vi-movement-mode命令,结合到ESC默认在键vi-insert的键映射。

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

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

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

vi-command键盘映射使用标准的,单按键像abc用文字移动和互动,就像vi编辑器的默认或命令模式。一般没有Ctrl+key组合。在这种模式下不能插入文本;字母键映射到编辑/移动命令。要输入文本,请切换到vi-insert键盘映射(例如:按i“插入”)。

输入文本是使用键vi-insert映射完成的,如果您editing-mode vi.inputrc文件中有该键,则该键在 shell 启动时处于活动状态。vi-insert通过i在 in vi-command(或以许多其他方式启动到vi)时按“插入”来切换到键盘映射。

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