First things first, I want to use ag to search through my project files. Coming from fzf, I like to have two bindings for this -- one that respects my projects .gitignore and one that does not. The latter is helpful if I want to examine a built file or look at a node_module dependency while working on my js project.
I use an alias for file_rec source to toggle the -u flag on ag. Now, <C-P> searches in my git files, and <C-O> searches everything.
" denite file search (c-p uses gitignore, c-o looks at everything)
map <C-P> :DeniteProjectDir -buffer-name=git -direction=top file_rec/git<CR>
map <C-O> :DeniteProjectDir -buffer-name=files -direction=top file_rec<CR>
" -u flag to unrestrict (see ag docs)
call denite#custom#var('file_rec', 'command',
\ ['ag', '--follow', '--nocolor', '--nogroup', '-u', '-g', ''])
call denite#custom#alias('source', 'file_rec/git', 'file_rec')
call denite#custom#var('file_rec/git', 'command',
\ ['ag', '--follow', '--nocolor', '--nogroup', '-g', ''])
Next is searching over file contents. Working in js, code analysis tools are pretty weak. So, I often want to find all of the instances where a particular string appears within my project. Denite allows me to do this in a nice and interactive way.
" denite content search
map <leader>a :DeniteProjectDir -buffer-name=grep -default-action=quickfix grep:::!<CR>
call denite#custom#source(
\ 'grep', 'matchers', ['matcher_regexp'])
" use ag for content search
call denite#custom#var('grep', 'command', ['ag'])
call denite#custom#var('grep', 'default_opts',
\ ['-i', '--vimgrep'])
call denite#custom#var('grep', 'recursive_opts', [])
call denite#custom#var('grep', 'pattern_opt', [])
call denite#custom#var('grep', 'separator', ['--'])
call denite#custom#var('grep', 'final_opts', [])
Here's how it works.
- you start by pressing
<leader>a(for ag).grep:::!will invoke thegrepsource in an interactive window. Which means that you will re-query the source as you type. - The bottom half of the config is taken straight from
:help deniteand binds the grep source to use ag - I overwrite the matcher to be
matcher_regexpbecause I find fuzzy matching to be too forgiving for the purpose of finding strings in the source. This also has the benefit of speeding up the update cycle. - I set the default action to
quickfix. This way, when I tag multiple files in the denite buffer and press enter, those locations go into my quickfix list. I can then use]qand[qfrom unimpaired to quickly look through the matches and make corrections where necessary.
Here's a video of it in action! https://asciinema.org/a/93i6c5y2mz60juq8xt2a3svdz
What you see in the video:
- I enter
vi(for me that's an alias for nvim) in the root of my git repo - I press
<leader>a. This brings up an Denite buffer that's piping my commands to ag - I try a few regexes to get the set of results that I want
- I press
<Ctrl-O>to enter normal mode (this is a default denite keybinding for insert mode) - I press
*to select all Enterto invoke the default action, which moves all matches into the quickfix window]qand[qto move around quickfix results using unimpaired
The ASCIICinema recording was archived BTW.