在 Neovim 或者 Vim 中,QuickFix 窗口内的内容默认的格式是:
<filename>|<lnum> col <col>|<text>
最近有需求修改 QuickFix 窗口内容的格式,使其更加美观一些,修改前,QuickFix 窗口打开后内容如下:
而修改后最终展示的效果如下:
下面展示了两种修改方法,一个是在老旧的 Vim 内实现的方法,另外一个是借助 Vim 8.2 的 qftf
选项实现的方式。
老旧方法
早在 Vim 7.4 之前,可以使用 autocmd 来手动修改,其实现的逻辑是监控 BufReadPost
事件
function! QuickFixFormat()
let qflist = map(getqflist(),
\ 'extend(v:val, {"filename" : bufname(v:val.bufnr)})')
let prefix_len = 2 + max(map(copy(qflist),
\ 'strchars(v:val.filename . v:val.lnum)'))
let fmt = '%-' . prefix_len . 's' . '%s'
setlocal modifiable
call setline('1', map(qflist,
\ 'printf(fmt, v:val.filename . ":" . v:val.lnum, "| " . v:val.text)'))
setlocal nomodifiable nomodified
endfunction
augroup QuickFixFormat
autocmd!
autocmd BufReadPost quickfix call QuickFixFormat()
augroup END
上述代码中,还可以把分隔符 |
修改成占据整行的竖线 │
,以实现完整分割线效果。
完成窗口内容修改后,还存在一个问题,QuickFix 窗口里内容的高亮是通过 Vim 默认的 syntax/qf.vim
文件实现的,在这里需要覆盖默认的 qf
FileType 的语法高亮:
Vim 可以新建 ~/.vim/syntax/qf.vim
文件,Neovim 是 ~/.config/nvim/syntax/qf.vim
。
if exists('b:current_syntax')
finish
endif
syn match qfFileName "^[^│]*" contains=qfLineNr
syn match qfSeparator "│"
syn match qfLineNr ":\d*" contained
" The default highlighting.
hi def link qfFileName Directory
hi def link qfLineNr LineNr
hi def link qfSeparator VertSplit
let b:current_syntax = 'qf'
使用 quickfixtextfunc
上面的方法是强制修改 QuickFix Buffer 内容实现的格式化,Vim 8.2 提供了 quickfixtextfunc
选项,
可以通过设定这一选项来实现格式化 QuickFix 窗口,修改第一段代码为:
function! QuickFixFormat(info)
let qflist = getqflist({'id' : a:info.id, 'items' : 1}).items
let qflist = map(qflist,
\ 'extend(v:val, {"filename" : bufname(v:val.bufnr)})')
let prefix_len = 2 + max(map(copy(qflist),
\ 'strchars(v:val.filename . v:val.lnum)'))
let fmt = '%-' . prefix_len . 's' . '%s'
return map(qflist,
\ 'printf(fmt, v:val.filename . ":" . v:val.lnum, "│ " . v:val.text)')
endfunction
set quickfixtextfunc=QuickFixFormat
可以通过 if exists('&quickfixtextfunc')
来检测当前 Vim 或者 Neovim 是否支持 quickfixtextfunc
选项。