ddu.vimの基本設定概観
この記事は何ではあって何ではないか
- ⭕: 私のddu.vimに対する基本的な理解を書く
- あくまでも「私なりの理解」の記述に重きを置いています
- 基本的な構造について書いています
- ❌: 設計思想には言及しない
- "思想"を語るべき立場にないと考えています
- あくまでも「私からの見え方」を記しています
- ❌: 網羅しない
- ddu.vimのすべての使い方の説明はしません
- 解説している内容はddu.vim全体のごく一部です
- 列挙も「概観を理解するうえで重要なもの」だけを挙げています
- ❌: ヘルプ・ガイドラインではない
- 本体付属のヘルプドキュメントや、リファレンスを代替するものではありません
- ❗: 断言する
- 実直に書くとすべての文が「思われます」「ようです」といった推測・曖昧さを残す表現を伴ってしまいます
- あえてこれらを省略して断言する表現に改め、読みやすくしています
はじめに: ddu.vimとは
ddu.vimは、Vim/Neovimその他テキストエディタによくみられるFuzzy Finderを代替するリストビュープラグインです。[1]
ddu.vimを構成する基本要素
ddu.vimは、それ本体だけでは何もできません。
これに次の3つの要素を組み合わせて、様々なリストの表示・選択・アクションを実現できます。
-
Source
-
Item
のリストを生成する
-
-
Kind
-
Item
のリストを受け取ってアクションを実行する関数群
-
-
UI
-
Item
のリストを表示する - ユーザーの
Item
の選択を受け付ける - ユーザーのアクション名の指定を受け付ける
-
また、3種類のFilter
を組み合わせて、Fuzzy Finderのようなリストの抽出・変換・整列を実現できます。
-
Filter
-
UI
-
Filter
に指定するためのユーザーのクエリ入力を受け取る
-
ddu.vim本体は、これらをつなぐ役目を負っています。
-
Source
からItem
のリストを受け取る -
Item
のリストをFilter
に通す -
Item
のリストをUI
に渡す -
UI
から選択されたItem
とアクションのリクエストを受け取る -
Kind
の、UI
から指定されたアクションを呼び出す
ddu.vimの使用方法
ここからはddu.vimを設定して、実際の使用方法を概説します。
インストール
まず、次のセットをインストールします。
さらに、お好みのUI
, Source
, Kind
をインストールします。
また、Item
をクエリの入力で絞り込みたい場合は、Matcher
をインストールします。
以下の節では、試用する上で分かりやすい以下4つのプラグインセットを前提として説明します。
- Fuzzy-Finder風の
UI
Shougo/ddu-ui-ff - ファイル一覧を取得する
Source
Shougo/ddu-source-file_rec - ファイルに関する処理を持つ
Kind
Shougo/ddu-kind-file - 部分文字列への完全一致で絞り込む
Matcher
Shougo/ddu-filter-matcher_substring
使用時の流れ
使う際には、次のようなフローをたどります。
# | 目的 | 実際の操作 |
---|---|---|
1 | ddu.vimで一覧を表示する | :call ddu#start({オプション}) |
2 |
Input 用のバッファを表示する |
:call ddu#ui#do_action("openFilterWindow") |
3 |
Item を絞り込むワードを入力する |
i キーワードを入力 <ESC>
|
4 | 一覧のバッファに移動する | :call ddu#ui#do_action("leaveFilterWindow") |
5 |
Item を選ぶ |
j や k で移動する |
6 |
Kind のアクションを呼び出す |
:call ddu#ui#do_action("itemAction", {"name": <アクション名>}) |
ここで呼び出している各処理をそれぞれ解説します。
ddu#start({オプション})
ddu.vimのSource
取得、UI
表示といったすべての処理の起点です。
オプションの例は後述します。
ddu#ui#do_action()
ddu.vimのUI
にアクションの呼び出しを要求します。
今回は例としてUI
にddu-ui-ffを使用しているため、呼び出しているアクションはddu-ui-ffで定義されたものです。
:help ddu-ui-ff-action-openFilterWindow
:help ddu-ui-ff-action-leaveFilterWindow
:help ddu-ui-ff-action-itemAction
itemAction
が少し複雑ですが、Item
に対応するKind
のアクションのうち、name
で指定された名前のものを呼び出すようddu.vimに要求します。
オプションの指定方法
ddu.vimのオプションには4つのレイヤーがあります。
- user:
ddu#start({dict})
に直接渡すオプション - local: 独自に名前を付けたオプションセット。
ddu#custom#patch_local({name}, {dict})
を使って設定する - global: 全体に共通する設定。
ddu#custom#patch_global({dict})
によって設定される - default: デフォルト値
ddu.vimはこれらをuser→local→global→defaultという優先順位でマージして使います。
そのため、globalで指定したオプションは、localの同じ名前のオプションで上書きされ、さらにuserのオプションで上書きされます。
また、使用するlocalオプションの名前(name
の値)自体も、user, globalでの指定に従います。
たとえば、
call ddu#custom#patch_global({
\ "option1": "foo" " !
\ "option2": "bar"
\ })
call ddu#custom#patch_local("local-name", {
\ "option2": "baz", " !
\ "option3": "qux", " !
\ "option4": "quux",
\ })
call ddu#start({
\ name = "local-name", " local-nameと名付けたlocalオプションを使用する
\ option4 = "corge", " !
\ option5 = "grault", " !
\ })
このように呼び出すと、次のようにオプションがマージされます。
- option1:
"foo"
- option2:
"baz"
- option3:
"qux"
- option4:
"corge"
- option5:
"grault"
これらのレイヤーにより、
- すべての
ddu#start()
で共通する設定はglobal -
ddu#start()
する際のコンテキストに依存しない設定はlocal -
ddu#start()
する際のコンテキストに依存する設定はuser
というように設定できます。
オプションの構成
オプションは各構成要素ごとに分かれています。
-
UI
の設定 -
Source
の設定 -
Filter
の設定 -
Kind
の設定
各構成要素のためのオプションには、Option
とParam
があります。
例えば、Source
のためのOption
は、次のように設定します。
\ "sourceOptions": {
\ "_": {
\ ... # すべてのSourceに適用するOptions
\ },
\ "file_rec" {
\ ... # file_rec Sourceだけに適用するOptions
\ },
\ }
内容の詳細は各ヘルプに詳しく記載されています。
:help ddu-option-ui
:help ddu-option-uiOptions
:help ddu-option-uiParams
:help ddu-option-filterOptions
:help ddu-option-filterParams
:help ddu-option-sources
:help ddu-option-sourceOptions
:help ddu-option-sourceParams
注意点として、ui
や sources
には
- どの
UI
/Source
を使うか - 適用する
Options
、Params
を同時に指定できます。例えば
\ "sources": [{
\ "name": "file_rec",
\ "params": {
\ "ignoredDirectories": ["node_modules"]
\ },
\ "options:" {
\ "matchers": ["substring"]
\ }
\ }]
と
\ "sources": ["file_rec"],
\ "sourceParams": {
\ "file_rec": {
\ "ignoredDirectories": ["node_modules"]
\ }
\ },
\ "sourceOptions": {
\ "file_rec": {
\ "matchers": ["substring"]
\ }
\ }
は同じ意味です。
global, local, userといったオプションのレイヤーを分割する際や、複数のSource
をまたいで共通するOption
を設定する際など、場合によって使いやすい方を選んで使用します。
また、どのKind
を使用するか、は原則的にSource
によって決定されます。
Source
のヘルプには、どのKind
を必要とするかが明記されています。
例::help ddu-source-file_rec-install
実際の設定例
実際に以下の様な設定を例示します。
- 現在のディレクトリ(
getcwd()
)配下のファイルをFuzzy Finder UIで表示する - 2種類の設定でddu.vimを利用する
- コマンド
:DduNodeFiles
:.git/
node_modules/
ディレクトリ配下を無視する - コマンド
:DduWholeFiles
: ファイルを無視せず、50,000件を上限とする
- コマンド
- 部分文字列の完全一致による絞り込みを可能とする
- 選んだ
Item
をe
キーで開く
" 以下各プラグインをインストールしておく
" vim-denops/denops.vim
" Shougo/ddu.vim
" Shougo/ddu-ui-ff
" Shougo/ddu-source-file_rec
" Shougo/ddu-kind-file
" Shougo/ddu-filter-matcher_substring
" 全体に共通する設定を行う
call ddu#custom#patch_global({
\ "ui": "ff",
\ "sourceOptions": {
\ "_": {
\ "matchers": ["matcher_substring"]
\ },
\ },
\ })
" DduNodeFilesで使用する設定を用意する
call ddu#custom#patch_local("node-files", {
\ "sources": ["file_rec"],
\ "sourceParams": {
\ "file_rec": {
\ "ignoredDirectories": [".git", "node_modules"],
\ }
\ }
\ })
" DduWholeFilesで使用する設定を用意する
call ddu#custom#patch_local("whole-files", {
\ "sources": ["file_rec"],
\ "sourceParams": {
\ "file_rec": {
\ "ignoredDirectories": [],
\ }
\ },
\ "sourceOptions": {
\ "file_rec": {
\ "maxItems": 50000
\ }
\ }
\ })
" ddu-ui-ff上でのみ有効なKeymap(`e`)を設定する
autocmd FileType ddu-ff call s:ddu_ff_settings()
function s:ddu_ff_settings() abort
nnoremap <buffer> e <Cmd>call ddu#ui#do_action('itemAction', {'name': 'open'})<CR>
endfunction
" ddu#startを各オプションセット名で呼び出すコマンドを準備する
command! DduNodeFiles call ddu#start({"name": "node-files", "sourceOptions": {"file_rec": {"path": getcwd()}}})
command! DduWholeFiles call ddu#start({"name": "whole-files", "sourceOptions": {"file_rec": {"path": getcwd()}}})
終わりに
ここからは、今回の記事の主旨(基礎的な概観)からは外れた実用、感想を含む内容です。
実用上のコツ
ddu.vimはかなりのユースケースに対応可能な柔軟性を持っています。
「設定」の範囲内で、かなりの不満を解消できます。
何か不満が生じたときのためのコツがいくつかあります。
-
Source
で様々なユースケースを吸収しようとしない- 表示が気に食わない→
Filter
(Converter
)で変換すればよい - XXがリストに含まれないのが気に食わない→複数の
Source
を混ぜればよい - アクションが気に食わない→Custom Actionや、Action Overwriting(
:help ddu-source-option-actions
)を設定すれば良い
- 表示が気に食わない→
-
Kind
に完全性を求めない- Custom Actionを使う
- Custom Actionで
push
(:help ddu-option-push
)を使って別のSource
につなぐ
- すべてをKeymapしない
- chooseAction (
:help ddu-ui-ff-action-chooseAction
や:help ddu-ui-filer-action-chooseAction
)を活用する
- chooseAction (
- insertモードで色々と操作しようとしない
- クエリを入力するモード(insertモード)とItemを選択するモード(normalモード)は分ける
- Vimらしい、モードごとに分かれた挙動とした方が何かと困難に遭遇しにくい
これらについてはこの記事では列挙するのみにとどめ、詳細はいずれ別記事を起こすかもしれません。
Loves ddu.vim
ddu.vimの設定はかなり柔軟性をもっており、その実現のために1つ1つの設定から得られる情報の結合度が低く、俯瞰して統合した知識を得ることが難しいように感じました。
そこで1つの挑戦として、私なりの理解した内容を俯瞰して記事にしてみました。
ddu.vimの柔軟性には大変助けられる部分が大きく、既存のFuzzy Finderをカスタムしようと苦労した人ほど、嬉しいプラグインだと感じています。
他にも同じように苦しんでいる人がいれば、この記事が導入の一助となれれば幸いです。
Discussion
ddu#custom#patch_local()
の使い方もわかって設定をだいぶ整理できました。ありがとうございます。