具有历史记录的 zsh bindkey

zsh bindkey with history

简而言之,我想将 Ctrl + 2 映射到我的 .zsh_history 文件中第二个最近记录的命令。通常我会输入 !-2 来实现这一点。但是,为了在 shell 函数中重新创建此行为,我编写了以下内容:

function two_back {
  HISTFILE=~/.zsh_history
  command=$(history | tail -n 2 | head -n 1 | cut -c 8-)

  echo -n "$command"
}

这输出了我期望的值,所以我觉得还不错。事实上,如果我只是 运行 函数 two_back 并按 <Enter> 它会按预期工作。在我将函数绑定到某些击键后,问题似乎就暴露出来了。

首先我将函数转换为 zsh 小部件,以便我可以将它绑定到一些击键...

$ zle -N two_back_widget two_back

然后我使用 bindkey 命令创建映射...

$ bindkey '^@' two_back_widget

现在,当我键入 Ctrl + 2 时,我的 z-shell 行编辑器 zle 包含我期望的输出。但是,当我尝试通过按 <Enter> 来 运行 命令时,什么也没有发生……其他人可以重现吗?有谁知道为什么这不起作用?

这不起作用的原因是,虽然命令被打印到终端(output),但它没有写入终端(input).

为了像在 shell 中输入的那样实际输入命令,这应该可行:

function two_back {
   HISTFILE=~/.zsh_history
   command=$(history | tail -n 2 | head -n 1 | cut -c 8-)

   BUFFER="$command"
   CURSOR=$#BUFFER
}

zle -N two_back_widget two_back
bindkey '^@' two_back_widget

解释:

  • zle widgets BUFFER 中包含当前命令行。也可以修改。在这种情况下 BUFFER 设置为 command 的值。写入 BUFFER 有效编辑命令行上的当前命令。
  • CURSOR 包含命令行上的光标位置。通过将其设置为 BUFFER 的长度,光标将放置在输入的末尾。这不是绝对必要的,如果不设置它,光标将保留在同一个地方。如果命令行之前为空,则光标将位于命令的最左侧。