Subject: Re: bug#20489: 25.0.50; next-error-find-buffer chooses non-current buffer without good reason

From: Dmitry Gutov <[email-masked]>
Date: Wed, 27 Jan 2016 05:43:26 +0300

On 01/27/2016 03:57 AM, Juri Linkov wrote:

> I suppose that navigation from every navigational window displays its targets
> in own dedicated window that will be associated with its “parent” window.

That's a considerable change. Associated how? The window itself won't 
have any indication with which navigation buffer it's associated with, 
will it?

And what if you do have the same buffer references in different 
navigation windows? Will they have to show it in both associated 
windows? That seems wasteful.

> So e.g. after navigating from *grep* to window A, and from *compilation*
> to window B, next-error invoked from windows A or B will continue
> the right navigation.

Suppose you've did that, then turned left to look out of the window for 
half a minute, then looked back at Emacs. How are you going to predict 
what M-x next-error will do?

Now, in addition to remembering which navigational command you ran last, 
you have to remember the window associations.

>> We can fix xref, but not every next-error-function uses the same window,
>> and that's not codified in this variable's docstring. change-log-next-error
>> doesn't.
>
> If some next-error-function doesn't use the same window, still there is
> no problem because its displayed window will continue the last navigation
> visited in that window.

And soon, all windows in the frame will refer to the ChangeLog buffer as 
its next-error-last-buffer, right?

`next-error' always continuing the last navigation does not require 
window-local values. We can just have next-error-last-buffer to be global.

And if you're still thinking of the two-frame scenario, here's a little 
modification:

- Run M-x grep in one frame, with several windows, jump to an error 
there, in window A.
- Switch to another frame, run M-x compile there.
- Switch back to the first frame. But select some other window than A. 
Call M-x next-error, and see it use the location from the *compilation* 
buffer, even though *grep* is visible right there.

That scenario looks just as counter-intuitive to me as the original one. 
Your proposal would only fix the original one.

> This adds another problematic case to consider, but we could avoid it
> by always requiring creation of a navigation buffer, possibly hidden
> when necessary.  (As for your point about a hole, I already addressed it
> below - that requires unburing a navigation buffer that you want switch to).

One navigational buffer per file buffer? That's too much.

>> I mean to ask compilation-mode (as well as other similar modes) to
>> (setq-local next-error-function-nonlocal t), in addition to setting
>> next-error-function and next-error-last-buffer.
>
> How this could help to point to other buffer?

It will only tag it to be available for completion in the new 
pick-next-error-last-buffer command.

Or we can put those buffers in a ring, which was also suggested here 
previously. That would also tag them, and allow switching between them 
in a historical fashion.

>> Why complicated? It would just be a way to choose the source of errors to
>> follow. You'd also be able to do that by clicking on an error, or pressing
>> RET, in the "nonlocal" navigation buffers.
>
> I think it would be more WYSIWYG first to switch to the navigation buffer,
> and then to click on an error, or press RET.

That can also be a way to change the global next-error-last-buffer 
value. And whether it's window-local or not, neither scenario solves the 
Flycheck problem.

>> The main point, however, which you might not agree with, is to make
>> next-error-last-buffer global.
>
> I prefer this precedence:
> 1. window-local next-error-last-buffer
> 2. buffer-local next-error-last-buffer
> 3. global next-error-last-buffer

My preference is: 3, 2. Except we never set next-error-last-buffer 
locally, so we should interpret the global nil value to mean "the 
current buffer".

>> Making next-error-last-buffer window-local feels clunkier to me: there
>> would be no indication that a given window is following *Compilation*, for
>> example. And up until now, next-error worked more or less in
>> a global fashion.
>
> Are you hinting that currently there is such indication in the form of
> navigation buffer's window displayed in the same frame (rule#1 in
> next-error-find-buffer)?

That an one option - we can indeed keep some logic reliant on whether 
next-error-last-buffer is visible in the current frame (but drop the 
"not more than one" limitation, because it leads to non-intuitive behavior).

Then the change to the API could be smaller, but the use case of using 
next-error with non-visible navigational buffers will be more broken 
than currently.

But my first choice is to not rely on buffer visibility at all, and 
simply follow the current global next-error-last-buffer value, as well 
as provide an easy way to switch to a different one.

> I proposed window-local next-error-last-buffer only because you had
> some problems with this rule using in xref.

Yes, I did. But IIUC, Eli had more of a problem with the

(if (eq (length window-buffers) 1)

part of that rule. The commit that disabled next-error integration in 
xref has a link to that discussion in its message.

>> How will you "switch" to the next-error-function set locally by Flycheck in
>> the current file-visiting buffer?
>
> By restarting Flycheck?

Restarting how? It's a minor mode that triggers linting checks when the 
buffer is saved, or you've typed something and wait a bit, or the file 
buffer has just been opened. The exact set of conditions is customizable.

And it doesn't set next-error-last-buffer at all.

But suppose it did. Imagine: you M-x compile, jump to an error, that 
opens the file in a new buffer, Flycheck kicks in, runs its linting 
check, and sets next-error-function and next-error-last-buffer in that 
buffer. If you call next-error now, you'll be jumping to the next 
linting error, not *compilation* error.

>> How will you switch between Grep and Compilation if they display a location
>> in the same buffer (and window)? Won't the desired navigation buffer have
>> to be visible? So you'd have to select some window, switch to that buffer
>> in it, and then click or press RET on some error?
>
> Yes.

Lots of clicking.

>> Using a command to switch between next-error-last-buffer candidates seems
>> much quicker.
>
> In case of Flycheck, there will be no next-error-last-buffer, no?

We should interpret nil as "use the current buffer".