LoginSignup
8
8

More than 3 years have passed since last update.

SSH接続先のvimでヤンクした内容をローカルホストクリップボードに反映する

Last updated at Posted at 2019-12-21

更新履歴

2020/01/04 追記

SendViaOSC52関数の呼び出し条件を変更しました。

2019/12/23 追記

以下の内容で、小規模なテキストについて、ヤンクした内容がクリップボードに連携されることは確認した。(実用上はこれで問題ない。)
しかし、大きなデータ(1000行とか)をヤンクすると、クリップボードに反映されない、という現象が発生している。詳細と次善の対処方法(手順4)を後述する。

問題

Ubuntu18.04LTSにSSH接続して、リモートのvimでテキストを編集するとき、ヤンクした内容をクリップボードに反映したい。
vimはUbuntuのパッケージ vim を利用。(vim-tinyではない。)
vimのバージョンは、以下の通り。

$ dpkg -l | grep vim
ii  vim                                    2:8.0.1453-1ubuntu1.1             amd64        Vi IMproved - enhanced vi editor
ii  vim-common                             2:8.0.1453-1ubuntu1.1             all          Vi IMproved - Common files
ii  vim-runtime                            2:8.0.1453-1ubuntu1.1             all          Vi IMproved - Runtime files
ii  vim-tiny                               2:8.0.1453-1ubuntu1.1             amd64        Vi IMproved - enhanced vi editor - compact version
$ ll /usr/bin/vim
lrwxrwxrwx 1 root root 21 Aug 24  2018 /usr/bin/vim -> /etc/alternatives/vim*
$ ll /etc/alternatives/vim
lrwxrwxrwx 1 root root 18 Aug 24  2018 /etc/alternatives/vim -> /usr/bin/vim.basic*
$ vim --version | grep Vi
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Jun 06 2019 17:31:41)
$ vim --version | grep version
Huge version without GUI.  Features included (+) or not (-):

対処

OSC 52という端末制御シーケンスを用いると、クリップボードに連携できる模様。
ただし、「OSC 52でのクリップボードアクセスはセキュリティ面の懸念から、デフォルトでは無効にしている端末が多い」とのこと。
ご利用は、自己責任で。

手順 1. RLoginあるいはiTerm2の設定(OSC52の有効化)

Rloginの設定(Windows)

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

iTerm2の設定(Mac)

メニューのProfiles/Open Profilesで Allow clipboard access to terminal appsにチェックを入れる

手順 2. vimプラグインのインストール

以下のコマンド(3行)を実行して、pluginディレクトリに、osc52.vimファイルを配置します。
ここで登録するファイルは、GitHubで公開されている ShikChen/osc52.vim です。
このプラグインには、関数 SendViaOSC52() が定義されています。

$ mkdir -p ~/.vim/plugin/
$ cd ~/.vim/plugin/
$ wget https://raw.githubusercontent.com/ShikChen/osc52.vim/master/plugin/osc52.vim

プラグインが不要なら、以下のようにして削除してください。

$ rm ~/.vim/plugin/osc52.vim 

手順 3. 関数 SendViaOSC52() の呼び出し設定

とりあえず、すべてのテキストヤンクに対して、クリップボードに連携する設定を行います。

以下の設定(5行)を、~/.vimrc に追加します。

augroup osc52
    " 最初にこのグループのautocmd定義を削除する。
    autocmd!
    autocmd TextYankPost * if v:event.operator ==# 'y' | call SendViaOSC52(getreg(v:event.regname)) | endif
augroup END

上記の設定では、autocmd(自動コマンド)という機能を使います。
テキストをヤンクしたあとのイベント(TextYankPost)において、すべてのファイル(*)で、yキーでヤンクしたときだけ、SendViaOSC52()関数を呼び出す設定です。

2020/01/04 追記
記事公開当初は、autocmd TextYankPost * call SendViaOSC52(getreg(v:event.regname)) と紹介していたが、xキーで文字を削除するとき、いちいち関数が呼ばれて動作が重くなってしまうため、yキーだけで関数を呼び出すようにした。

autocmdは、イベントにコマンドを追加するだけなので、再読み込みすると、イベントに何度も追加されてしまいます。このため、augroupで、osc52という自動コマンドグループを定義し、最初にautocmd!でグループ内のautocmd定義をすべて削除します。

セキュリティ的に懸念がある場合は、キー割り当てで呼び出す設定をしてもよいと思います。
上記の設定を行わずに、以下の設定(1行)を、~/.vimrc に追加します。

vnoremap Y y:call SendViaOSC52(getreg('"'))<CR> 

上記の設定では、vnoremap を使って、ビジュアル(選択)モードで、Y(=Shift-y)キーに、以下の動作を割り当てます。

  • y(=ヤンク)
  • 関数SendViaOSC52()の呼び出し(無名レジスタの値をクリップボードに送る)

※2019/12/23 追記
デフォルトでは、キー Y には、何も機能がマッピングされていないはず。
デフォルトでは、キー Y は、"yy"(行ヤンク) と同じ動作となっています。

2019/12/23 追記

上記設定を行った状態で、大きなデータ(1000行とか)をヤンクすると、クリップボードに反映されない、という現象が発生している。
確認した環境は、Windows10のRLogin経由。このとき、vimでヤンクしたテキストは98292bytes、送信するBASE64データが131064bytesまではうまく送信できたが、テキスト98293bytes、送信するBASE64データが131068bytesになると、クリップボードに反映されなかった。

vimプラグイン側は送信しているようなので、受け取り側の問題のような気がする。
ただ、RLogin側の問題か、Windows10側クリップボードの仕様か、メモリ割り当ての問題あたり?
RLogin側の該当部分は、このあたり。 RLogin/RLogin/TextRamProc.cpp [Line.4680]

              if ( (m_pDocument->m_TextRam.m_ClipFlag & > OSC52_WRITE) != 0 ) {
                  clip.Base64Decode(MbsToTstr(p));
                  if ( pView != NULL )
                      pView->SetClipboard(&clip);

そこで、ヤンクを使わない方法として、マウスによる範囲選択でコピーしてしまう方法を検討。以下は、その設定方法。

手順 4. 行番号と不可視文字の表示・非表示をトグルするための設定

※この手順は、手順1~3を行っていなくても有効な設定手順です。
以下の通り、.vimrcに設定する。(listcharsはお好みで。)

set number
set list
set listchars=tab:»-,trail:-,eol:↲,extends:»,precedes:«,nbsp:%
set mouse=a

" 行番号と不可視文字の表示・非表示とマウスモードをトグルする
noremap <silent> <F12> <ESC>:set number!<CR>:set list!<CR>:exec &mouse!=""? "set mouse=" : "set mouse=a"<CR> 

上記の設定では、set numberで行表示を、set listで不可視文字の表示を、set mouse=aでマウスモードをallに設定している。
また、noremapの行で、F12キーに対して、「行番号と不可視文字の表示・非表示とマウスモードをトグルする」コマンドを割り当てている。
これにより、F12を押して非表示にすれば、端末ソフトウェアの機能を使って範囲選択・コピーすることができる。再度F12を押して表示できる。

なお、範囲選択だけでクリップボードにコピーするようにするには、以下を行う。

  • RLoginの場合は、「クリップボード」「左クリックの範囲指定だけでクリップボードにコピーする」にチェックを入れる。
  • iTerm2の場合は、メニューのPreference ->General -> Copy to clipboard on selectionにチェックを入れる
8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8