Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

denite.nvimからfzf.vimに移行してみた

tl;dr

  • 操作性が良い
  • :Agコマンドが強すぎる
  • めっちゃカッコイイ!!

fzf.vimとは?

fzf.vimとはfzfを使ってファイルオープンやバッファ切り替えを行うツールです。denite.nvimと役割はかなり近いです。

fzf.vimの使い方

requirement

fzf本体を別途インストールする必要があります。公式ではホームディレクトリにインストールしていますが、$XDG_CACHE_HOME以下にインストールするとホームディレクトリが汚れなくて快適です。

$ git clone https://github.com/junegunn/fzf "$XDG_CACHE_HOME/fzf"
$ $XDG_CACHE_HOME/fzf/install --xdg --no-key-bindings --completion --no-update-rc

オプションはお好みで。

Gitを使う方法以外に、vimのプラグインとして、zshのプラグインとして管理する方法もあります(しかし結局、上の方法が一番問題が起こりづらいです)。

fzf.vimのインストール

fzf.vimをインストールします。以下ではdein.nvimを例に挙げています。その他の環境の場合はfzf.vimをご覧ください。

[[plugins]]
repo = 'junegunn/fzf.vim'
on_cmd = [
    'Files',
    'ProjectFiles',
    'Buffers',
    'BLines',
    'History',
    'Tags',
    'BTags',
    'GFiles',
    'Ag',
]
hook_add = '''
nnoremap <silent> ,a :<C-u>Ag<CR>
nnoremap <silent> ,f :<C-u>ProjectFiles<CR>
nnoremap <silent> ,b :<C-u>Buffers<CR>
nnoremap <silent> ,m :<C-u>History<CR>
set rtp+=$XDG_CACHE_HOME/fzf "$XDG_CACHE_HOMEの下にインストールした場合
" set rtp+=~/.fzf "~/.fzfにインストールした場合
'''

基本設定はこれでOKです。以下はかっこよくしたり、プロジェクトディレクトリで開くためのコードです。

hook_source = '''
function! s:find_git_root()
  " プロジェクトルートで開く
  return system('git rev-parse --show-toplevel 2> /dev/null')[:-2]
endfunction

command! ProjectFiles execute 'Files' s:find_git_root()
" command! -bang -nargs=? -complete=dir Files
"     \ call fzf#vim#files(<q-args>, fzf#vim#with_preview(), <bang>0)
command! -bang -nargs=? -complete=dir Files
    \ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline', '--preview', 'head -20 {}']}, <bang>0)



" Terminal buffer options for fzf
autocmd! FileType fzf
autocmd  FileType fzf set noshowmode noruler nonu

" 見た目をいい感じにする
" 参考: https://github.com/junegunn/dotfiles/blob/master/vimrc
"   https://github.com/junegunn/dotfiles/blob/master/vimrc
if has('nvim')
  function! s:create_float(hl, opts)
    let buf = nvim_create_buf(v:false, v:true)
    let opts = extend({'relative': 'editor', 'style': 'minimal'}, a:opts)
    let win = nvim_open_win(buf, v:true, opts)
    call setwinvar(win, '&winhighlight', 'NormalFloat:'.a:hl)
    call setwinvar(win, '&colorcolumn', '')
    return buf
  endfunction

  function! FloatingFZF()
    " Size and position
    let width = float2nr(&columns * 0.9)
    let height = float2nr(&lines * 0.6)
    let row = float2nr((&lines - height) / 2)
    let col = float2nr((&columns - width) / 2)

    " Border
    let top = '╭' . repeat('─', width - 2) . '╮'
    let mid = '│' . repeat(' ', width - 2) . '│'
    let bot = '╰' . repeat('─', width - 2) . '╯'
    let border = [top] + repeat([mid], height - 2) + [bot]

    " Draw frame
    let s:frame = s:create_float('Comment', {'row': row, 'col': col, 'width': width, 'height': height})
    call nvim_buf_set_lines(s:frame, 0, -1, v:true, border)

    " Draw viewport
    call s:create_float('Normal', {'row': row + 1, 'col': col + 2, 'width': width - 4, 'height': height - 2})
    autocmd BufWipeout <buffer> execute 'bwipeout' s:frame
  endfunction

  let g:fzf_layout = { 'window': 'call FloatingFZF()' }
endif
'''

使い方

:Filesまたは,fと入力するとカレントディレクトリのファイルが列挙された状態になります。エンターを押すと選択したファイルを新しいバッファーで開きます。カーソルはC-nC-pで候補を移動でき、<TAB>を押すと複数選択できます。

:Buffersは開いているバッファーの一覧を表示します。こちらは複数選択はできません。

agコマンドがインストールされている場合、:Agコマンドが利用できます。こちらはag '^(?=.)'の検索結果(カレントディレクトリ以下のすべてのファイルの内容)に対してfzfでフィルタリングするというものになっています。非常に動作が軽くて快適です。エンターを押すと該当ラインにカーソルが当たった状態でバッファーを開きます。

denite.nvimとfzf.vimの違い

PROS CONS
denite.nvim ・ ソースが豊富
・ registerを扱える
・ フィルタリングのレスポンスがfzfより悪い
fzf ・ 操作性が良い
:Agが便利
・ 動作が軽い
・ denite.nvimのregisterにあたるものがデフォルトではない

こんな感じです。フィルタリングがサクサクできるのはfzf.vimの大きなメリットだと思います。