LoginSignup
21
14

More than 5 years have passed since last update.

軽量ディレクトリビューワ dirvish をカスタマイズする方法

Last updated at Posted at 2017-12-04

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 したバージョンをお使い下さい。

21
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
14