Skip to content

Instantly share code, notes, and snippets.

@dlants
Last active March 5, 2021 06:13
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save dlants/8d7fadfb691b511f1376ba437a9aaea9 to your computer and use it in GitHub Desktop.
Save dlants/8d7fadfb691b511f1376ba437a9aaea9 to your computer and use it in GitHub Desktop.
denite setup with interactive ag pattern-search of project contents

Files

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', ''])

File Contents

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 the grep source 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 denite and binds the grep source to use ag
  • I overwrite the matcher to be matcher_regexp because 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 ]q and [q from 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
  • Enter to invoke the default action, which moves all matches into the quickfix window
  • ]q and [q to move around quickfix results using unimpaired
@seanparsons
Copy link

The ASCIICinema recording was archived BTW.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment