![了解绑定映射以在 emacs 和 vi 模式之间切换](https://linux22.com/image/212940/%E4%BA%86%E8%A7%A3%E7%BB%91%E5%AE%9A%E6%98%A0%E5%B0%84%E4%BB%A5%E5%9C%A8%20emacs%20%E5%92%8C%20vi%20%E6%A8%A1%E5%BC%8F%E4%B9%8B%E9%97%B4%E5%88%87%E6%8D%A2.png)
太长了;博士
如果我在 中执行以下命令bash
,Ctrl+z似乎没有效果
bind -m vi-command '"\C-z": emacs-editing-mode'
bind -m vi-insert '"\C-z": emacs-editing-mode'
bind -m emacs-standard '"\C-z": vi-editing-mode'
而像这样愚蠢的东西却有效
bind -m vi-insert '"h": "ciaooooo"'
这个问题的由来
这并不是说我想使用这些映射,因为我一直很满意vi-editing-mode
,但我想了解我观察到的行为,主要是因为我对如何fzf
的key-bindings.bash
作品。
key-bindings.bash
定义了一堆函数,比如__fzf_select__
,__fzf_cd__
和其他,然后以各种方式将它们绑定到密钥。
现在,假设足够最近的bash
,绑定就像这样:
# Required to refresh the prompt after fzf
bind -m emacs-standard '"\er": redraw-current-line'
bind -m vi-command '"\C-z": emacs-editing-mode'
bind -m vi-insert '"\C-z": emacs-editing-mode'
bind -m emacs-standard '"\C-z": vi-editing-mode'
#if (( BASH_VERSINFO[0] < 4 )); then
# older versions of the commands in the else branch
#else
# CTRL-T - Paste the selected file path into the command line
bind -m emacs-standard -x '"\C-t": fzf-file-widget'
bind -m vi-command -x '"\C-t": fzf-file-widget'
bind -m vi-insert -x '"\C-t": fzf-file-widget'
# CTRL-R - Paste the selected command from history into the command line
bind -m emacs-standard -x '"\C-r": __fzf_history__'
bind -m vi-command -x '"\C-r": __fzf_history__'
bind -m vi-insert -x '"\C-r": __fzf_history__'
#fi
# ALT-C - cd into the selected directory
bind -m emacs-standard '"\ec": " \C-b\C-k \C-u`__fzf_cd__`\e\C-e\er\C-m\C-y\C-h\e \C-y\ey\C-x\C-x\C-d"'
bind -m vi-command '"\ec": "\C-z\ec\C-z"'
bind -m vi-insert '"\ec": "\C-z\ec\C-z"'
这里,就 和__fzf_history__
而言,在 、 、和fzf-file-widget
3 个键映射上执行相同的映射emacs-standard
。到目前为止,一切都很好。vi-command
vi-insert
然而,__fzf_cd__
故事却有所不同:
- 只
bind -m emacs-standard
在一系列疯狂的 emacs 特定击键中引用它, - 而
bind -m vi-command
/vi-insert
似乎利用Ctrl+z映射(上面代码片段的顶部)在emacs-editing-mode
和之间切换vi-editing-mode
,从而应用逻辑- 进入
emacs-editing-mode
模式 - 击中Alt+c
- 返回
vi-editing-mode
模式
- 进入
我相对确定上述分析大部分是正确的。
Ctrl但是+的映射与+的映射z定义在相同的范围内,后者利用了前者;但后者有效,而前者无效。Altc
我缺少什么?
答案1
我预计发生的情况是,当手动尝试时,“\Cz”被终端本身捕获为“挂起”字符。
因此,readline
内置函数bash
实际上从未看到该角色,因此从未执行相关操作。当“\Cz”是映射的一部分时,它不会通过终端,因此不会被拦截。
我猜这就是为什么 fzf 选择使用该特定键进行“内部”切换的原因。
为了检查这一点,您可以打开一个新终端并运行stty -a
。在该输出中,我希望您会看到susp = ^Z;
确认 Cz 字符确实是终端要查找的字符。
然后在同一个终端中,您可以运行stty susp ^X
来创建挂起字符^X
,而不是^Z
在测试C-z
您定义的映射之前切换到emacs-editing-mode
,如果我是对的,您的键绑定应该已经更改。
要点要明确:
bind -m vi-insert '"\C-z": emacs-editing-mode'
stty -a
(只是为了查看)。stty susp ^X
- 按下
C-z
并查看按键绑定是否已更改。