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

From: Dmitry Gutov <[email-masked]>
Date: Tue, 26 Jan 2016 02:36:17 +0300

On 01/26/2016 12:55 AM, Juri Linkov wrote:

> A frame might contain more pairs of navigational/target windows,
> e.g. a window with *grep* output, and a file buffer visited from *grep*;
> a window with *Occur*, and another place in the same file buffer
> but visited from *Occur*, etc.

Yes, but it wasn't your scenario there. In that scenario, you switched 
to a different frame, which had only a *compilation* buffer visible, and 
were surprised to see a next-error-function used from a non-visible 
buffer you last accessed in a different frame.

> So frame-local is not of help here, whereas window-local is,
> provided a navigational window (like *grep*/*compilation*)
> always displays target buffers in another dedicated window.

How does it really help? You've navigated from *grep*, to that buffer A, 
then did that from *compilation*, and then you can't continue jumping to 
next *grep* occurrences from that buffer.

frame-local could be sufficient if we were sure that different 
navigation windows show error locations in distinctly different sets of 
windows, IMHO.

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.

> As I see this is not what xref currently does: navigating in it
> jumps between many different windows that is very inconvenient,
> but this can be easily fixed to work the sane way as *grep*
> or *compilation* already works.

Yes, this can use an improvement.

>> How do linting minor modes (like Flycheck or Flymake) fit into this?
>
> Does Flycheck or Flymake display a navigation window with a list of results?

Flycheck has such a buffer, but it's not displayed by default. And in 
any case, it sets next-error-function locally in file buffers, but not 
in its "list of errors" buffer.

Hmm. Apparently, Flymake doesn't set next-error-function, so we can 
disregard it.

js2-mode is another example: it's a major mode that sets 
next-error-function in its buffers. You can ask it for the "list of 
errors" buffer as well, but it's usually not shown.

> If not, then this is a new case that we need to support as well.

Apparently so.

>> Suppose I called M-x compile (or, better yet, M-x grep), navigated to some
>> file buffer from it and then see that it has some linter errors highlighed
>> by Flycheck. So I want to use the current buffer's next-error-function now,
>> and jump between linter warnings using next/previous-error. How do I do
>> that? IIU your plan correctly, the current window-local
>> next-error-last-buffer value will continue pointing at the Grep buffer,
>> even if I bury it.
>
> What if you have two navigations in the same buffer, and both are
> without a navigation window that you can't bury?

I don't follow. The above was an attempt to point out an hole in your 
plan. I'm not sure you can refute that with a "what if" counter-example.

>> - Some indicator that a given buffer's next-error-function points to other
>> buffer (then, if you're in a different buffer, that other buffer is still
>> relevant). Like a buffer-local variable called, for example,
>> next-error-function-nonlocal.
>
> Do you mean to bind a navigation buffer with navigated target buffers/windows?

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.

>> - A command (or several) to switch between the plausible candidates for
>> next-error-last-buffer. Maybe just have a single command that uses
>> read-buffer with a predicate checking the aforementioned variable and an
>> extra option that means "just use the current buffer".
>
> This would be too complicated to use.

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.

The main point, however, which you might not agree with, is to make 
next-error-last-buffer global.

>> - Ignore next-error-last-buffer's visibility. Or make it frame-local, to
>> account for your scenario as well (but that would bring extra complexity:
>> some people use use frames like almost separate applications, and other can
>> use frames instead of windows, and display them side-by-side).
>
> Buffers are displayed in windows, so better to bind them to windows.

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.

> I remember the original idea was to always continue the same navigation
> that displayed a given target buffer/window, so switching to another
> navigation in the same window could be achieved by explicitly navigating
> to another result from another navigation, e.g. when current navigation
> was from *compilation* then switching to *grep* buffer and typing M-n
> for the next grep hit in the same file buffer.

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

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?

Using a command to switch between next-error-last-buffer candidates 
seems much quicker.