How do I programmatically populate the quickfix list from Vimscript?
Answer
setqflist()
Explanation
setqflist() lets you build the quickfix list from a Vimscript list of dictionaries rather than relying on compiler output or :vimgrep. This is the foundation for writing custom linters, test runners, or any tool that feeds results into Vim's quickfix workflow.
How it works
Each entry in the list passed to setqflist() is a dictionary with any combination of these keys:
bufnrorfilename— the file the entry points tolnum— line numbercol— column numbertext— the message shown in the quickfix windowtype—'E'for error,'W'for warning,'I'for infovalid—1if the entry is a valid jump target
The second argument controls the action: ' ' to create a new list, 'a' to append, 'r' to replace the current list.
Example
Create a quickfix list of every TODO comment in the current buffer:
function! CollectTodos()
let l:items = []
for l:lnum in range(1, line('$'))
let l:line = getline(l:lnum)
if l:line =~# 'TODO'
call add(l:items, {
\ 'bufnr': bufnr('%'),
\ 'lnum': l:lnum,
\ 'text': trim(l:line),
\ 'type': 'W'
\ })
endif
endfor
call setqflist(l:items, ' ')
copen
endfunction
nnoremap <leader>T :call CollectTodos()<CR>
Tips
- Use
getqflist()to read the current quickfix list back into a variable for further processing - Pass
{'title': 'My Tool'}as the third argument to label the quickfix window:setqflist(items, ' ', {'title': 'TODOs'}) - Combine with
:cdoor:cfdoto act on all generated entries setloclist(winnr(), items)works identically but targets the window-local location list instead