bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#19576: write-file writes the wrong buffer


From: Anders Lindgren
Subject: bug#19576: write-file writes the wrong buffer
Date: Wed, 18 Nov 2015 20:23:42 +0100

Hi!

I don't understand why

    (set-window-start WINDOW POS t)

is not sufficient.  It does force the display engine to honor the
window-start position requested by the call; no recentering will take
place.  You say you "would prefer if it was possible to tell the
display engine to leave some windows alone", but that's exactly what
the above call does, wrt the starting position of the window.  So why
isn't it sufficient?

If "pos" is point-max, the window will be recentered after a while. You can try by entering the following in the *scratch* buffer:

 (set-window-start (selected-window) (point-max) t)

Place the cursor at the end of the buffer and evaluate the _expression_ using M-C-x.

If you work with Emacs for a while, you will notice that the content of the *scratch* buffer will be visible after a while. This is what `follow-avoid-tail-recenter' is designed to avoid. (For follow-mode, this mean that the illusion of one tall window is broken, when the visible text doesn't reach the rightmost window.)

As I have mentioned before, I would like to have a hook variable that the display engine can call when doing this. Packaged like follow-mode can use this to override the default behaviour.


 
> * Make it easier for other packages to use it. By this I mean packages that
> display information, like "grep", should be able to use follow mode to
> display a buffer using side by side windows.

But Follow is a minor-mode, right?  So why cannot Grep etc. just turn
it on?

A package should never turn follow-mode on, but it should respect it when it is activated in buffer!

Effectively, if a package wants to display a line in a buffer, and that line is visible in any of the windows in a follow-mode window group, that window should be used regardless if it was the window that was selected before.

"Grep" does in fact do the right thing, the grep hit arrow move across the visible windows nicely.

A package like "ispell" behaves behaves worse since it, somehow, prevent follow-mode from doing it's job. The effect is that the windows are no longer aligned (i.e. some lines are visible in more than one window, or some lines between two windows are no longer shown.)

Another thing that makes things difficult is that the *selected* window group is aligned by follow-mode. If a package wants to show (but not select) another buffer, the windows of the other buffer will not be aligned automatically, and there is no good interface for this. (In my package `font-lock-studio', a control buffer is shown in the selected window, but I wanted the source buffer to be displayed aligned (if follow-mode was active). I ended up calling follow-post-command-hook directly, which really isn't a good practice.)


> * When follow-mode is enabled, there is a noticeable lag when updating the
> region. You can see this by pressing C-c SPACE and holding the up or down
> key. When follow-mode is disabled, the region is updated as fast as the
> cursor moves, when enabled, it is updated in chunks.

I guess follow-mode's post-command-hook interferes with
pre-redisplay-functions used to display the region nowadays.  Please
look into this, it would be good to fix this before Emacs 25.1 is out.

Unfortunately, I won't be able to work on this. We are expecting a baby any day now and when it comes to Emacs-related activitied I have picked up where Jan Djärv left of regarding the NextStep port.

Besides, this is more of a minor irritation point rather than showstopper, so it might just as well wait.


> * Process output: In early versions of follow-mode, it could be used with
> any process. This was accomplished using `defadvice' on a handful of
> process-related functions. At some point in time, this system was replaced
> with a system specific to comint and compilation buffers -- as part of the
> great defadvice sweep. Personally, I would like to Emacs to provide
> `pre-process-output-functions' and `post-process-output-functions',
> allowing packages like follow-mode to perform whatever action they would
> like to the output of any process.

Such hooks will be almost trivial to provide, I think.  But I don't
think I understand what problems would such hooks solve.  Could you
elaborate?

Follow mode can be used both in plain source buffers and in process buffers. Concretely, you can have a *shell* buffer displayed in a number of side by side windows, where the prompt is at the bottom of the rightmost one, and the rest shows your recent activity.

Normally, follow-mode use the post-command-hook to ensure that the windows are aligned. However, when you type something like "ls -lR" in your shell, output will be coming in through the process system, which is not seen by the post-command-hook.

In my original follow-mode implementation, the process filter functions were advices so that all process output were passed through follow-modes own filter functions that aligned the windows and passed the output the real filter functions. The effect was that all process buffer, regardless of which system they used, worked with follow mode. At some point in time it was decided that `defavice' should not be used and this system was replaced with a simpler system only working with compilation and comint buffers.

If generic process output hooks follow-mode could once again work for all processes, and in a much cleaner way. I can see other packages taking advantage of this, like packages that would color output or strip away parts of the output etc.


> * If a user have columns with different widths, follow-mode can't correctly
> display long lines stretching from one window to the next. The reason for
> this is that the start position can't be placed at an arbitrary location on
> a long line, only on positions that are a multiple of the column width. I
> don't see any way to solve this without modifying the display engine.

This is a tough nut, and the real problem is not necessarily obvious.
The real problem is that the display engine _assumes_ the lines above
and below the window edge are of the same pixel width.  It uses this
assumption in its layout code and decisions.  But when follow-mode us
used in windows of unequal width, that assumption breaks.  This is a
very serious problem, because the basic design of the Emacs display
engine is that it does its job one window at a time, i.e. it assumes
that displaying a window is possible by examining only the data of
that single window, and its associated buffer.

In most cases this is the sane thing to do, I guess.

However, one way to handle this is to respect an explicit `set-window-start' position even if the column isn't a multiple of the screen width.


> Thanks for working on this, Martin.  However, I don't think we should
> install this change.  We call Lisp hooks from many places, including
> maybe a dozen in the display engine.  It makes little sense to make
> only one of them resistant to this kind of problems.  OTOH, if we do
> this everywhere, I feel that we will unduly punish 99.999% percent of
> legitimate users of these hooks just because one of them had a bug.
>
> I think this is a clear bug in follow.el, and should be fixed there,
> and nowhere else.  Perhaps we should also have some prominent warnings
> in the documentation about this gotcha, so that the probability this
> will happen again becomes lower.

I don't agree with you on this but I respect your opinion.

This is one of the most obscure bugs I have seen when working with Emacs -- trying to figure out why on earth `write-file' would save the wrong buffer was no easy task, even with many years of Emacs experience under my belt.

There is a risk that other package writers will stumble upon similar problems and give up, or write it of as "unexplainable". Ensuring that the caller saves and restores the state is a very cheap life saver.

    -- Anders


reply via email to

[Prev in Thread] Current Thread [Next in Thread]