tateren’s diary

何か書きたくなった時に使う

リモートのVimからssh越しにクリップボード書き込み

わりと皆やりたがるやつ。

OSC52という端末の制御シーケンスでクリップボードアクセスができるらしい。

端末側の設定

セキュリティ上端末エミュレーターのデフォルト設定では無効になってることが多いとか。

自分が触る範囲だと以下の方法で書込許可設定ができた。

Tera Term

[設定]→[その他の設定]→[制御シーケンス]→[リモートからのクリップボードアクセス]を書き込みのみ(又は読込/書込)

Rlogin

Server Edit Entryで[クリップボード]→[制御コードによるクリップボード操作]→[OSC 52 によるクリップボードの書き込みを許可する]にチェック

Vim側の設定

こういうVim scriptがあった。

github.com

コメントにも書かれている通りosc52.vimを任意のパスに保存して、.vimrc内に以下の二行を追記

source ~/path/to/osc52.vim
vmap <C-c> y:call SendViaOSC52(getreg('"'))<cr>

ビジュアルモードで範囲選択中にCtrl-Cを押すとローカルのクリップボードに書き込んでくれる。

Tera Termで日本語対応

Tera Termだと日本語をコピーした時に化けてしまった。

色々調べてたらTera Termの中の人のgistを見つけた。

OSC 52 でのクリップボード書き込み (zsh用関数定義) · GitHub

# 漢字コードの扱いは端末依存。
# 例えば Tera Term の場合は現状では変換をまったく行わない為、
# 事前に CP932 に変換する必要がある。

ということで事前にcp932に変換してやるように修正してみた。

diff --git a/osc52.vim b/osc52_for_teraterm.vim
index 1cb6931..376347b 100644
--- a/osc52.vim
+++ b/osc52_for_teraterm.vim
@@ -42,7 +42,8 @@ endfunction
 "
 " It's appropriate when running in a raw terminal that supports OSC 52.
 function! s:get_OSC52 (str)
-  let b64 = s:b64encode(a:str)
+  let str = iconv(a:str, &encoding, "cp932")
+  let b64 = s:b64encode(str)
   let rv = "\e]52;c;" . b64 . "\x07"
   return rv
 endfunction
@@ -56,7 +57,8 @@ endfunction
 function! s:get_OSC52_DCS (str)
   " The base64 commands with no params will return a string with newlines
   " every 72 characters.
-  let b64 = s:b64encode(a:str)
+  let str = iconv(a:str, &encoding, "cp932")
+  let b64 = s:b64encode(str)
 
   " Remove the trailing newline.
   let b64 = substitute(b64, '\n*$', '', '')

これでTeraTermからでも日本語がクリップボードに送れるようになった。

RLoginは端末の文字コード設定に応じて解釈してくれるっぽいのでこの修正は不要だった。