我们常常会用 ssh 登录远程机器,并在在其中 vim 命令编辑查看文件。一个常见的问题是如何无缝把选中的内容复制到本地的剪贴板呢?

步骤

  1. 本地需要一个支持 OSC 52 的终端
    • Linux 下的 xterm,设置 disallowedWindowOps: 20,21,SetXprop
    • Mac 下的 iterm2,勾选 Applications in terminal may access clipboard
  2. 在远程机器上安装 neovim,它允许我们自定义如何复制粘贴
  3. clipboard-provider 脚本放在 PATH 下。
  4. 在 vimrc 中添加如下配置:
    if executable('clipboard-provider')
    let g:clipboard = {
    \ 'name': 'myClipboard',
    \ 'copy': {
    \ '+': 'clipboard-provider copy',
    \ '*': 'env COPY_PROVIDERS=tmux clipboard-provider copy',
    \ },
    \ 'paste': {
    \ '+': 'clipboard-provider paste',
    \ '*': 'env COPY_PROVIDERS=tmux clipboard-provider paste',
    \ },
    \ }
    endif

尝试在 ssh 中打开 neovim,通过 "+y 来复制内容,预期本地能直接粘贴这些内容!

原理

OSC 52

OSC 52 是 xterm 的一个特性,许多终端也支持。它能识别命令行输出中的一些特定格式的内容,并将其中的内容解析后设置为系统剪贴板的内容。具体来说,这个特性 能解析的格式如下:

OSC 52 ; Pc ; Pd ST
  • 前缀 OSC 是 \e]
  • 其中的 Pc 用于选择使用哪个剪贴板,我们选择主剪贴板 c
  • 其中的 Pd 是 base64 编码后的内容,例如 hello 编码为 aGVsbG8=
  • ST 指的是 \a

我们可以通过执行命令 echo -e '\e]52;c;aGVsbG8=\a',然后看粘贴的内容是否为 hello 来判断当前终端是否支持 OSC 52.

注意:这个特性有潜在的安全问题,所以理论上开启后不要执行你不信任的程序。

clipboard-provider

clipboard-provider 脚本的作用是将输入的内容尝试“粘贴”到 tmux 的 buffer 中、系统的剪贴板中。这个脚本可以独立于 neovim 使用。如可以尝试把远程的文件复制到剪贴板中:cat hello.txt | clipboard-provider copy

g:clipboard

在 neovim 中输入 :help g:clipboard 可以看到相关的说明。简单地说,它允许我们指定,当复制内容到 +* 寄存器时,执行什么命令。上面的设置其实就是调用了 clipboard-provider copy 来将内容复制 tmux 及系统剪贴板中。

支持 tmux

我个人一般是在 SSH 中运行 tmux,再在 tmux 中运行 vim 等命令。幸运的是 tmux 也支持 OSC 52. 只需要在 ~/.tmux.conf 中添加:

set -g set-clipboard on

现在还缺失的一个功能是远程粘贴的时候也能打通剪贴板,这个还没研究出来,就先不说了。