unite.vimより高速なdenite.nvimを使う

  • 102
    いいね
  • 3
    コメント

Denite

Denite.nvim is a dark powered Neovim unite all interfaces. It resolves unite.vim problems. It is 10 times faster than unite.vim.

暗黒の力を手に入れた云々。早い
パッと動かしたい人は操作方法の項まで見れば動かせる文章構成にしています。

こんな感じ

asciicast

インストール

python3を持ってないといけません。
pyenvとpyenv-virtualenvを使っている場合

# pyenv install 3.5.2
# 2016/9/22 update 後述するcpsmを利用する場合動的リンクを含む以下の方法でインストールしてください。
env PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install 3.5.2
pyenv virtualenv 3.5.2 neovim3
pyenv activate neovim3
pip install neovim

生のpython3を使っている方は

pip3 install neovim

とかでいいかもしれません。
ここら辺は詳しくはNeovim Wikiに懇切丁寧にかいてあるので、こちらを見てみると良いです。

python3のbinを指定してあげます。

.vimrc
let g:python3_host_prog = expand('~/.pyenv/versions/neovim3/bin/python')
" 上に記載した方法を取っていない方は which python3 とかしてそのPATHを設定してください。

neovimを起動して:echo has('python3')で1が返ってきた場合、設定できています。

0が返ってきた場合はどっかの設定が間違っています。vim-jpの方はみなさん優しいので問い合わせましょう。

本体のインストールは使っているプラグインマネージャーによって違うかと思いますが、

.dein.toml
[[plugins]]
repo = 'Shougo/denite.nvim'

こんな感じです。
:UpdateRemotePlugins
をneovimないで呼び出してください。

remote/host: python3 host registered plugins ['denite', 'deoplete']
remote/host: generated rplugin manifest: /Users/okamos/.local/share/nvim/rplugin.vim

こんな感じのメッセージが出てくると思います。deniteがあれば成功しています。

用例

ここでは大半の人が使うであろうdenite.nvimの実行集をみていきます。
実際に実行してみて、次項の「操作方法」をみながら操作してみてください。

コマンド 候補 候補選択時のアクション
:Denite file_rec カレントディレクトリ以下のファイル ファイルを開く
:Denite -auto_preview grep 検索結果(プレビュー付き) 検索結果の行を開く
:DeniteCursorWord grep 検索結果(カーソル以下の文字をインプットにする) 検索結果の行を開く
:Denite -resume 前回のDeniteバッファを再表示する 前回の動作に準ずる
:Denite file_mru 最近開いたバッファ(neo_mru.vim依存) ファイルを開く
:Denite neoyank ヤンクの履歴(neoyank.vim依存) ペースト

file_recやgrepをagに変更する場合はdeniteのプラグイン読み込み終了後に以下のコマンドを実行します。dein.vimを使っている場合hook_post_source内に記述すると良いです。

call denite#custom#var('file_rec', 'command', ['ag', '--follow', '--nocolor', '--nogroup', '-g', ''])
call denite#custom#var('grep', 'command', ['ag'])
call denite#custom#var('grep', 'recursive_opts', [])
call denite#custom#var('grep', 'pattern_opt', [])
call denite#custom#var('grep', 'default_opts', ['--follow', '--no-group', '--no-color'])

操作方法

共通

キー マップ
<Esc> 以前のモードに戻るか、Deniteのバッファを閉じます
<C-c> Deniteのバッファを閉じます
<CR>(Enter) デフォルトのアクションを実行します
<C-z> Deniteを中断します、CRで再開します

挿入モード

キー マップ
<C-h> 一文字消します
<BS> 一文字消します
<C-w> 一単語消します
<C-u> 一行消します
<C-g> 次の行に移動します
<Tab> 次の行に移動します
<C-t> 前の行に移動します
<S-Tab> 前の行に移動します
<C-j> Vimのコマンドラインから文字を入力します
<C-r> レジスタから貼り付けします
<C-o> ノーマルモードに切り替えます
<C-v> プレビューを表示します

ノーマルモード

キー マップ
i 挿入モードに切り替えます
j 次の行に移動します
k 前の行に移動します
g 最初の行に移動します
G 最後の行に移動します
<C-d> ウィンドウの下方向に移動します
<C-u> ウィンドウの上方向に移動します
<C-f> 次のページに移動します
<C-b> 前のページに移動します
p プレビューを表示します
q Deniteのバッファを閉じます
<Tab> アクションを選択します

こうなっています。マッピングは変更可能で、

call denite#custom#map('insert', "<C-d>", '<denite:delete_char_under_caret>', 'noremap')

のようにして追加・修正することが可能です。
<C-c>は変更することができません。

コマンド

コマンド 概要
:Denite 標準のコマンドです
:DeniteBufferDir 現在開いているバッファのディレクトリをターゲットとして:Deniteを実行します。私は絞り込んでfile_recしたい時によく使います
:DeniteCursorWord カーソル配下にある言葉をターゲットにして:Deniteを実行します。私はgrepする時によく使います
:DeniteProjectDir プロジェクトのルートディレクトリ(と思われる箇所)をターゲットとして:Deniteを実行します

オプション

オプションは:Denite -options file_recのように指定します。
例えば:Denite -auto_preview -mode=normal file_recとするとノーマルモードで自動的にプレビューが開く設定でfile_recを実行します
オプションは頭に-no-をつけることで無効化することができます。あまり使う必要は無いでしょうが...

オプション 概要 デフォルト値
-auto-preview 別の候補へ移動した際に自動的にプレビューを開きます false
-default-action={action} 指定したアクションをデフォルトアクションとします。後述するsplitなどのアクションを指定します "default"
-immediately 候補が存在する場合デフォルトのアクションを直ちに実行します false
-input={text} 指定したテキストを入力済みの状態で実行します ""
-mode={mode} normalかinputを指定します "insert"
-quit アクションを実行後にDeniteのバッファを閉じます。 true
-resume 以前のバッファを使います。 false
-cursor-pos +1や-1といった番号で指定した候補に移動します。 ""
-statusline ステータスを表示します。デフォルトでオンの機能です true

ソース

いわゆる選択候補です

ソース 候補 選択時の動作
buffer バッファ バッファに飛びます
colorscheme カラースキーマ カラースキーマを変更します
directory_rec ディレクトリ チェンジディレクトリします(バッファローカル)
file_rec ファイル 開きます
filetype ファイルの種類 filetypeを変更します
command vimのコマンド exモードで挿入します
grep grepの結果 行へ飛びます
help Vimドキュメント内のタグ タグに飛びます
menu 予め設定した項目(後述) デフォルトアクション
file_mru neomruのmru ファイルを開く
neo_yank neoyank.vimのヤンク履歴 ペースト

menu

以下のように:call denite#custom#var('menu', 'menus', var)で設定した項目を列挙して絞り込みアクションできます。

let s:menus = {}
let s:menus.zsh = { 'description': 'zsh configuration' }
let s:menus.zsh.file_candidates = [
\ ['zshrc', '~/.zshrc'], ['zplug', '~/.init.zplug']]
let s:menus.my_commands = { 'description': 'my commands' }
let s:menus.my_commands.command_candidates = [
\ ['Split the window', 'vnew'], ['Open zsh menu', 'Denite menu:zsh']]

call denite#custom#var('menu', 'menus', s:menus)

設定したものは:Denite menu:zshのように呼び出すことができます。
二重の配列になっている配列の一個目が一覧に列挙されます。
file_candidatesの場合は配列の二個目をファイルとして開き、command_candidatesでは配列の二個目をvimのコマンドとして実行します。
をかけて、アクション(ペースト)します。

アクションの候補

候補の種類によって実行できるアクションが違います

候補の種類 アクション 概要
コマンド execute 実行する
ディレクトリ cd チェンジディレクトリ
ファイル open 開く(default)
ファイル preview プレビュー
ファイル tabopen 新しいタブで開く
ファイル split 水平分割で開く
ファイル vsplit 垂直分割で開く

フィルター

候補を絞り込む際に候補と入力のマッチング -> 並び替え -> 出力を整形しているようです。

call denite#custom#source('file_rec', 'matchers', ['mather_fuzzy'])

のようにソース、フィルター、値(配列)で設定します。

フィルター 概要
matcher_cpsm 高速に絞り込み検索をおこなうcpsmを利用します。詳しくは後述
matcher_fuzzy いわゆるあいまい検索します(default)
matcher_ignore_globs globのパターン(複数)を弾いた状態で検索します
matcher_regexp 正規表現で検索します。正規表現を利用する場合はcpsmとfuzzyとチェーンしても意図した結果は得られません
sorter_rank selectaというスコアリングアルゴリズムを使って並び替えます。詳しくは知りません
sorter_sublime おそらくsublimeに使われているスコアリングアルゴリズムを使って並び替えるのでしょう。
converter_relative_word 相対パスを使って候補を出力します

matcher_cpsmについて

表にあるリンクを見れば大体わかるかと思いますが、一応導入方法を記載しておきます。
OS Xでは依存としてboostがあるので

brew install boost

しておきます。

dein.vimを利用しているなら

dein.toml
[[plugins]]
repo = 'nixprime/cpsm'
build = 'env PY3=ON ./install.sh'

で大丈夫です。env PY3=ONはpython3でビルドするためのオプションでVimが+python3になっている場合は自動検出されてpython3でビルドされるようです。(私はneovimしか使っていないので使っています)
ここで動的リンクが検出されるのですが、pyenvだと上述の env PYTHON_CONFIGURE_OPTS="--enable-framework" でpythonをインストールしている必要があるそうです。
動的リンクが必要なことまでは理解していたのですが、よくわからなくなってIssue立てちゃいました...作者であるnixprime氏が数時間後にこの回答をしてくれてすごく助かりました。

call denite#custom#source('file_rec', 'matcher', ['matcher_cpsm'])

matcherを変更する場合は上述のように書きます。

応用

リンクされた記事からの受け売りですが、

:Denite -resume -immediately -cursor-pos=+1 "以前のバッファで次の候補を即座に開く
:Denite -resume -immediately -cursor-pos=-1 "以前のバッファで前の候補を即座に開く

@pocariさんありがとうございます

私の設定

dein.vimにおける設定

dein_lazy.toml
repo = 'Shougo/denite.nvim'
depends = ['neomru.vim']
on_event = 'BufRead'
hook_add = '''
nmap <silent> <C-u><C-t> :<C-u>Denite filetype<CR>
nmap <silent> <C-u><C-p> :<C-u>Denite file_rec<CR>
nmap <silent> <C-u><C-j> :<C-u>Denite line<CR>
nmap <silent> <C-u><C-g> :<C-u>Denite grep<CR>
nmap <silent> <C-u><C-]> :<C-u>DeniteCursorWord grep<CR>
nmap <silent> <C-u><C-u> :<C-u>Denite file_mru<CR>
nmap <silent> <C-u><C-y> :<C-u>Denite neoyank<CR>
nmap <silent> <C-u><C-r> :<C-u>Denite -resume<CR>
nmap <silent> <C-u>; :<C-u>Denite -resume -immediately -select=+1<CR>
nmap <silent> <C-u>- :<C-u>Denite -resume -immediately -select=-1<CR>
nmap <silent> <C-u><C-d> :<C-u>call denite#start([{'name': 'file_rec', 'args': ['~/dotfiles']}])<CR>
nnoremap ml :<C-u>call denite#start([{'name': 'file_rec', 'args': [g:memolist_path]}])<CR>
'''
hook_post_source = '''
call denite#custom#var('file_rec', 'command',
\ ['pt', '--follow', '--nocolor', '--nogroup', '--hidden', '-g', ''])
call denite#custom#var('grep', 'command',
\ ['pt', '--nogroup', '--nocolor', '--smart-case', '--hidden'])
call denite#custom#var('grep', 'default_opts', [])
call denite#custom#var('grep', 'recursive_opts', [])
'''

こんな感じでマッピングしています。
denite#custom#*はプラグイン読み込みが終わってからじゃないと動作しないので注意してください。
file_recはデフォルトはfindですがagやackなどに変えることができます。
grepのdefault_optsやrecursive_optsは不要であれば配列だけを渡しておけば大丈夫です。(ptはデフォルトでrecursiveです)

個人的にcolorschemeやmenuはあまり頻繁に使うもののように思えず設定しておりません。

余談

なぜかカーソルラインのfgが設定されていなかったので、最初選択行がどれなのか全くわかりませんでした。
現在はドキュメントのFAQに記載されているので戸惑うこともないかと思います。

.vimrc
hi CursorLine guifg=#E19972

Shougoさんへの感謝の気持ちで溺れそう。