Eric's Blog 时光荏苒,岁月如梭

自定义 quickfix 窗口格式

2025-01-10
Eric Wong

在 Neovim 或者 Vim 中,QuickFix 窗口内的内容默认的格式是:

<filename>|<lnum> col <col>|<text>

最近有需求修改 QuickFix 窗口内容的格式,使其更加美观一些,修改前,QuickFix 窗口打开后内容如下:

quickfix before

而修改后最终展示的效果如下:

quickfix before

下面展示了两种修改方法,一个是在老旧的 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 选项。


版权声明:本文为原创文章,遵循 署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)版权协议,转载请附上原文出处链接和本声明。


延生阅读

分享到:

评论

目前只支持使用邮件参与评论。