Vim のファイラ選び
Vim には幾らかファイラがあります。
他にもいろいろあります。僕も昔は NERDTree を使っていたのですが、軽さを求めていたので dirvish にスイッチしました。
Big Sky :: Vim 上のファイラを NERDTree から dirvish に乗り換えた。
dirvish はとにかく何もしません。何もしないので機能が無いのですが、その分速いという訳です。README.md によると Netrw の2倍速いとのこと。
ただ、全てを気に入っているかというと、そういう訳ではなくて、幾らか不満もあります。
以下は僕がどうしても気に入らなかった2つの問題を解決する方法を紹介します。
-
で起動してしまう
デフォルトではノーマルモードの -
で dirvish が起動します。オペレータ等では反応しないので問題ないのですが、たまにキータイプをミスした時に画面を dirvish にすり替えられるのが許せませんでした。
ただしこの挙動は既にマッピングがあれば登録されない様になっているので以下を vimrc 入れておくことで回避出来ます。
nmap <Plug>(nomap-dirvish_up) <Plug>(dirvish_up)
検索プロンプトが独自
dirvish は独自で検索プロンプト /
をハックしており、ファイル名のみマッチする様に作り込まれています。それはそれで便利なのですが、これの実装がムズムズする実装なのです。/
をタイプすると
/\ze[^\/]*[\/]\=$
といった様に \ze[^\/]*[\/]\=$
という文字を強制で入れられてしまいます。要は /
を含まない後続部分にマッチしている訳ですが、こんなのが後ろに付いた状態で文字を入力したくない訳です。
運よく dirvish のバッファは dirvish
というファイルタイプを設定してくれているので、カスタマイズする事が出来ます。
augroup DirVish
au!
autocmd FileType dirvish (何か)
augroup END
ここでキーを無効にする為に以下の様に書いても良いかもしれません。
function! s:setup_dirvish()
nunmap <buffer> /
nunmap <buffer> ?
endfunction
augroup DirVish
au!
autocmd FileType dirvish :call s:setup_dirvish()
augroup END
もし「絶対にファイル名だけにマッチして欲しいけど、あの挙動だけは許せない」という人が居れば vim-prompter を使う事も出来ます。vim-prompter は Vim のコマンドラインを疑似するプラグインで、独自の補完やフックを行える様になっています。
function! s:on_enter(input)
echo "YOU MAN!: " . join(a:input, '')
endfunction
function! s:on_cancel(input)
echo "WHY JAPANESE PEOPLE!"
endfunction
call prompter#input({
\ 'prompt': '# ',
\ 'on_enter': function('s:on_enter'),
\ 'on_cancel': function('s:on_cancel'),
\})
この例を実行すると確定時に YOU WIN!
を、キャンセル時に WHY JAPANESE PEOPLE!
を表示します。
function! s:on_change(input)
call clearmatches()
exe "match Search /" . join(a:input, '') . "/"
endfunction
function! s:on_enter(input)
call clearmatches()
echohl Warning | echo "WHY JAPANESE PEOPLE!: " . join(a:input, '') | echohl None
endfunction
function! s:complete(input)
return split(glob(a:input[0] . '*'), "\n")
endfunction
call prompter#input({
\ 'color': 'Normal',
\ 'prompt': '/',
\ 'on_complete': function('s:complete'),
\ 'on_enter': function('s:on_enter'),
\ 'on_change': function('s:on_change'),
\})
on_complete
イベントや、on_change
イベントをフックする事でインクリメンタルサーチを実現する事も出来ます。
これを使って dirvish の /
を置き換えてしまった物が以下になります。
nmap <Plug>(nomap-dirvish_up) <Plug>(dirvish_up)
augroup DirVish
au!
autocmd FileType dirvish :call s:setup_dirvish()
augroup END
function! s:setup_dirvish()
nunmap <buffer> /
nunmap <buffer> ?
call prompter#ready()
nnoremap <buffer> / :<c-u>call <SID>search('/')<CR>
nnoremap <buffer> ? :<c-u>call <SID>search('?')<CR>
endfunction
function! s:search(dir)
let s:dir = a:dir
let s:pos = getpos('.')
call prompter#input({
\ 'prompt': a:dir,
\ 'prompt_color': 'Normal',
\ 'cursor': '_',
\ 'cursor_color': 'StatusLine',
\ 'histtype': '/',
\ 'on_change': function('<SID>on_change'),
\ 'on_enter': function('<SID>on_enter'),
\ 'on_cancel': function('<SID>on_cancel'),
\ })
endfunction
function! s:on_cancel(input)
call setpos('.', s:pos)
endfunction
function! s:on_enter(input)
let @/ = join(a:input, '') . '\ze[^\/]*[\/]\=$'
endfunction
function! s:on_change(input)
call setpos('.', s:pos)
call search(join(a:input, '') . '\ze[^\/]*[\/]\=$', s:dir == '/' ? '' : 'bw')
normal! 0
endfunction
あくまで疑似なので通常のプロンプトの動作とは異なります。これも嫌だという片は、おとなしく nunmap
したバージョンをお使い下さい。