在服务器上的 vim 里按 y,内容只留在 vim 里,到不了手机。这里讲清楚原因,以及一个小插件,让每次复制(yank)都送到手机剪贴板——在 tmux 里、走 mosh 也行。
撰写于
在 vim 里,y 是复制到 vim 自己的寄存器。这个寄存器在 vim 里,在服务器上,不会被送到任何别的地方。在同一个 vim 里可以用 p 粘回来,但手机完全不知道。
系统剪贴板寄存器 "+ 和 "* 也帮不上忙。在服务器上,它们指的是服务器自己桌面的剪贴板,而服务器没有桌面。大多数服务器上的 vim 直接就是这样编译的:vim --version 里显示 -clipboard,"+y 什么也不做。就算 vim 带剪贴板,复制到的也是服务器的剪贴板,不是手机的。SSH 在两台机器之间传的是按键和屏幕,不是剪贴板。
能从服务器到达手机的,是一个叫 OSC 52 的转义序列。程序把它打印出来,终端就把其中的文字放进它所在设备的剪贴板。Term 支持它:文字直接进入手机剪贴板。vim 自己不会发送 OSC 52,所以需要一个插件来做这件事。
vim-oscyank 是一个小插件,把复制的内容以 OSC 52 发出去。在服务器上把它装成 vim 的 package,不需要插件管理器:
mkdir -p ~/.vim/pack/plugins/start git clone https://github.com/ojroques/vim-oscyank ~/.vim/pack/plugins/start/vim-oscyank
如果用 vim-plug,就在 ~/.vimrc 里加上 Plug 'ojroques/vim-oscyank', {'branch': 'main'},再执行 :PlugInstall。
插件只在被调用时才工作。要让平常的每次复制也送到手机,在 ~/.vimrc 里加上:
" Copy every yank to the phone's clipboard (vim-oscyank, OSC 52) autocmd TextYankPost * \ if v:event.operator is 'y' && v:event.regname is '' | \ execute 'OSCYankRegister "' | \ endif
之后 yy、yw、V 再 y——任何复制到默认寄存器的操作——都会同时到达手机,vim 也会提示:[oscyank] 61 characters copied。文字马上出现在输入法的 From clipboard(来自剪贴板)一栏里,在手机上任何地方都能粘贴。回到 Term 里,在光标旁长按或按 Ctrl+Shift+V 就能粘贴——见终端里的复制与粘贴。
删除(d、x)和复制到命名寄存器("ay)仍然只留在 vim 里,和以前一样。如果只想有意复制某一段,而不是每次复制都发送,插件的 README 里给了一个映射:选中后按 <leader>c。
tmux 会截住里面程序发出的 OSC 52。默认设置(set-clipboard external)下它把复制留给自己,于是 vim 提示 copied,手机上却什么也没有。让 tmux 把它传出去:
set -s set-clipboard on然后用 tmux source-file ~/.tmux.conf 重新加载。
走 mosh 时,tmux 还要再加一行。mosh 只转发 52;c; 这种形式的复制,而 tmux 写出来的是 52;;,所以在 tmux 里复制的内容会在路上被丢掉:
set -ag terminal-overrides ',*:Ms=\E]52;%p1%sc;%p2%s\a'不经过 tmux 时,vim-oscyank 本身写出来的就是 52;c; 形式,所以 mosh 下直接用 vim 不需要额外设置。
同一个插件在 Neovim 里也能用:克隆到 ~/.local/share/nvim/site/pack/plugins/start/,把同样的几行放进 ~/.config/nvim/init.vim。
Neovim 0.10 及以后的版本也内置了 OSC 52(let g:clipboard = 'osc52')。它能复制到手机,但粘贴时也用 OSC 52,会向终端索要剪贴板内容。Term 不会响应这个请求(见下文),所以 "+p 会停在 Waiting for OSC 52 response from the terminal,然后放弃。插件只负责复制,所以从不需要等待。粘贴请用 Term 自己的粘贴。
这是单向的。服务器上的程序可以把文字放进手机剪贴板,但 Term 不允许它读回剪贴板。这是出于安全考虑:剪贴板里常常是密码、验证码和私人消息,而读取请求可能来自你连接的任何服务器上的任何程序——一个脚本、一个依赖包、别人的机器。所以这个功能目前不开放。要从手机粘贴到 vim 里,在插入模式下用 Term 的粘贴:粘贴什么由你决定,文字会插入到光标处。
mosh 最多传 16 KB 的剪贴板内容。更长的复制会被截断,而且不会报错。走 SSH 时上限是几 MB。