我真的很喜欢 zsh 的整体速度,但有两件事让我很烦。
- 我必须在按下 Esc 键和按下斜线键之间等待片刻才能进入历史记录搜索(如果按下斜线键太快,则会显示
zsh: do you wish to see all 514 possibilities (172 lines)
) - 由于点击
a
或进入插入模式后A
,我无法退格进入插入模式的位置。
我知道 2 就像经典的 vi,但我更喜欢 vim 风格。
答案1
(1). 出于某种原因,bindkey 在遇到“/”时会表现得很奇怪:<esc>
紧接着的/
被解释为<esc-/>
。(前几天我观察到了这种行为;不太确定是什么原因造成的。)我不知道这是一个错误还是一个功能,如果是一个功能,是否可以禁用它,但你可以相当轻松地解决这个问题。
此组合键可能与 绑定_history-complete-older
,从而产生不良结果——您可以使用bindkey -L
来查看是否是这种情况。
无论如何,如果你不介意牺牲实际的 <esc-/>
(按下在一起,作为和弦)绑定,您可以将其重新绑定到 vi 模式历史搜索命令,以便键入<esc>
后跟/
在任何打字速度下都会执行相同的操作。=)
由于这将被视为和弦,因此它不会产生首先进入 vi 命令模式的效果,因此我们必须确保首先发生这种情况。首先,您需要定义一个函数;fpath
如果您使用它,请将其放在您的某个位置,否则将其放在您的 .zshrc 中:
vi-search-fix() {
zle vi-cmd-mode
zle .vi-history-search-backward
}
其余内容以任意方式放入你的 .zshrc 中:
autoload vi-search-fix
zle -N vi-search-fix
bindkey -M viins '\e/' vi-search-fix
應該可以去。
(2). 可以按如下方法修复退格键:
`bindkey "^?" backward-delete-char`
此外,如果您希望其他 vi 样式命令有类似的行为:
bindkey "^W" backward-kill-word
bindkey "^H" backward-delete-char # Control-h also deletes the previous char
bindkey "^U" backward-kill-line
答案2
我仅要回答问题(1)。
您的问题是 KEYTIMEOUT。我引用 zshzle(1) 的话:
当 ZLE 从终端读取命令时,它可能会读取与某个命令绑定的序列,该序列也是更长的绑定字符串的前缀。在这种情况下,ZLE 将等待一段时间以查看是否输入了更多字符,如果没有(或者它们与任何更长的字符串不匹配),它将执行绑定。此超时由 KEYTIMEOUT 参数定义;其默认值为 0.4 秒。如果前缀字符串本身未绑定到命令,则没有超时。
0.4 秒是按下 ESC 后遇到的延迟。解决方法是在其中一个 shell 启动文件中将 KEYTIMEOUT 设置为 0.01 秒:
export KEYTIMEOUT=1
不幸的是,这会产生连锁反应:其他事情开始出错……
首先,vi 命令模式现在存在一个问题:输入 ESC 会导致光标挂起,然后您接下来输入的任何字符都会被吞掉。这是因为在 vi 命令模式下,ESC 默认不与任何内容绑定,但存在以 ESC(光标键!)开头的多字符小部件。因此,当您按下 ESC 时,ZLE 会等待下一个字符……然后吞掉它。
修复方法是将 ESC 绑定到某物在命令模式下,从而确保某物在 $KEYTIMEOUT 厘秒后传递给 ZLE。现在我们可以在命令模式下保持从 ESC 开始的绑定,而不会产生这些不良影响。我将 ESC 绑定到铃声字符,我发现这比自插入更不具侵入性(并且我的 shell 被静音了):
bindkey -sM vicmd '^[' '^G'
2017年更新:
后来我找到了一个更好的绑定 ESC 的解决方案 —
undefined-key
小部件。我不确定当我最初写这个答案时这个小部件是否在 zsh 中可用。
bindkey -M vicmd '^[' undefined-key
下一个问题:默认情况下,vi 插入模式下的一些双键小部件从 ^X 开始;如果将 $KEYTIMEOUT 一直设置到最低,这些小部件将无法使用。我所做的是在 vi 插入模式下解除 ^X 的绑定(默认情况下它是自插入的);这允许这些双键小部件继续工作。
bindkey -rM viins '^X'
您失去了自我插入的绑定,但您当然可以将其绑定到其他东西。(我不会这样做,因为我用不着它。)
最后一个问题(到目前为止我发现的):由于设置了 $KEYTIMEOUT,我们“丢失”了一些剩余的默认键绑定,即:在 vi 插入模式下以 ESC 开头的键绑定不是光标键。我个人将它们重新绑定为以 ^X 开头:
bindkey -M viins '^X,' _history-complete-newer \
'^X/' _history-complete-older \
'^X`' _bash_complete-word
2018年更新:
事实证明,上面的整个部分(“更新 2017”之后)不是必需的。可以使用以下方法在键盘映射中将 META 键设置为等同于 ESC:
bindkey -mv
因此有可能不是解除绑定 ^X,并通过按 META 作为引导键(现代键盘上为 ALT 或 OPT)来访问以 ESC 开头的键绑定。
如果你有权阅读本书从 Bash 到 Z Shell由 Kiddle 等人撰写,在第 4 章第 78-79 页的边栏中讨论了键绑定中 ESC 和 META 的等效性。
答案3
我选择重新执行历史补全以消除冲突。compinit
绑定和弦后运行以下命令。
bindkey -M viins -r "^[/"
bindkey -M viins "^[." _history-complete-newer