I am trying to delete items from the quickfix list, using the same delete interface I am used to, visual delete and dd. The .vimrc code I am trying to use to accomplish this is below. It does not work. It skips every other line and moves the cursor several lines down probably related to how many lines were visually selected. dd works but visual selected is where it breaks down.

function! Delete()
    if &buftype == 'quickfix'
        call setqflist(filter(getqflist(), {idx -> idx != line('.') - 1}), 'r')
nnoremap <silent> dd :call Delete()<cr>
vnoremap <silent> d :call Delete()<cr>
  • see vi.stackexchange.com/a/16890/1292
    – Hotschke
    Commented Sep 22, 2019 at 16:01
  • @Hotschke while useful(added to my vimrc), not exactly what I'm after. Commented Sep 22, 2019 at 17:36
  • I am not sure whether you also noticed the two plugins I mentioned in this answer. I repeat them here: vim-qfedit and quickfix-reflector.vim.
    – Hotschke
    Commented Sep 22, 2019 at 18:02
  • @Hotschke I did not, the description in the answer made it sound like they only supported manual commands. I'll try them out, thanks! Commented Sep 22, 2019 at 18:09

1 Answer 1


1) Use a function with range keyword (:h func-range) for processing your visual selection. Moreover, that also allows for [count] in Normal mode.

2) Prefer buffer-local mappings whenever it makes sense.

" using range-aware function
function! QFdelete(bufnr) range
    " get current qflist
    let l:qfl = getqflist()
    " no need for filter() and such; just drop the items in range
    call remove(l:qfl, a:firstline - 1, a:lastline - 1)
    " replace items in the current list, do not make a new copy of it;
    " this also preserves the list title
    call setqflist([], 'r', {'items': l:qfl})
    " restore current line
    call setpos('.', [a:bufnr, a:firstline, 1, 0])

" using buffer-local mappings
" note: still have to check &bt value to filter out `:e quickfix` and such
augroup QFList | au!
    autocmd BufWinEnter quickfix if &bt ==# 'quickfix'
    autocmd BufWinEnter quickfix    nnoremap <silent><buffer>dd :call QFdelete(bufnr())<CR>
    autocmd BufWinEnter quickfix    vnoremap <silent><buffer>d  :call QFdelete(bufnr())<CR>
    autocmd BufWinEnter quickfix endif
augroup end
  • is there a way to preserve the cursor position after the delete has been executed so that it behaves fully like normal delete operations? Otherwise this is great! Commented Sep 22, 2019 at 18:00
  • @JoshLawrence Add call cursor(a:firstline, 1), for example.
    – Matt
    Commented Sep 22, 2019 at 18:18
  • call cursor(a:firstline, 1) worked while call setpos('.', [a:bufnr, a:firstline, 1, 0]) did not Commented Sep 22, 2019 at 19:13
  • @JoshLawrence It should work; make sure you pass bufnr as argument to a function. cursor() would fail if the function would be called when quickfix is not an active buffer; that's not possible in this case, but in general that could be an issue.
    – Matt
    Commented Sep 22, 2019 at 19:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.