lightline.vim を使って vim のステータスラインをカスタマイズ

先日 [vim-powerline](https://github.com/Lokaltog/vim-powerline) から [vim-airline](https://github.com/bling/vim-airline) に乗り換えたばかりだったのですが、あっさり [lightline.vim](https://github.com/itchyny/lightline.vim) に乗り換えてしまいました。

理由は、lightline.vim 作者さんの以下記事に共感したからです。

- [lightline.vim作りました - プラグインの直交性について - プログラムモグモグ](http://d.hatena.ne.jp/itchyny/20130824/1377351527)

また、設定方法が直感的で分かりやすい点や、カスタマイズしやすい点なども気に入りました。

# インストール

```vim
NeoBundle 'itchyny/lightline.vim'
```

今回のカスタマイズでは、以下のプラグインと連携させているので入れておくと良いです。
(無くてもエラーになったりはしません)

```vim
NeoBundle 'tpope/vim-fugitive'
NeoBundle 'airblade/vim-gitgutter'
```

NeoBundle 以外のインストール方法は、[README](https://github.com/itchyny/lightline.vim/blob/master/README.md) 読んで下さい。

# カスタマイズ

おすすめの設定ですが、[README](https://github.com/itchyny/lightline.vim/blob/master/README.md) を上から順に試していくのも良いですが、作者さんの設定を真似るのが一番手っ取り早いです。

作者さんの設定は、[README](https://github.com/itchyny/lightline.vim/blob/master/README.md) の一番最後に記載されています。
もしくは、直接 [作者さんの .vimrc](https://github.com/itchyny/dotfiles/blob/master/.vimrc) を参考にしましょう。

さらに今回は、カーソル下の文字コード表示と、[vim-gitgutter](https://github.com/airblade/vim-gitgutter)と連携してGitの追加/変更/削除のハンク数も表示させるようにしました。

![lightline-vim.png](https://qiita-image-store.s3.amazonaws.com/0/10548/9d5db33e-111c-23ad-c5d1-f5e5122a9fab.png)

以下が最終的な設定です。

特に解説はしませんが lightline.vim の設定方法は非常に直感的で分かりやすいので、すぐに理解できると思います。
また、[README](https://github.com/itchyny/lightline.vim/blob/master/README.md) がチュートリアル方式になっているので、もし分からなければ読んでみると良いでしょう。

```vim
" vim-gitgutter
let g:gitgutter_sign_added = '✚'
let g:gitgutter_sign_modified = '➜'
let g:gitgutter_sign_removed = '✘'

" lightline.vim
let g:lightline = {
        \ 'colorscheme': 'landscape',
        \ 'mode_map': {'c': 'NORMAL'},
        \ 'active': {
        \   'left': [
        \     ['mode', 'paste'],
        \     ['fugitive', 'gitgutter', 'filename'],
        \   ],
        \   'right': [
        \     ['lineinfo', 'syntastic'],
        \     ['percent'],
        \     ['charcode', 'fileformat', 'fileencoding', 'filetype'],
        \   ]
        \ },
        \ 'component_function': {
        \   'modified': 'MyModified',
        \   'readonly': 'MyReadonly',
        \   'fugitive': 'MyFugitive',
        \   'filename': 'MyFilename',
        \   'fileformat': 'MyFileformat',
        \   'filetype': 'MyFiletype',
        \   'fileencoding': 'MyFileencoding',
        \   'mode': 'MyMode',
        \   'syntastic': 'SyntasticStatuslineFlag',
        \   'charcode': 'MyCharCode',
        \   'gitgutter': 'MyGitGutter',
        \ },
        \ 'separator': {'left': '⮀', 'right': '⮂'},
        \ 'subseparator': {'left': '⮁', 'right': '⮃'}
        \ }

function! MyModified()
  return &ft =~ 'help\|vimfiler\|gundo' ? '' : &modified ? '+' : &modifiable ? '' : '-'
endfunction

function! MyReadonly()
  return &ft !~? 'help\|vimfiler\|gundo' && &ro ? '⭤' : ''
endfunction

function! MyFilename()
  return ('' != MyReadonly() ? MyReadonly() . ' ' : '') .
        \ (&ft == 'vimfiler' ? vimfiler#get_status_string() :
        \  &ft == 'unite' ? unite#get_status_string() :
        \  &ft == 'vimshell' ? substitute(b:vimshell.current_dir,expand('~'),'~','') :
        \ '' != expand('%:t') ? expand('%:t') : '[No Name]') .
        \ ('' != MyModified() ? ' ' . MyModified() : '')
endfunction

function! MyFugitive()
  try
    if &ft !~? 'vimfiler\|gundo' && exists('*fugitive#head')
      let _ = fugitive#head()
      return strlen(_) ? '⭠ '._ : ''
    endif
  catch
  endtry
  return ''
endfunction

function! MyFileformat()
  return winwidth('.') > 70 ? &fileformat : ''
endfunction

function! MyFiletype()
  return winwidth('.') > 70 ? (strlen(&filetype) ? &filetype : 'no ft') : ''
endfunction

function! MyFileencoding()
  return winwidth('.') > 70 ? (strlen(&fenc) ? &fenc : &enc) : ''
endfunction

function! MyMode()
  return winwidth('.') > 60 ? lightline#mode() : ''
endfunction

function! MyGitGutter()
  if ! exists('*GitGutterGetHunkSummary')
        \ || ! get(g:, 'gitgutter_enabled', 0)
        \ || winwidth('.') <= 90
    return ''
  endif
  let symbols = [
        \ g:gitgutter_sign_added . ' ',
        \ g:gitgutter_sign_modified . ' ',
        \ g:gitgutter_sign_removed . ' '
        \ ]
  let hunks = GitGutterGetHunkSummary()
  let ret = []
  for i in [0, 1, 2]
    if hunks[i] > 0
      call add(ret, symbols[i] . hunks[i])
    endif
  endfor
  return join(ret, ' ')
endfunction

" https://github.com/Lokaltog/vim-powerline/blob/develop/autoload/Powerline/Functions.vim
function! MyCharCode()
  if winwidth('.') <= 70
    return ''
  endif

  " Get the output of :ascii
  redir => ascii
  silent! ascii
  redir END

  if match(ascii, 'NUL') != -1
    return 'NUL'
  endif

  " Zero pad hex values
  let nrformat = '0x%02x'

  let encoding = (&fenc == '' ? &enc : &fenc)

  if encoding == 'utf-8'
    " Zero pad with 4 zeroes in unicode files
    let nrformat = '0x%04x'
  endif

  " Get the character and the numeric value from the return value of :ascii
  " This matches the two first pieces of the return value, e.g.
  " "<F>  70" => char: 'F', nr: '70'
  let [str, char, nr; rest] = matchlist(ascii, '\v\<(.{-1,})\>\s*([0-9]+)')

  " Format the numeric value
  let nr = printf(nrformat, nr)

  return "'". char ."' ". nr
endfunction
```

あとは気に入らない部分を自分好みに変えていくと良いかと思います。

- vim-gitgutter の sign は私の好みで変えてるだけなので、別にデフォルトのままでも良いです
- `separator` と `subseparator` は [vim-powerline](https://github.com/Lokaltog/vim-powerline) のものなので、対応していない方は設定を削除するか、フォントに[パッチ](https://github.com/Lokaltog/vim-powerline/tree/develop/fontpatcher)を当てて下さい。[powerline](https://github.com/Lokaltog/powerline) を使ってる方はそっちでもおk

私の最新の設定はGithubに置いてあるので、良ければ何かの参考にでも。

- [dotfiles/.vimrc.plugins_setting at master · yonchu/dotfiles](https://github.com/yonchu/dotfiles/blob/master/.vimrc.plugins_setting)


## 追記

### 2010/08/28

- ファイル名を取得する関数(MyFilename())内の `expand(%t)` を `expand(%:t)` に修正 (←タイポです)

    `%:t` でファイル名のみの表示になります。
    以前のようにパスも含めて表示したい場合は、`expand('%')` として下さい。(`t` は要りません)