Skip to content

Instantly share code, notes, and snippets.

@romainl
Last active November 7, 2021 20:57
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save romainl/3c7ee68125f822ec550c to your computer and use it in GitHub Desktop.
Save romainl/3c7ee68125f822ec550c to your computer and use it in GitHub Desktop.
Show ]I, [I, ]D, [D, :ilist and :dlist results — even spanning multiple files — in the quickfix window.
" This is an updated, more powerful, version of the function discussed here:
" http://www.reddit.com/r/vim/comments/1rzvsm/do_any_of_you_redirect_results_of_i_to_the/
" The purpose of this function is to make the results of ']I', '[I', ']D', '[D', ':ilist' and ':dlist'
" easier to navigate and more persistant by using the quickfix window instead of the default list-like interface.
function! List(command, selection, start_at_cursor, ...)
" Derive the commands used below from the first argument.
let excmd = a:command . "list"
let normcmd = toupper(a:command)
" If we are operating on a visual selection, redirect the output of '[I', ']I', '[D' or ']D'.
" If we don't, redirect the output of ':ilist argument' or ':dlist argument'.
let output = ""
if a:selection
if a:0 > 0 && len(a:1) > 0
let search_pattern = a:1
else
let old_reg = @v
normal! gv"vy
let search_pattern = substitute(escape(@v, '\/.*$^~[]'), '\\n', '\\n', 'g')
let @v = old_reg
endif
redir => output
silent! execute (a:start_at_cursor ? '+,$' : '') . excmd . ' /' . search_pattern
redir END
else
redir => output
silent! execute 'normal! ' . (a:start_at_cursor ? ']' : '[') . normcmd
redir END
endif
" Clean up the output.
let lines = split(output, '\n')
" Bail out on errors.
if lines[0] =~ '^Error detected'
echomsg 'Could not find "' . (a:selection ? search_pattern : expand("<cword>")) . '".'
return
endif
" Our results may span multiple files so we need to build a relatively complex list based on filenames.
let filename = ""
let qf_entries = []
for line in lines
if line !~ '^\s*\d\+:'
let filename = split(line, '\.\./')[-1]
else
let lnum = split(line)[1]
let text = substitute(line, '^\s*.\{-}:\s*\S\{-}\s\s', "", "")
let col = match(text, a:selection ? search_pattern : expand("<cword>")) + 2
call add(qf_entries, {"filename" : filename, "lnum" : lnum, "col" : col, "text" : text})
endif
endfor
" Build the quickfix list from our results.
call setqflist(qf_entries)
" Open the quickfix window if there is something to show.
cwindow
endfunction
" Override the built-in [I and ]I.
nnoremap <silent> [I :call List("i", 0, 0)<CR>
nnoremap <silent> ]I :call List("i", 0, 1)<CR>
" Add [I and ]I for visual mode.
xnoremap <silent> [I :<C-u>call List("i", 1, 0)<CR>
xnoremap <silent> ]I :<C-u>call List("i", 1, 1)<CR>
" Add the :Ilist command.
command! -nargs=1 Ilist call List("i", 1, 0, <f-args>)
" Override the built-in [D and ]D.
nnoremap <silent> [D :call List("d", 0, 0)<CR>
nnoremap <silent> ]D :call List("d", 0, 1)<CR>
" Add [D and ]D for visual mode.
xnoremap <silent> [D :<C-u>call List("d", 1, 0)<CR>
xnoremap <silent> ]D :<C-u>call List("d", 1, 1)<CR>
" Add the :Dlist command.
command! -nargs=1 Dlist call List("d", 1, 0, <f-args>)
@romainl
Copy link
Author

romainl commented Apr 11, 2015

Fixed the column jumping.

@romainl
Copy link
Author

romainl commented Apr 11, 2015

Modified line 47 as per c0ffeeartc's comment. Didn't notice any undesirable side effect.

@romainl
Copy link
Author

romainl commented Apr 11, 2015

I'm wondering if I should turn this thing into an actual plugin. On one hand it would help tracking issues, on the other hand this function may be too small for that.

@romainl
Copy link
Author

romainl commented Apr 11, 2015

This gist is no longer maintained. See romainl/vim-qlist.

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