ゆんたんのきまぐれBlog

dotfiles

#neovim #dotfiles #tmux

TL;DR

let s:osc52_copy = {lines, regtype ->
\ chansend(v:stderr, printf("\x1b]52;;%s\x1b\\", system("base64", join(lines, "\n"))))}
let s:osc52_paste = {-> getreg('"', 1, 1)} " fallback
if !exists('$TMUX')
  let g:clipboard = {
\   'name': 'osc52',
\   'copy': {
\     '+': s:osc52_copy,
\     '*': s:osc52_copy,
\   },
\   'paste': {
\     '+': s:osc52_paste,
\     '*': s:osc52_paste,
\   },
\   'cache_enabled': 1,
\ }
endif
set -g set-clipboard on

OSC 52制御文字列とは

CLIアプリとクリップボードを連携するためのXTermの制御文字列. XTerm Control Sequences

OSC 52に対応している端末エミュレーターで以下のコードを試すと,クリップボードの内容を変更できる.

printf "\x1b]52;;%s\x1b\\" "$(base64 <<< "hello")" # "hello" をクリップボードに送信

以下のコードでクリップボードの内容を取得できる(…はずだが,なぜか上手くいかない)

printf "\x1b]52;;?\x1b\\"; awk -F ";" '{print $3}' | base64 -d

利点

  • OSに依存しない
    • xclippbcopyなどのプログラムを指定しなくてもOSのクリップボードを読み書きできる.
  • SSHで使える
    • X11転送ssh -Xの代わりに使える.

欠点

  • 対応している端末エミュレーターが少ない
    • 特に,OSC 52 ?にはセキュリティ上の理由で対応していないアプリがほとんど.
  • クリップボードの内容をvim/tmuxに反映することができない
    • neovimでクリップボードの内容の取得を試したが手段が見つからなかった.
    • tmuxはクリップボードの内容の取得に対応していない.

neovimの設定

neovimのclipboard-providerとして登録する.:h provider-clipboardを参照.

let s:osc52_copy = {lines, regtype ->
\ chansend(v:stderr, printf("\x1b]52;;%s\x1b\\", system("base64", join(lines, "\n"))))}
let s:osc52_paste = {-> getreg('"', 1, 1)} " fallback
if !exists('$TMUX')
  let g:clipboard = {
\   'name': 'osc52',
\   'copy': {
\     '+': s:osc52_copy,
\     '*': s:osc52_copy,
\   },
\   'paste': {
\     '+': s:osc52_paste,
\     '*': s:osc52_paste,
\   },
\   'cache_enabled': 1,
\ }
endif
  • clipboard providerから/dev/ttyにアクセスできないので,ワークアラウンドとしてchansend(v:stderr, "hello")を使う.
  • tmuxの上にnvimが乗ってるときは,providerを追加せずにデフォルトで用意されているtmux providerを使う.
  • OSC52?(クリップボードの内容の取得)を試したが,上手いやり方が見つからなかった.
    • 失敗例
    • code:vim
    • let s:osc52_paste = {–> system(“base64 -d”, split(chansend(v:stderr, “\x1b]52;;?\x1b\”), “;”)[2])}
    • code:vim
    • let s:osc52_paste = “echo -en '\x1b]52;;?\x1b\'; awk -F ';' '{print $3}' | base64 -d”
  • ひとまず"registerの内容を持ってきて誤魔化している.
    • code:vim
    • let s:osc52_paste = {–> getreg('“', 1, 1)} ” fallback

tmuxの設定

tmuxはOSC52?(クリップボードの内容の取得)には対応していない. – OSC 52 clipboard reading · Issue #1477 · tmux/tmux

set -g set-clipboard on

OSC52に対応している端末エミュレーター

端末エミュレーターの設定

  • Alacrittyは設定不要.
  • RLoginの設定例

参考

#tmux #dotfiles

見た目の変更

ウィンドウとペインのインデックスを1から始めるようにする.

set -g base-index 1
set -g pane-base-index 1

アクティブなペインの枠を目立たせる

set -g pane-active-border-fg red

prefixキーの変更

prefixキーを押しやすいキー(Ctrl-a)に変更する.

unbind C-b
set -g prefix C-a
bind C-a send-prefix

キーバインド

PREFIX Tabで次のパネルに移動する.

bind Tab select-pane -t :.+ # 次のペインを選択

PREFIX Shift-Tabで前のパネルに移動したいが,なぜか次の設定は反映されない.

bind S-Tab select-pane -t :.- # 前のペインを選択

vimのようにPREFIX pで貼り付けする.

bind p paste-buffer # ペースト

ペイン分割のキーバインドを覚えやすいものに変更する.

bind | split-window -h # 縦に分割
bind - split-window -v # 横に分割

copy modeのキーバインドをよりvimらしくする(vで選択開始,yでyank).

setw -g mode-keys vi # copy-modeでvi bindingを使う 
bind -T copy-mode-vi v send-keys -X begin-selection
bind -T copy-mode-vi y send-keys -X copy-selection  

#tmux #dotfiles

以下の画像のようなstatus lineにするための,tmuxの設定を紹介する.

通常時のstatus line.左から順に,モード,ホスト名,ウィンドウリスト,メモリの容量,ルートのディスクの容量,load average,日付時刻を表示している.

prefix keyを押下したときのstatus line.モード表示の色を反転させている.また,ホスト名の代わりに一部のキーバインドを表示している.

copy modeにおけるstatus line.モードとcopy modeで使える一部のキーバインドを表示している.

この記事では以下の設定について紹介する.

  • emacsのwhich-keyぽいやつ
  • モードの表示とprefix keyの状態表示
  • メモリ,ディスク容量,load average等の表示

status lineの色の設定

お好みで.

set -g status-fg black
set -g status-bg white

左側の設定

set -g status-left-length 120
# prefix keyが押されていたら色を反転,copy-modeに入ったら表示を変更
set -g status-left '#{?pane_in_mode,#[bg=yellow] COPY ,#[fg=cyan,bg=black]#{?client_prefix,#[reverse],} TMUX }'
# ホスト名を表示,prefix keyが押されたらwhich-key的なヒントを表示,copy-modeに入ったらwhich-key的ヒントを表示
# #H: ホスト名
set -ga status-left '#[default] #{?pane_in_mode,/: search  v: begin-selection  y: copy  q: cancel,#{?client_prefix,M-1: even-h  M-2: even-v  M-3: main-h  M-4: main-v  M-5: tiled  Space: next-layout  d: detach  Enter: copy-mode  p: paste,#H}}'

?pane_in_modeでcopy modeかどうか,?client_prefixでprefix keyが押されているか判別できる.which-key的ヒント用の文字列はお好みで.status leftに表示する文字列の長さに応じてstatus-left-lengthを変更する.

中央(ウィンドウリスト)の設定

set -g status-justify centre # ウィンドウリストを中央寄せ
set -g window-status-current-fg red # アクティブなウィンドウを目立たせる

右側の設定

set -g status-right-length 120
set -g status-right '[mem: #(tmux-status-mem)]' # メモリの容量と空き
set -ga status-right ' [disk: #(tmux-status-disk)]' # /の容量と空き容量
set -ga status-right ' [load: #(tmux-status-load)]' # load average
set -ga status-right ' [%Y-%m-%d %H:%M]' # 日付・時刻

メモリ,ディスク,load averageを取得するスクリプトは,別のスクリプトに分けて,$PATHが通るところに置く..tmux.conf内にスクリプトを書くと,文字列の多重エスケープにより解読不能になるため.

#!/bin/bash

free -h | awk '/^Mem:/{print $3"/"$2}'
#!/bin/bash

# /にマウントされているファイルシステムの容量と空き容量を表示
df -h | awk '$6 ~ /^\/$/ {print $4 "/" $2}'
#!/bin/bash

uptime | awk '{print "1m " $(NF - 2) "/5m " $(NF - 1) "/15m " $(NF)}' | sed 's/,//g'

おまけ

tmuxの設定例(その2)