NERDTreeで選択中のノードに対してfzfでファイルを検索する
vimでNERDTreeというファイラプラグインを使っているのですが,NERDTreeで選択中のノードを起点にfzfでファイル検索したいなあと思って,設定を書いてみました.
環境
$ vim --version | head -4
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Dec 19 2020 21:23:05)
macOS version
Included patches: 1-2164
Compiled by root@Mac-1608412769109.local
$ (cd ~/.vim/bundles/repos/github.com/junegunn/fzf && git rev-parse HEAD)
bf447d77035c0c67f4c9306696bd5541cbcb3e11
$ (cd ~/.vim/bundles/repos/github.com/junegunn/fzf.vim && git rev-parse HEAD)
d43df0ea2f099836c2e3499756101e87bcbd3e25
$ (cd ~/.vim/bundles/repos/github.com/scrooloose/nerdtree && git rev-parse HEAD)
aaa946fb6bd79b9af86fbaf4b6b63fd81d839bd9
.vimrc
NERDTreeのキーマップAPIを使い,NERDTreeでファイルノードかディレクトリノードを選択中にzf
をタイプすることでファイル検索を,
zg
をタイプすることでgrep(ripgrep)検索を行えるようにしました.
キーマップAPIのヘルプは:help NERDTreeKeymapAPI
で参照できます.
.vimrc
" function to find file under current node
function! NERDTreeFindFile(node)
if a:node.path.isDirectory == 1
let path = a:node.path.str()
else
let path = a:node.path.getDir().str()
endif
echo path
NERDTreeClose
call fzf#vim#files(path)
endfunction
" function to grep files under current node
function! NERDTreeGrepFile(node)
if a:node.path.isDirectory == 1
let path = a:node.path.str()
else
let path = a:node.path.getDir().str()
endif
NERDTreeClose
call fzf#vim#grep("rg --column --line-number --no-heading --color=always --smart-case \"\" ".shellescape(path), 1, fzf#vim#with_preview())
endfunction
augroup nerdtree
autocmd!
" find file under current node
autocmd VimEnter * call NERDTreeAddKeyMap({
\ 'key': 'zf',
\ 'callback': 'NERDTreeFindFile',
\ 'quickhelpText': 'find file under current node',
\ 'scope': 'Node' })
" grep files under current node
autocmd VimEnter * call NERDTreeAddKeyMap({
\ 'key': 'zg',
\ 'callback': 'NERDTreeGrepFile',
\ 'quickhelpText': 'grep files under current node',
\ 'scope': 'Node' })
augroup END
NERDTreeAddKeyMap
は.vimrcを読み込むタイミングではNot a editor command
というエラーが出てしまうので,VImEnterのタイミングで呼ぶようにしました.
NERDTreeを開いていると,NERDTreeのウィンドウでファイルが開いてしまうので,fzfのファンクションを呼ぶ前にNERDTreeを閉じています. できればNERDTreeは開いたまま,NERDTreeでファイル選択したときにファイルが開くウィンドウで開くようにしたかったのですが, うまい方法が思いつかなったので,このようにしています.
ちなみに,zf
したときのファイル検索で,ファイルを開くのではなく,NERDTree上でファイルを選択(フォーカス)したい場合は,
NERDTreeFindFile
ファンクションを次のようにすることで実現できます.
.vimrc
" function to find file under current node
function! NERDTreeFindFile(node)
if a:node.path.isDirectory == 1
let path = a:node.path.str()
else
let path = a:node.path.getDir().str()
endif
let args = {
\ 'source': 'rg --files -- ' . path,
\ 'sink': { lines -> lines },
\ 'down': '~50%',
\ }
let list = fzf#run(fzf#wrap(args))
if len(list)
execute 'NERDTreeFind' list[0]
endif
endfunction