How would I go about setting up a hotkey (eg: CTRL+g) to perform a VIMGREP
operation on the current visual selection in the current buffer? My intent is to show a line-numbered list in the "quickfix" window of all matching search results.
Right now, if I want to get a list of results for a regex search, I could do a command-mode query like so:
:vimgrep /foo/ %
However, there are two problems with this:
Thank you.
Try [I
and the :ilist
command:
[I " lists every occurrence of the word under the cursor
" in the current buffer (and includes)
:ilist /foo<CR> " lists every occurrence of foo in the current buffer
" (and includes)
Press :
followed by a line number and <CR>
to jump to that line.
You can use them on the visual selection with a simple mapping:
xnoremap <key> "vy:<C-u>ilist /<C-r>v<CR>:
You'll probably need to sanitize the register upon insertion, though.
See :help :ilist
.
Since we are at it, let's dig even deeper and find the amazingly simple and elegant:
:g/foo/#
that you could use in the same way as :ilist
above:
xnoremap <key> "vy:<C-u>g/<C-r>v/#<CR>:
The solutions above don't use the quickfix window, obviously, but they allow you to:
They have limitations, though:
:cnext
or :clast
to move around the result.If those limitations are a showstopper, the function below, adapted from justinmk's answer in this /r/vim thread, gives you an almost complete solution:
[I
in normal mode to search for the word under the cursor in the whole buffer,]I
in normal mode to search for the word under the cursor after the current line,[I
in visual mode to search for the selected text in the whole buffer,]I
in visual mode to search for the selected text after the current line.The function below uses the quickfix list/window when the buffer is associated to a file and falls back to the regular behavior of [I
and ]I
otherwise. It could probably be modified to be used as part of an :Ilist
command.
" Show ]I and [I results in the quickfix window.
" See :help include-search.
function! Ilist_qf(selection, start_at_cursor)
" there's a file associated with this buffer
if len(expand('%')) > 0
" we are working with visually selected text
if a:selection
" we build a clean search pattern from the visual selection
let old_reg = @v
normal! gv"vy
let search_pattern = substitute(escape(@v, '\/.*$^~[]'), '\\n', '\\n', 'g')
let @v = old_reg
" and we redirect the output of our command for later use
redir => output
silent! execute (a:start_at_cursor ? '+,$' : '') . 'ilist /' . search_pattern
redir END
" we are working with the word under the cursor
else
" we redirect the output of our command for later use
redir => output
silent! execute 'normal! ' . (a:start_at_cursor ? ']' : '[') . "I"
redir END
endif
let lines = split(output, '\n')
" better safe than sorry
if lines[0] =~ '^Error detected'
echomsg 'Could not find "' . (a:selection ? search_pattern : expand("<cword>")) . '".'
return
endif
" we retrieve the filename
let [filename, line_info] = [lines[0], lines[1:-1]]
" we turn the :ilist output into a quickfix dictionary
let qf_entries = map(line_info, "{
\ 'filename': filename,
\ 'lnum': split(v:val)[1],
\ 'text': getline(split(v:val)[1])
\ }")
call setqflist(qf_entries)
" and we finally open the quickfix window if there's something to show
cwindow
" there's no file associated with this buffer
else
" we are working with visually selected text
if a:selection
" we build a clean search pattern from the visual selection
let old_reg = @v
normal! gv"vy
let search_pattern = substitute(escape(@v, '\/.*$^~[]'), '\\n', '\\n', 'g')
let @v = old_reg
" and we try to perform the search
try
execute (a:start_at_cursor ? '+,$' : '') . 'ilist /' . search_pattern . '<CR>:'
catch
echomsg 'Could not find "' . search_pattern . '".'
return
endtry
" we are working with the word under the cursor
else
" we try to perform the search
try
execute 'normal! ' . (a:start_at_cursor ? ']' : '[') . "I"
catch
echomsg 'Could not find "' . expand("<cword>") . '".'
return
endtry
endif
endif
endfunction
nnoremap <silent> [I :call Ilist_qf(0, 0)<CR>
nnoremap <silent> ]I :call Ilist_qf(0, 1)<CR>
xnoremap <silent> [I :<C-u>call Ilist_qf(1, 0)<CR>
xnoremap <silent> ]I :<C-u>call Ilist_qf(1, 1)<CR>
NB: <C-r><C-w>
inserts the word under the cursor, not the visual selection for which there's unfortunately no such shortcut. We have no choice but to yank.