An Overview of Basic Settings for ddu.vim
What This Article Is and Is Not About
- ✅: Writing about my understanding of ddu.vim
- Focused on "my understanding"
- Describes the basic structure
- ❌: Does not describe design philosophy
- I do not consider myself in a position to talk about the "philosophy"
- It's just "how I see it"
- ❌: Not exhaustive
- Does not explain all ways to use ddu.vim
- Only covers a small part of ddu.vim
- Only includes "important things for understanding the overview"
- ❌: Not a help or guideline
- Not a substitute for the help documentation or reference
- ❗: Assertive
- To avoid all sentences having a speculative or vague expression like "it seems," "it appears"
- Deliberately omits these to make it easier to read
Introduction: What is ddu.vim?
ddu.vim is a list view plugin that replaces the Fuzzy Finder commonly seen in Vim/Neovim and other text editors. [1]
Basic Components of ddu.vim
ddu.vim itself can't do anything.
By combining the following three elements, it can display various lists, select items, and perform actions:
-
Source
- Generates a list of
Item
s
- Generates a list of
-
Kind
- Takes a list of
Item
s and executes actions
- Takes a list of
-
UI
- Displays the list of
Item
s - Accepts user selections of
Item
s - Accepts user-specified action names
- Displays the list of
Also, by combining three types of Filter
, you can extract, transform and sort items like Fuzzy Finder:
-
Filter
-
UI
- Receives user query input for passing to
Filter
s
- Receives user query input for passing to
ddu.vim connects them:
- Receives a list of
Item
s fromSource
- Passes the list of
Item
s throughFilter
- Gives the list of
Item
s toUI
- Receives the selected
Item
and action request fromUI
- Calls the action specified by
UI
inKind
How to Use ddu.vim
I outline how to set up and use ddu.vim in practice.
Install
First, install the following set:
Additionally, install your preferred UI
, Source
, and Kind
.
If you want to filter Item
s by query input, install a Matcher
.
In the following sections, I assume a set of four plugins that are easy to try out:
- Fuzzy-Finder-like
UI
Shougo/ddu-ui-ff -
Source
that retrieves a list of files Shougo/ddu-source-file_rec -
Kind
that handles file-related actions Shougo/ddu-kind-file -
Matcher
that filters by exact substring match: Shougo/ddu-filter-matcher_substring
Usage Flow
When using it, follow this flow:
# | Purpose | Actual Operation |
---|---|---|
1 | Display the list with ddu.vim | :call ddu#start({options}) |
2 | Show the buffer for Input
|
:call ddu#ui#do_action("openFilterWindow") |
3 | Enter the word to filter Item s |
i , Enter keyword and <ESC>
|
4 | Move to the list buffer | :call ddu#ui#do_action("leaveFilterWindow") |
5 | Select Item
|
Navigate with j or k
|
6 | Call Kind action |
:call ddu#ui#do_action("itemAction", {"name": <action name>}) |
Now, let's explain each process.
ddu#start({options})
This is the starting point for all uses in ddu.vim, such as Source
retrieval and UI
display. Examples of options are given later.
ddu#ui#do_action()
Requests ddu.vim's UI
to call an action. In this example, I'm using ddu-ui-ff as the UI
, so the actions being called are defined in ddu-ui-ff.
:help ddu-ui-ff-action-openFilterWindow
:help ddu-ui-ff-action-leaveFilterWindow
:help ddu-ui-ff-action-itemAction
itemAction
is a bit complex, but it requests ddu.vim to call the action of the Kind
corresponding to the Item
, specified by the name
.
Specifying Options
ddu.vim has four layers of options:
- user: Options passed directly to
ddu#start({dict})
- local: Custom named option sets. Set with
ddu#custom#patch_local({name}, {dict})
- global: Common settings for all. Set by
ddu#custom#patch_global({dict})
- default: Default values
ddu.vim merges these options in the order of user→local→global→default.
Therefore, an option specified globally is overridden by the same local option, which is further overridden by the user option.
The name of the local option set (name
value) also follows the specification in user and global.
For example,
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", " Use the local option named "local-name"
\ option4 = "corge", " !
\ option5 = "grault", " !
\ })
Calling it like this merges the options as follows:
- option1:
"foo"
- option2:
"baz"
- option3:
"qux"
- option4:
"corge"
- option5:
"grault"
These layers allow you to set:
- Settings common to all
ddu#start()
in global - Settings independent of the context in which
ddu#start()
is called in local - Settings dependent on the context in which
ddu#start()
is called in user
Option Structure
Options are divided for each component:
-
UI
settings -
Source
settings -
Filter
settings -
Kind
settings
Each component has Option
and Param
. For example, set Option
for Source
as follows:
\ "sourceOptions": {
\ "_": {
\ ... # Options applied to all Sources
\ },
\ "file_rec" {
\ ... # Options applied only to file_rec Source
\ },
\ }
Details are in each help document:
: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
Note that for ui
and sources
, you can specify:
- Which
UI
/Source
to use - The
Options
,Params
to apply
For instance,
\ "sources": [{
\ "name": "file_rec",
\ "params": {
\ "ignoredDirectories": ["node_modules"]
\ },
\ "options:" {
\ "matchers": ["substring"]
\ }
\ }]
and
\ "sources": ["file_rec"],
\ "sourceParams": {
\ "file_rec": {
\ "ignoredDirectories": ["node_modules"]
\ }
\ },
\ "sourceOptions": {
\ "file_rec": {
\ "matchers": ["substring"]
\ }
\ }
are equivalent. Choose the easier option depending on the situation, such as when dividing layers of options or setting common Options
across multiple Sources
.
Also, which Kind
to use is generally determined by the Source
. Each Source
help document clearly states the required Kind
.
Example: :help ddu-source-file_rec-install
A Configuration Example
Here's a configuration example:
- Display files under the current directory (
getcwd()
) with a Fuzzy Finder UI - Use ddu.vim with two types of settings:
- Command
:DduNodeFiles
: Ignore files under.git/
,node_modules/
directories - Command
:DduWholeFiles
: Don't ignore files, limit to 50,000 items
- Command
- Allow filtering by exact substring match
- Open selected
Item
with thee
key
" Install the following plugins first
" 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
" Set common settings for all
call ddu#custom#patch_global({
\ "ui": "ff",
\ "sourceOptions": {
\ "_": {
\ "matchers": ["matcher_substring"]
\ },
\ },
\ })
" Prepare settings for use with DduNodeFiles
call ddu#custom#patch_local("node-files", {
\ "sources": ["file_rec"],
\ "sourceParams": {
\ "file_rec": {
\ "ignoredDirectories": [".git", "node_modules"],
\ }
\ }
\ })
" Prepare settings for use with DduWholeFiles
call ddu#custom#patch_local("whole-files", {
\ "sources": ["file_rec"],
\ "sourceParams": {
\ "file_rec": {
\ "ignoredDirectories": [],
\ }
\ },
\ "sourceOptions": {
\ "file_rec": {
\ "maxItems": 50000
\ }
\ }
\ })
" Set a Keymap (`e`) effective only in ddu-ui-ff
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
" Prepare commands to call ddu#start with each option set name
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()}}})
Conclusion
This part includes practical tips and thoughts that deviate from the main theme (basic overview) of this article.
Practical Tips
ddu.vim is highly flexible and can accommodate a wide range of use cases. Many issues can be resolved within the "configuration" range. Here are some tips for when issues arise:
- Don't try to absorb various use cases in
Source
- If you don't like that appearance → Use
Filter
(Converter
) for transformation - If you're unhappy that XX isn't included in the list → Mix multiple
Sources
- If you don't like the actions → Use Custom Action or Action Overwriting (
:help ddu-source-option-actions
)
- If you don't like that appearance → Use
- Don't demand completeness in
Kind
- Use Custom Action
- Use
push
(:help ddu-option-push
) in Custom Action to connect to anotherSource
- Don't map everything to key
- Utilize chooseAction (
:help ddu-ui-ff-action-chooseAction
or:help ddu-ui-filer-action-chooseAction
)
- Utilize chooseAction (
- Don't try to do various operations in insert mode
- Separate the mode for entering queries (insert mode) and the mode for selecting Items (normal mode)
- Vim-like, mode-separated behavior makes it less likely to encounter difficulties
These are just listed here, and details may be covered in a separate article later.
Loves ddu.vim
The settings in ddu.vim are quite flexible, and each setting provides a low degree of integrated information for its realization, making it difficult to obtain overarching, integrated knowledge.
As a challenge, I tried to write down my understanding in this article.
I'm greatly helped by the flexibility of ddu.vim, and I believe it's a delightful plugin, especially for those who have struggled to customize existing Fuzzy Finders.
If others are struggling similarly, I hope this article helps them get started.
-
ddu.vim focuses on customizability in its setup, barely suggests "how to use it," and using it as a Fuzzy Finder is just one example. So, it's not just "Fuzzy Finder". ↩︎
-
Not introduced in this article. I hope to cover them in an advanced post, but for now, just think of them as "something like that exists." ↩︎ ↩︎
Discussion