changing pathnames in quickfix list

22 views
Skip to first unread message

duv...@comfychair.org

unread,
May 12, 2020, 12:03:14 PM5/12/20
to vim...@googlegroups.com
I have a Makefile rule that builds some go packages in a directory a few levels
down from the current directory:

cd down/down/down && $(GO) build $(GO_BUILD_FLAGS) -o ../../../../$(@) $*

When I run :make, it builds as expected, but if I have an error, then I get
something like

# dir1/dir2/pkg
dir2/pkg/foo.go:53:16: undefined: "github.com/pkg/errors".Wrrapf

The quickfix list loads "dir2/pkg/foo.go", which doesn't exist: the file is
actually at "down/down/down/dir2/pkg/foo.go".

Is there a way to get the right information into the quickfix list?

I tried adding "%Dcd\ %f\ " to 'errorformat', relying on the "missing leave
directory" heuristics to figure the rest out, but that didn't seem to work.

I could write a function for QuickFixCmdPost that would look at each buffer,
grab its name, and if the name didn't exist, load the real file into a buffer,
change the list, and wipeout the incorrect buffer, but a) it's a lot of work,
and b) we end up loading a lot of buffers for bogus files.

I feel like there's got to be a way to intercept the quickfix list before vim
has parsed it, or at least before it's created buffers for the files with
errors. Is there? Should there be?

Thanks,
Danek

duv...@comfychair.org

unread,
Jun 2, 2020, 1:08:18 PM6/2/20
to vim...@googlegroups.com
After patch 0869 came out, implementing 'quickfixtextfunc', I thought perhaps
that would be the answer I was looking for. Alas, it seems to be useful only to
manipulate the text of the quickfix window, not the list loaded by :make. But
it got me looking at this again, and I decided to give the QuickFixCmdPost
solution a shot. It was easier than I thought, even though it doesn't work
quite right:

function! FixQuickFix()
let qflist = getqflist()
for i in qflist
let fname = buffer_name(i.bufnr)
if fname =~ "\.go$"
let fname = "down/down/down/" . fname
let i.bufnr = bufadd(fname)
" call bufload(i.bufnr)
" call setbufvar(i.bufnr, "&buflisted", 1)
endif
endfor
call setqflist(qflist, 'r')
endfunction

I run :make, and the build runs, and fails as expected, but vim doesn't switch
to the buffer with the file containing the first error. I get a "Press ENTER or
type command to continue" message after the make completes, and then a second
one after showing me the first line of the output (not the first error), but
then it just leaves me in the buffer I was originally in.

:clist is what I expect:

17 down/down/down/pkg/foo.go:503 col 14: undefined: tst
18 Makefile:981: recipe for target 'bin/foo' failed

and :cnext takes me to that first error, but it's not done automatically.

The "too many buffers loaded" problem is definitely here:

:ls!
1 %a "Makefile" line 6
2u "pkg/foo.go" line 0
3u "down/down/down/pkg/foo.go" line 0
4u h- "[Quickfix List]" line 19

Makefile was my original buffer. You can see that two buffers exist for the
file where the problem occurred: one prior to the edit made by FixQuickFix(),
and one after.

If I uncomment the setbufvar() line, it definitely ends up listed, and if I call
bufload(), then the buffer is definitely loaded (complaints about an existing
swapfile, if it's open in another vim), but neither one nor both together give
me the behavior I'm expecting. I can put "cnext" at the end of it (not
requiring either of the bufload() or setbufvar() calls), and that works, but
then I don't know of any way to distinguish between :make and :make!.

Is there anything else I can do without extra support from vim?

Thanks,
Danek
Reply all
Reply to author
Forward
0 new messages