よんちゅBlog

― このブログは自分用のメモや日々の問題などを共有するためのものです ―

20121005185841 お知らせ:  2013/07/17 ブログデザインをリニューアルしました。

vimとtmuxのステータスラインを連携させてみた。

少し前からやってて意外と便利だったので紹介。
(しかし需要は極めて低いと思われる)

今回紹介する方法では tmux-powerline というtmuxのステータスラインをpowerline風にしてくれるスクリプトを使用します。

ただし、tmux-powerlineを使用しなくても、自身で必要な部分を作りこむことでも対応できます。

vim と tmux を連携してみる

まずは完成図を見て頂きましょう。

以下は通常時の tmux-powerline を使用したターミナル画面です。
tmuxのステータスラインに注目して下さい。
(表示情報が多すぎる気がするが、そこは気にしないでください。)

f:id:yonchu:20130322215933p:plain

続いて、vim を起動した時のターミナル画面です。

f:id:yonchu:20130322215514p:plain

いかがでしょう。
tmuxのステータスラインがガラリと変わったことに気づいたでしょうか。

vim起動後のステータスラインには、
vim内で選択されているバッファのディレクトリパスとそのディレクトリの git status が表示されています。

シェルのカレントディレクトリではありません。
vim 内でバッファを移動すれば、ステータスラインも更新されます。
また、vimを終了したり、tmux内で別ウィンドウや別ペインに移動した場合にも、それに応じて更新されます。

これでいつでも、ひと目でバッファのディレクトリとgitの状態が確認できます。

tmux-powerlineについて

tmux-powerlineの導入方法については、ここでは省かせて頂きます。
公式のreadmeを読むなりして導入して下さい。

ただ、tmux-powerline導入時に少しだけ注意があります。

tmux-powerline は2012年12月半ばあたりに大幅なバージョンアップが行われたため、過去の導入記事が役に立たなくなっています。
最新版の導入方法は公式readmeを見る必要があります。
(新verの tmux-powerline の導入方法について良い感じに説明しているページがあったのですが、失念してしまいました)

それと、tmux-powerline導入時に忘れがちな設定があります。
設定しなくも一部機能を除けば動作可能なのでですが、今回の話では必要なのでそこだけ書いておきます。
(公式readmeには書かれています)

bashの場合は .bashrc に以下の設定を、

PS1="$PS1"'$([ -n "$TMUX" ] && tmux setenv TMUXPWD_$(tmux display -p "#D" | tr -d %) "$PWD")'

zshの場合は .zshrc に以下の設定を追加して下さい。

PROMPT+='$([ -n "$TMUX" ] && tmux setenv TMUXPWD_$(tmux display -p "#D" | tr -d %) "$PWD")'

いずれもプロンプトに設定を追加していますが、プロンプトの表示内容には影響しませんのでご心配なく。

導入方法

遅くなりましたが、導入方法の説明をしていきましょう。

まず、.vimrc に以下の設定を記述します。

if exists('$TMUX')
  autocmd MyAutoCmd BufEnter * call <SID>set_vim_cwd_to_tmux()
  autocmd MyAutoCmd VimLeave * call <SID>del_vim_cwd_from_tmux()
endif

function! s:set_vim_cwd_to_tmux()
  if !exists('$TMUX')
    return
  endif

  let pain_id = system('tmux display -p "#D" | tr -d "%" | tr -d $"\n"')
  call system('tmux setenv ' . "TMUX_VIM_CWD_" . pain_id . ' ' . getcwd())

  let bt = &buftype
  let ft = &filetype
  " let bn = bufname('%')
  if bt ==# 'nofile' || ft ==# 'qf' || ft ==# 'quickrun'
    let pwd = getcwd()
  else
    let pwd = expand('%:p:h')
  endif

  let var_name = system('tmux display -p "TMUXPWD_#D" | tr -d "%" | tr -d $"\n"')
  call system('tmux setenv ' . var_name . ' ' . shellescape(pwd))
endfunction

function! s:del_vim_cwd_from_tmux()
  if !exists('$TMUX')
    return
  endif
  let var_name = system('tmux display -p "TMUX_VIM_CWD_#D" | tr -d "%" | tr -d $"\n"')
  call system('tmux setenv -u ' . var_name)
endfunction

簡単に説明すると、
バッファ移動(BufEnter)時に、tmux の環境変数 TMUX_VIM_CWD_#D に vim のカレントディレクトリ(cwd)のパスを設定し、TMUXPWD_#D に vim のバッファディレクトリのパスを設定しています。
さらに、vim終了(VimLeave)時には、TMUX_VIM_CWD_#D を削除しています。

TMUXPWD_#D は tmux-powerline が pwd を判定するのに使用している環境変数です。
この変数は削除する必要はありません。シェルのプロンプト更新時に自動的に更新されます。
TMUX_VIM_CWD_#D は今回新たに用意した環境変数です。

続いて、tmux-powerline のテーマ設定ファイルを変更します。
デフォルトのテーマを使用している場合は、tmux-powerline/themes/default.sh を変更して下さい。
自身で用意したものを使用している場合は、そちらを使用して下さい。

# Format: segment_name background_color foreground_color [non_default_separator]

vim_cwd=$(tmux showenv $(tmux display -p 'TMUX_VIM_CWD_#D' | tr -d '%') 2> /dev/null)
vim_cwd=${vim_cwd#*=}

if [ -n "$vim_cwd" ]; then
    # vim 起動時のステータスライン設定

    if [ -z $TMUX_POWERLINE_LEFT_STATUS_SEGMENTS ]; then
        TMUX_POWERLINE_LEFT_STATUS_SEGMENTS=(
            "tmux_session_info 148 234" \
            "hostname 63 255" \
            "vcs_branch 29 88" \
            "vcs_compare 60 255" \
            "vcs_staged 64 255" \
            "vcs_modified 9 255" \
            "vcs_others 245 0" \
        )
    fi

    if [ -z $TMUX_POWERLINE_RIGHT_STATUS_SEGMENTS ]; then
        TMUX_POWERLINE_RIGHT_STATUS_SEGMENTS=(
            "pwd 89 211" \
            #"vim-cwd 21 231" \
            "date_day 235 136" \
            "date 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}" \
            "time 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}" \
        )
    fi
else
    # vim未起動時のステータスライン設定
    # 以下は tmux-powerline デフォルトのテーマです。

    if [ -z $TMUX_POWERLINE_LEFT_STATUS_SEGMENTS ]; then
        TMUX_POWERLINE_LEFT_STATUS_SEGMENTS=(
            "tmux_session_info 148 234" \
            "hostname 33 0" \
            #"ifstat 30 255" \
            #"ifstat_sys 30 255" \
            "lan_ip 24 255 ${TMUX_POWERLINE_SEPARATOR_RIGHT_THIN}" \
            "wan_ip 24 255" \
            "vcs_branch 29 88" \
            "vcs_compare 60 255" \
            "vcs_staged 64 255" \
            "vcs_modified 9 255" \
            "vcs_others 245 0" \
        )
    fi

    if [ -z $TMUX_POWERLINE_RIGHT_STATUS_SEGMENTS ]; then
        TMUX_POWERLINE_RIGHT_STATUS_SEGMENTS=(
            #"earthquake 3 0" \
            "pwd 89 211" \
            "mailcount 9 255" \
            "now_playing 234 37" \
            #"cpu 240 136" \
            "load 237 167" \
            #"tmux_mem_cpu_load 234 136" \
            "battery 137 127" \
            "weather 37 255" \
            #"rainbarf 0 0" \
            #"xkb_layout 125 117" \
            "date_day 235 136" \
            "date 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}" \
            "time 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}" \
            #"utc_time 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}" \
        )
    fi
fi

上記は一例ですので、ご自由に変更して下さい。

また、バッファのディレクトリではなくvimのカレントディレクトリを表示させたい場合は、下記スクリプトを segment ディレクトリに追加し、テーマ設定ファイルに vim-cwd を追加して下さい。

ちなみに私の設定は以下にありますので、参考にどうぞ。

以上です。