Edited at

Vimからクリップボードインテグレーションシーケンス(PASTE64/OSC52)を利用する

More than 5 years have passed since last update.


はじめに

今回もまたxterm由来のクリップボードインテグレーション(PASTE64/OSC52)の話題なんですが、先日iTerm2がサポートしたことで、ほんのちょっとだけ認知度が上がったようですね。よかったです。

PASTE64/OSC52って何のことか知らないという人は、お先にこちらをどうぞ。


Vimからの利用

この機能はXが無い環境からでもssh先とクリップボード連携できるという特性があり、なかなか使い勝手がよいものです。

tmuxだけにつかわせておくのはちょっともったいないですよね。

そこで今回は、VimにPASTE64/OSC52をインテグレートする設定例を書いてみました。


function! s:Paste64Copy() range
let l:tmp = @@
silent normal gvy
let l:selected = @@
let l:i = 0
let l:len = strlen(l:selected)
let l:escaped = ''
while l:i < l:len
let l:c = strpart(l:selected, l:i, 1)
let l:escaped .= printf("\\u%04x", char2nr(l:c))
let l:i = l:i + 1
endwhile
if $TMUX != ""
"tmuxのとき
call system('printf "\x1bPtmux;\x1b\x1b]52;;%s\x1b\x1b\\\\\x1b\\" `echo -en "' . l:escaped . '" | base64` > /dev/tty')
elseif $TERM == "screen"
"GNU Screenのとき
call system('printf "\x1bP\x1b]52;;%s\x07\x1b\\" `echo -en "' . l:escaped . '" | base64` > /dev/tty')
else
call system('printf "\x1b]52;;%s\x1b\\" `echo -en "' . l:escaped . '" | base64` > /dev/tty')
endif
redraw!
endfunction

command! -range Paste64Copy :call s:Paste64Copy()

.vimrcにこれを書いて、テキストを選択後、


:'<,'>Paste64Copy


とコマンドを打ち込んでやれば、OSC52シーケンス経由でのクリップボードコピーができます。

もちろんSSH越しでも使えます。


解説

Vimから端末に対して、任意のタイミングで生文字列を送る方法をちょっと探してみたのですが、どうやらsystem関数でやるしかなさそうだったので、ここではそうしています。

正直こんなかっこわるいやり方はゆるせない、と思っているので、他にもっといい方法があれば教えてください。

さて、OSC52シーケンスが制御端末まで届いたとしても、まだ障害があります。

GNU Screenやtmuxのようなターミナルマルチプレクサは、基本的に自分の知らないシーケンスを全部たべてしまうので、フロントエンド端末まで届かないのです。

私がターミナルマルチプレクサを使わない理由の3割くらいはこれなんですが、普通の人は使うと思うので、ここではGNU Screen/tmuxの独自拡張であるパススルーシーケンスを使用し、OSC 52を貫通させました。

GNU Screenとtmuxでのエスケープの仕方の違いを考慮するあたりがとても重要なポイントですね。