kefir_さんが書いたVimからクリップボードインテグレーションシーケンス(PASTE64/OSC52)を利用する #端末エミュレーション #Terminal #Vim – Qiitaにtmuxを使ってても、使える設定があったので、試してみたけど、base64コマンドがなかったので、id:ks0608が書いた”pbcopy“を使うように書き換えた、他。

コピー編

Vimでヴィジュアルモードで選択した領域をクリップボードに保存する。

Windowsで、OSC52に対応している端末エミュレータ(Tera Termなど。いわもと こういち さんの記事によると他にもいろいろあるらしい)を使っているのを想定している。

使い方

  1. 上のclipboard.vimの方を.vimrcに加える
  2. 下のpbcopy.plをpbcobyというファイル名に変換して、実行権限を与えて、PATHの通った場所に置く
  3. Tera Termを使っている場合は[設定]-[その他の設定]-[制御シーケンス]にある、“リモートからのクリップボードアクセス”を“書込のみ”を設定する

    • ビジュアルモードで選択して、:'<,'>Paste64Copyすると、クリップボードに保存される
pbcopyを単体で使う場合は

[bash]

$ date | pbcopy

$ tree | pbcopy

$ pbcopy < file.txt

[/bash]

説明

clipboard.vimにて、選択した文字列をpbcopyに送り、画面にOSC52の制御シーケンスを送って、Tera Termがクリップボードに保存する。

let l:tmp = @”あたりでやっているのは、現在のヤンクされている内容をtmpに一度避難させて、選択領域をヤンク。let @” = l:tmpで戻している。

エスケープ処理しているところは、日本語が混じっているとおかしくなったので、処理から外した。ちなみにこのエスケープ処理は、”とか$などをエスケープするために必要。

pbcopy.plではWindows用に文字列の改行コードを変換したり、文字コードをcp932に変換している。

その下で、tmux, screen, 素の状態別に処理を書いている。

どうもtmuxでは250文字, screenでは510文字しか、一度に文字列を送れないらしい(多分制御シーケンスもあわせて256byte, 512byteな感じ)。そこで分割しておくる。

クリップボードに保存できる文字数はBASE64で変換後の文字列で4096byteまで。変換前だと、4096 * 3 / 4 = 3072byteくらいまで。

残念ながら、tmux起動時では、変換前の文字列で1800byteくらいしか保存できなかった。分割して送った時にtime outでもあるのかと思って、for文内でsleepしてみたけど、保存できる文字数に変化はなかった。

ちなみに文字列が限界を超えると、切り捨てで保存されるのではなく、全く保存されない仕様です。

ちなみに環境変数TMUXがあるかないかでtmuxの判定すると、sshした先では$TMUXが設定されておらず、うまくいかない。自分の場合は$TERMがxterm-256colorかどうかで判定するようにしている。

Puttyだと、リモートプリント機能を利用してクリップボードに保存するパッチがあるらしい。

昔書いたけど、tmux対応して、ちょこっと変更したのでもう一度書く。

Bracketed Paste Modeに対応する端末(Tera term, iceiv+puttyなど) で貼り付けを行った時に自動的にpaste modeにする。

使い方

上の設定をvimrcに書いて、インサートモードで貼り付けを行うと、自動的にpaste modeになり、貼り付けが終了するとpaste modeを解除する。

説明

  1. インサートモードに入ると、Vimが端末に\e[?2004hを送る。

    • Bracketed Paste Modeに対応した端末が、その制御シーケンスを受け取ると、貼り付け実行時に文字列の前に\e[200~を、後ろに\e[201~をつけるようになる。
    • \e[200~を受け取ったVimがpaste modeに変更し、その後の文字列を書き込む。
    • 文字列の最後で\e[201~を受け取ったVimがpaste modeを解除する
    • インサートモードを抜けると、Vimが端末に\e[?2004lを送り、受け取った端末は貼り付け時の文字列に制御シーケンスをつける設定を解除する
ちなみに

[vim]

inoremap [200~ :set paste

[/vim]

とせずに

[vim]

exec “set =\e[200~”

inoremap :set paste

[/vim]

のようにsetを間にかませているのは、

[vim]

inoremap [200~ :set paste

[/vim]

で設定すると、インサートモードでキーを押したときset timeoutlenで設定した時間だけキー待ちが発生するため。

キー待ちを回避するためには、F13のように使わないキーに対して、key codeをsetしてそのキーに対してmapする。

例えば、key mappingに対しては3000ミリ秒待ち、key codeに対しては10ミリ秒待つという設定にするにはvimrcに

[vim]

set timeout timeoutlen=3000 ttimeoutlen=10

[/vim]

と書いておく。

[vim]

set =^[[200~

[/vim]

(^[はctrl+V )ではなくexecを使ったのはコピペしやすくするため。

さらに蛇足だけど、tmux使っている時にを使って遅延を感じた場合は.tmux.confに

[text]

set -s escape-time 10

[/text]

を設定しておくと良い。

終わり。

関連するツイート