Vimのstatuslineを最適化する

FuzzyFinderのbufferモードやmrufileモードの補完メニューでパスの真ん中が省略されているのがわかりやすかったので、statuslineにも導入してよりわかりやすくしようという試み。インストール済みのGreasemonkeyスクリプトをちょっと編集する時など、ものすごく長いパスのファイルを編集する時のみ便利。

Vimのデフォルトのstatuslineは以下のようなもの。

デフォルトのstatuslineのスクリーンショット

これにファイルの種類や文字コード・改行コードなどあると便利な情報を追加した上で、ファイル名を先頭に持ってきて、残りのパスを%<を利用して省略させるようにすると、

ビルトインの省略機能を利用したカスタマイズ済みのstatuslineのスクリーンショット

こんな感じになる。このstatuslineのコードは、

set statusline=%{expand('%:p:t')}\ %<\(%{expand('%:p:h')}\)%=\ %m%r%y%w%{'['.(&fenc!=''?&fenc:&enc).']['.&ff.']'}[%3l,%3c]

というもので、しばらくこれを使っていた。悪くはないが、パスの先頭を省略するような書き方なのでドライブレターが見えなくなってしまいWindowsだとちょっとアレ。これをベースにFuzzyFinderから長いパスの中間を省略する関数をパクって最適化すると、

最適化されたstatuslineのスクリーンショット

こうなる。ドライブレターも見えるし、ファイルのあるフォルダ名も大体見えるのでわかりやすい!

set statusline=%{expand('%:p:t')}\ %<\(%{SnipMid(expand('%:p:h'),80-len(expand('%:p:t')),'...')}\)%=\ %m%r%y%w%{'['.(&fenc!=''?&fenc:&enc).']['.&ff.']'}[%3l,%3c]

function! SnipMid(str, len, mask)
  if a:len >= len(a:str)
    return a:str
  elseif a:len <= len(a:mask)
    return a:mask
  endif

  let len_head = (a:len - len(a:mask)) / 2
  let len_tail = a:len - len(a:mask) - len_head

  return (len_head > 0 ? a:str[: len_head - 1] : '') . a:mask . (len_tail > 0 ? a:str[-len_tail :] : '')
endfunction

SnipMid()はFuzzyFinderからコピペしただけ(autoload/fuf.vimの505行目あたりにある)。切り詰める長さはSnipMid()の第二引数で指定する。ここでは、

80-len(expand("%:p:h"))

と80からファイル名を引いた数で切り詰めているが、ターミナルの横幅やcolumnsにあわせて要調節。set columns=120な環境だとこれくらいが丁度良かった。頑張れば環境に合わせてフレキシブルに切り詰める長さを調節できそうだけど面倒なので……。

titlestringに使っても良い。

set titlestring=%{expand('%:p:t')}%(\ %m%r%w%)\ %<\(%{SnipMid(expand('%:p:h'),80-len(expand('%:p:t')),'...')}\)\ -\ Vim

Vimはどうにかしようと思うと大抵はどうにかできて幸せ……。