Skip to content

Instantly share code, notes, and snippets.

@markwu
Forked from PeterRincker/cfilter.vim
Created February 2, 2019 03:52
Show Gist options
  • Save markwu/bb9d6148990e4acd3eb2f4634586583d to your computer and use it in GitHub Desktop.
Save markwu/bb9d6148990e4acd3eb2f4634586583d to your computer and use it in GitHub Desktop.
Filter the quickfix list
" :Cfilter[!] /{pat}/
" :Cfilter[!] {pat}
" Filter the quickfix looking for pattern, `{pat}`. The pattern can match the filename or text.
" Providing `!` will invert the match (just like `grep -v`).
" Note: :cfilter command abbreviation is provided for convenience
"
" :Lfilter[!] /{pat}/
" :Lfilter[!] {pat}
" Same as :Cfilter but use the location list.
" Note: :lfilter command abbreviation is provided for convenience
" :Cfilter
function! s:cfilter(prefix, list, bang, pat)
let pat = a:pat =~ '^/.*/$' ? a:pat[1:-2] : a:pat
let pat = pat == '' ? @/ : pat
let keys = {'filename':1, 'module':1, 'text':1}
let args = a:list =~ 'loc' ? ['.'] : []
let Cmp = {k,v -> get(keys, k) && v =~ pat}
let Fn = a:bang == '!' ? {cnt -> cnt == 0} : {cnt -> cnt > 0}
try
let title = get(call('get'.a:list.'list', extend(copy(args), [{'title':1}])), 'title', '')
let title = title . '|'.a:prefix.'filter'.a:bang.' '.a:pat
catch
let title = ''
endtry
let entries = call('get'.a:list.'list', args)
let entries = filter(entries, {_,dict-> call(Fn, [len(filter(copy(dict), Cmp))])})
try
call call('set'.a:list.'list', extend(copy(args), [entries]))
call call('set'.a:list.'list', extend(copy(args), [[], 'a', {'title': title}]))
catch
call call('set'.a:list.'list', extend(copy(args), [entries]))
endtry
echo 'Filtered list: '.(a:bang ? 'not ' : '').'matching '.a:pat.' ('.len(call('get'.a:list.'list', copy(args))).' items)'
endfunction
command! -nargs=1 -bang Cfilter call <SID>cfilter('C', 'qf', '<bang>', <q-args>)
command! -nargs=1 -bang Lfilter call <SID>cfilter('L', 'loc', '<bang>', <q-args>)
function! s:exabbrev(lhs, ...)
let rhs = substitute(join(a:000, ' '), "'", "''", 'g')
execute 'cnoreabbrev <expr> ' . a:lhs . ' getcmdtype() == ":" && getcmdline() ==# "' . a:lhs . '" ? expand(''' . rhs . ''') : "' . a:lhs . '"'
endfunction
if !exists(':cfilter')
call s:exabbrev('cfilter', 'Cfilter')
endif
if !exists(':lfilter')
call s:exabbrev('lfilter', 'Lfilter')
endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment