如何配置 vi 模式 bash 用于复制和粘贴的缓冲区?

如何配置 vi 模式 bash 用于复制和粘贴的缓冲区?

总而言之: 有谁知道如何配置 vi-mode bash 使用哪个缓冲区进行拉取(复制)和粘贴?

长版:set editing-mode vi在我的.inputrc, 中使用该库的程序readline(即 bash)使用类似 vi 的键绑定。与此无关,我已经设置了 vim 和 tmux 以使用系统剪贴板进行拉取和粘贴。我想对 bash 做同样的事情。这似乎没有必要,因为我主要通过 tmux 使用 bash,但即便如此,能够使用p(在正常模式下)从剪贴板复制而不是C-a P或类似的东西(带有 tmux 前缀)也会很好。但是,我找不到任何有关如何配置 bash 这方面的信息,甚至找不到 bash 默认使用什么缓冲区进行拉取和粘贴的信息。当我在vim中执行时我没有看到它:registers,所以它似乎不是vim看到的任何寄存器。

答案1

经过一些研究后,bash 似乎为此使用了一个内部变量,而不是任何现成的系统缓冲区。它在 bash 和 readline 的手册条目中被称为“杀环”,其实现可以阅读在 GitHub 上、以及其他地方。也许可以劫持这个机制来使用系统剪贴板,但这似乎对我来说有点太复杂了,目前无法解决。

相反,我选择了下面的简单解决方法,使用 bash 内置bind命令,该命令记录在 bash 手册页中(搜索bind \[)。它很好地涵盖了我的用例,但它没有涵盖使用 vim 动作进行更高级的杀戮和猛拉。如果您发现我的解决方案有问题,请告诉我,因为我不习惯编写 bash 脚本。

在~/.bashrc中:

# Macros to enable yanking, killing and putting to and from the system clipboard in vi-mode. Only supports yanking and killing the whole line.
paste_from_clipboard () {
  local shift=$1

  local head=${READLINE_LINE:0:READLINE_POINT+shift}
  local tail=${READLINE_LINE:READLINE_POINT+shift}

  local paste=$(xclip -out -selection clipboard)
  local paste_len=${#paste}

  READLINE_LINE=${head}${paste}${tail}
  # Place caret before last char of paste (as in vi)
  let READLINE_POINT+=$paste_len+$shift-1
}

yank_line_to_clipboard () {
  echo $READLINE_LINE | xclip -in -selection clipboard
}

kill_line_to_clipboard () {
  yank_line_to_clipboard
  READLINE_LINE=""
}

bind -m vi-command -x '"P": paste_from_clipboard 0'
bind -m vi-command -x '"p": paste_from_clipboard 1'
bind -m vi-command -x '"yy": yank_line_to_clipboard'
bind -m vi-command -x '"dd": kill_line_to_clipboard'

编辑1: 使用两次连续按键的绑定“yy”和“dd”受keyseq-timeoutreadline 设置的影响。默认值为 500 毫秒,这意味着您必须在第一个字符后 500 毫秒内键入第二个字符。因此,如果您设置keyseq-timeout为低得多的值,则可能会遇到一些麻烦。

编辑2: 更新了粘贴以更精确地模拟 vim 行为。

相关内容