* bug#33532: 26.1; set-window-configuration does not restore display start
@ 2018-11-27 22:11 Markus Triska
2018-11-28 6:41 ` Eli Zaretskii
0 siblings, 1 reply; 26+ messages in thread
From: Markus Triska @ 2018-11-27 22:11 UTC (permalink / raw)
To: 33532
In "emacs -Q", please evaluate the following form:
(let ((buf (get-buffer-create "buf")))
(switch-to-buffer buf)
(erase-buffer)
(dotimes (x 10)
(insert (format "x is %s\n" x)))
(recenter 3)
(sit-for 1)
(let ((conf (current-window-configuration))
(ws (window-start))
(str (with-current-buffer buf (buffer-string))))
(with-current-buffer buf
(erase-buffer)
(insert str))
(set-window-configuration conf)
(sit-for 1)
(message "window-start: %s vs. %s" ws (window-start))))
This shows that after set-window-configuration, even though the buffer
content is the same as at the time the configuration was obtained, the
value of (window-start) differs from before: After the window
configuration is set, (window-start) is 1. I expect it to be 50 (i.e.,
the value at the time the configuration was obtained), because the
documentation of current-window-configuration states:
This describes ... for each ... buffer, where display starts ...
If possible, could you please consider restoring window-start to the
exact same position? Thank you very much!
In GNU Emacs 26.1 (build 1, x86_64-pc-linux-gnu, X toolkit, Xaw scroll bars)
of 2018-11-18 built on debian
Repository revision: 07f8f9bc5a51f5aa94eb099f3e15fbe0c20ea1ea
Windowing system distributor 'The X.Org Foundation', version 11.0.11902000
System Description: Debian GNU/Linux 9.6 (stretch)
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-11-27 22:11 bug#33532: 26.1; set-window-configuration does not restore display start Markus Triska
@ 2018-11-28 6:41 ` Eli Zaretskii
2018-11-28 17:13 ` Markus Triska
0 siblings, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2018-11-28 6:41 UTC (permalink / raw)
To: Markus Triska; +Cc: 33532
> From: Markus Triska <triska@metalevel.at>
> Date: Tue, 27 Nov 2018 23:11:21 +0100
>
> (let ((buf (get-buffer-create "buf")))
> (switch-to-buffer buf)
> (erase-buffer)
> (dotimes (x 10)
> (insert (format "x is %s\n" x)))
> (recenter 3)
> (sit-for 1)
> (let ((conf (current-window-configuration))
> (ws (window-start))
> (str (with-current-buffer buf (buffer-string))))
> (with-current-buffer buf
> (erase-buffer)
> (insert str))
> (set-window-configuration conf)
> (sit-for 1)
> (message "window-start: %s vs. %s" ws (window-start))))
>
> This shows that after set-window-configuration, even though the buffer
> content is the same as at the time the configuration was obtained, the
> value of (window-start) differs from before: After the window
> configuration is set, (window-start) is 1. I expect it to be 50 (i.e.,
> the value at the time the configuration was obtained), because the
> documentation of current-window-configuration states:
The window-start point is a marker, and is saved as such. Your code
replaces the entire text of the buffer with something new, so all the
markers are invalidated.
How important is the use case of replacing buffer text with identical
text? Because replacing with a different text will make preserving
window-start position based on its numerical value not really a
sensible thing, would it? It could even be impossible, e.g. if the
same position happens to be in the middle of a sequence of composed
characters.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-11-28 6:41 ` Eli Zaretskii
@ 2018-11-28 17:13 ` Markus Triska
2018-11-28 17:41 ` Eli Zaretskii
2018-11-29 8:31 ` martin rudalics
0 siblings, 2 replies; 26+ messages in thread
From: Markus Triska @ 2018-11-28 17:13 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 33532
Eli Zaretskii <eliz@gnu.org> writes:
> How important is the use case of replacing buffer text with identical
> text? Because replacing with a different text will make preserving
> window-start position based on its numerical value not really a
> sensible thing, would it? It could even be impossible, e.g. if the
> same position happens to be in the middle of a sequence of composed
> characters.
Please consider a use case that is described in the Emacs manual:
In order to store a window configuration on disk and
read it back in another Emacs session ...
In such use cases, I want to restore the exact same text in all buffers,
and then restore the window configuration, including display starts.
In fact, the snippet illustrates an even simpler situation: It stores
the configuration in a variable, and the session keeps running. I would
like to obtain the configuration, then close all buffers, and later
restore their contents (for example, from files), and then use
set-window-configuration to restore the original window configuration,
including all window-starts.
Could set-window-configuration be generalized to reliably restore the
window-starts also in such cases? If not, please consider adjusting the
documentation to make clear what this actually guarantees. In
particular, when are window-starts reliably restored, and when not?
Thank you and all the best,
Markus
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-11-28 17:13 ` Markus Triska
@ 2018-11-28 17:41 ` Eli Zaretskii
2018-11-28 17:58 ` Markus Triska
2018-11-29 8:31 ` martin rudalics
1 sibling, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2018-11-28 17:41 UTC (permalink / raw)
To: Markus Triska; +Cc: 33532
> From: Markus Triska <triska@metalevel.at>
> Cc: 33532@debbugs.gnu.org
> Date: Wed, 28 Nov 2018 18:13:57 +0100
>
> Eli Zaretskii <eliz@gnu.org> writes:
>
> > How important is the use case of replacing buffer text with identical
> > text? Because replacing with a different text will make preserving
> > window-start position based on its numerical value not really a
> > sensible thing, would it? It could even be impossible, e.g. if the
> > same position happens to be in the middle of a sequence of composed
> > characters.
>
> Please consider a use case that is described in the Emacs manual:
>
> In order to store a window configuration on disk and
> read it back in another Emacs session ...
>
> In such use cases, I want to restore the exact same text in all buffers,
> and then restore the window configuration, including display starts.
Please propose how to do that. If it can be done ion a useful manner,
I don't see why we shouldn't.
> In fact, the snippet illustrates an even simpler situation: It stores
> the configuration in a variable, and the session keeps running. I would
> like to obtain the configuration, then close all buffers, and later
> restore their contents (for example, from files), and then use
> set-window-configuration to restore the original window configuration,
> including all window-starts.
Well, you get everything _excluding_ the window-start. I think it's
still a bargain.
> Could set-window-configuration be generalized to reliably restore the
> window-starts also in such cases? If not, please consider adjusting the
> documentation to make clear what this actually guarantees. In
> particular, when are window-starts reliably restored, and when not?
As long as the buffer text exists, you will get the best approximation
to restoring window-start.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-11-28 17:41 ` Eli Zaretskii
@ 2018-11-28 17:58 ` Markus Triska
2018-11-28 18:29 ` Eli Zaretskii
0 siblings, 1 reply; 26+ messages in thread
From: Markus Triska @ 2018-11-28 17:58 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 33532
Eli Zaretskii <eliz@gnu.org> writes:
>> In such use cases, I want to restore the exact same text in all buffers,
>> and then restore the window configuration, including display starts.
>
> Please propose how to do that. If it can be done ion a useful manner,
> I don't see why we shouldn't.
In my opinion, one way to do it is to have current-window-configuration
store the window-start internally as an integer (instead of a marker),
denoting the position of the display start.
Then, set-window-configuration could set the window-start to that
position.
Would that work? At least that is how I currently work around the issue.
> Well, you get everything _excluding_ the window-start. I think it's
> still a bargain.
It is! However, the documentation suggests that it is even better, when
it's currently not.
All the best,
Markus
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-11-28 17:58 ` Markus Triska
@ 2018-11-28 18:29 ` Eli Zaretskii
0 siblings, 0 replies; 26+ messages in thread
From: Eli Zaretskii @ 2018-11-28 18:29 UTC (permalink / raw)
To: Markus Triska; +Cc: 33532
> From: Markus Triska <triska@metalevel.at>
> Cc: 33532@debbugs.gnu.org
> Date: Wed, 28 Nov 2018 18:58:30 +0100
>
> In my opinion, one way to do it is to have current-window-configuration
> store the window-start internally as an integer (instead of a marker),
> denoting the position of the display start.
>
> Then, set-window-configuration could set the window-start to that
> position.
How is this useful if the text has changed? You are just starting
display from some random position, don't you?
> Would that work?
Not in general, no.
> At least that is how I currently work around the issue.
I don't think this could be a general solution. But I'll let others
chime in and comment on this.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-11-28 17:13 ` Markus Triska
2018-11-28 17:41 ` Eli Zaretskii
@ 2018-11-29 8:31 ` martin rudalics
2018-11-29 18:09 ` Markus Triska
1 sibling, 1 reply; 26+ messages in thread
From: martin rudalics @ 2018-11-29 8:31 UTC (permalink / raw)
To: Markus Triska, Eli Zaretskii; +Cc: 33532
> Please consider a use case that is described in the Emacs manual:
>
> In order to store a window configuration on disk and
> read it back in another Emacs session ...
But the whole text is
In order to store a window configuration on
disk and read it back in another Emacs session, you can use the
functions described next.
and the functions mentioned there are `window-state-get' and
`window-state-put'. So you have to tell us what you want to fix: The
behavior of window configurations throughout one and the same Emacs
session (which uses markers to restore positions) or when restoring a
previous session (which relies on positions only).
> In such use cases, I want to restore the exact same text in all buffers,
What is "to restore the exact same text in all buffers"? The text at
the time the configuration was stored in a register? That one might
not be available any more. Restoring a window configuration (or
state) can only use the buffer text as is and adjust positions
accordingly.
> and then restore the window configuration, including display starts.
>
> In fact, the snippet illustrates an even simpler situation: It stores
> the configuration in a variable, and the session keeps running. I would
> like to obtain the configuration, then close all buffers,
I suppose you mean "kill all buffers" here. This will implicitly make
the window start and point positions of any window that showed the
buffer previously and is stored in a configuration to point nowhere.
Furthermore, there is no guarantee that the same buffer will be shown
in that window when the configuration is restored.
> and later
> restore their contents (for example, from files), and then use
> set-window-configuration to restore the original window configuration,
> including all window-starts.
If you use window states instead of configurations then this should
work. States store positions instead of markers.
> Could set-window-configuration be generalized to reliably restore the
> window-starts also in such cases? If not, please consider adjusting the
> documentation to make clear what this actually guarantees. In
> particular, when are window-starts reliably restored, and when not?
Emacs tries its best to do that. But killing and reverting buffers,
among other operations, can defy such attempts. So you either should
try 'window-state-get' and 'window-state-put' to do what you want or
save any positions separately before killing buffers and restore them
together with their buffers after restoring a configuration.
martin
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-11-29 8:31 ` martin rudalics
@ 2018-11-29 18:09 ` Markus Triska
2018-11-29 19:11 ` martin rudalics
0 siblings, 1 reply; 26+ messages in thread
From: Markus Triska @ 2018-11-29 18:09 UTC (permalink / raw)
To: martin rudalics; +Cc: 33532
martin rudalics <rudalics@gmx.at> writes:
> and the functions mentioned there are `window-state-get' and
> `window-state-put'.
These functions have an analogous issue, which you can see with:
(let ((buf (get-buffer-create "buf")))
(switch-to-buffer buf)
(erase-buffer)
(dotimes (x 10)
(insert (format "x is %s\n" x)))
(recenter 3)
(sit-for 1)
(let ((conf (window-state-get))
(ws (window-start))
(str (with-current-buffer buf (buffer-string))))
(with-current-buffer buf
(erase-buffer)
(insert str))
(window-state-put conf)
(sit-for 1)
(message "window-start: %s vs. %s" ws (window-start))))
> So you have to tell us what you want to fix: The behavior of window
> configurations throughout one and the same Emacs session (which uses
> markers to restore positions) or when restoring a previous session
> (which relies on positions only).
If possible, please fix both. I filed the simpler case first, but both
functions are broken. For now, I would like to concentrate on the case
that only involves variables in the same Emacs session, without saving
files to disk. I can file a separate issue for the other function.
> What is "to restore the exact same text in all buffers"? The text at
> the time the configuration was stored in a register?
It means the buffer text that can be obtained for example with
(buffer-string), and can be restored exactly as it was at any time. The
snippet I posted illustrates this case.
> Restoring a window configuration (or state) can only use the buffer
> text as is and adjust positions accordingly.
This is what I am asking for, and what currently does not work. Please
see the snippet I posted for a reproducible test case: The buffer text
is what it was, but the start position is not restored.
> Furthermore, there is no guarantee that the same buffer will be shown
> in that window when the configuration is restored.
The fact that other guarantees are also broken is definitely
unfortunate. However, improving just the particular aspect I mentioned
would already be extremely helpful for my use case.
> If you use window states instead of configurations then this should
> work. States store positions instead of markers.
Please see above: The snippet shows that it doesn't work. Also, I am
primarily interested in the window configuration, and the documentation
suggests that the window-start is saved (and restored).
If possible, please consider implementing this, or adjusting the
documentation so that it states what is actually guaranteed.
Thank you and all the best,
Markus
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-11-29 18:09 ` Markus Triska
@ 2018-11-29 19:11 ` martin rudalics
2018-11-30 16:58 ` Markus Triska
0 siblings, 1 reply; 26+ messages in thread
From: martin rudalics @ 2018-11-29 19:11 UTC (permalink / raw)
To: Markus Triska; +Cc: 33532
> These functions have an analogous issue, which you can see with:
>
> (let ((buf (get-buffer-create "buf")))
> (switch-to-buffer buf)
> (erase-buffer)
> (dotimes (x 10)
> (insert (format "x is %s\n" x)))
> (recenter 3)
> (sit-for 1)
> (let ((conf (window-state-get))
> (ws (window-start))
> (str (with-current-buffer buf (buffer-string))))
> (with-current-buffer buf
> (erase-buffer)
> (insert str))
> (window-state-put conf)
> (sit-for 1)
> (message "window-start: %s vs. %s" ws (window-start))))
You have to call 'window-state-get' with the WRITABLE argument
non-nil, like (window-state-get nil t). Otherwise, it gets you
markers just like 'current-window-configuration'.
Note that I did not disregard the remainder of your mail but please
let's continue the discussion after you tried my suggestion.
Thanks, martin
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-11-29 19:11 ` martin rudalics
@ 2018-11-30 16:58 ` Markus Triska
2018-11-30 17:47 ` martin rudalics
2018-11-30 19:20 ` Eli Zaretskii
0 siblings, 2 replies; 26+ messages in thread
From: Markus Triska @ 2018-11-30 16:58 UTC (permalink / raw)
To: martin rudalics; +Cc: 33532
martin rudalics <rudalics@gmx.at> writes:
> You have to call 'window-state-get' with the WRITABLE argument
> non-nil, like (window-state-get nil t). Otherwise, it gets you
> markers just like 'current-window-configuration'.
Perfect! This is what I need also for current-window-configuration!
Also, could this be made the default? Or is there some advantage in
using markers instead of the actual positions that can be restored?
All the best,
Markus
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-11-30 16:58 ` Markus Triska
@ 2018-11-30 17:47 ` martin rudalics
2018-12-01 22:52 ` Juri Linkov
2018-11-30 19:20 ` Eli Zaretskii
1 sibling, 1 reply; 26+ messages in thread
From: martin rudalics @ 2018-11-30 17:47 UTC (permalink / raw)
To: Markus Triska; +Cc: 33532
> Perfect! This is what I need also for current-window-configuration!
> Also, could this be made the default? Or is there some advantage in
> using markers instead of the actual positions that can be restored?
First of all we need a "reasonable" use case. The only purpose of a
form like
(let ((str (with-current-buffer buf (buffer-string))))
(with-current-buffer buf
(erase-buffer)
(insert str)))
is to annihilate all marker positions in buf and I have yet to
understand why that could be useful. I'm sure you have something more
reasonable in mind. Once we have such a use case we can decide how to
best support it.
AFAICT Emacs' window configurations use window start and point markers
ever since. And while they interfere with reverting buffers (see
Bug#33458 for a discussion) turning them into pure positions would
break far too many things as to make that the default.
We could store - in configurations and states - both, markers and
their corresponding pure positions. Then if, when restoring a
configuration or state, a marker's position has dropped to 1 while the
corresponding saved pure position is > 1, use the the pure position
instead. This should automatically fix your case and not violate any
others. Juri what do you think?
martin
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-11-30 16:58 ` Markus Triska
2018-11-30 17:47 ` martin rudalics
@ 2018-11-30 19:20 ` Eli Zaretskii
1 sibling, 0 replies; 26+ messages in thread
From: Eli Zaretskii @ 2018-11-30 19:20 UTC (permalink / raw)
To: Markus Triska; +Cc: 33532
> From: Markus Triska <triska@metalevel.at>
> Cc: Eli Zaretskii <eliz@gnu.org>, 33532@debbugs.gnu.org
> Date: Fri, 30 Nov 2018 17:58:39 +0100
>
> Or is there some advantage in using markers instead of the actual
> positions that can be restored?
Markers are much more useful default, because they preserve position
in text even if text is modified. So in the usual cases markers are a
better default.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-11-30 17:47 ` martin rudalics
@ 2018-12-01 22:52 ` Juri Linkov
2018-12-02 8:34 ` martin rudalics
0 siblings, 1 reply; 26+ messages in thread
From: Juri Linkov @ 2018-12-01 22:52 UTC (permalink / raw)
To: martin rudalics; +Cc: 33532, Markus Triska
>> Perfect! This is what I need also for current-window-configuration!
>> Also, could this be made the default? Or is there some advantage in
>> using markers instead of the actual positions that can be restored?
>
> First of all we need a "reasonable" use case. The only purpose of a
> form like
>
> (let ((str (with-current-buffer buf (buffer-string))))
> (with-current-buffer buf
> (erase-buffer)
> (insert str)))
>
> is to annihilate all marker positions in buf and I have yet to
> understand why that could be useful. I'm sure you have something more
> reasonable in mind. Once we have such a use case we can decide how to
> best support it.
>
> AFAICT Emacs' window configurations use window start and point markers
> ever since. And while they interfere with reverting buffers (see
> Bug#33458 for a discussion) turning them into pure positions would
> break far too many things as to make that the default.
>
> We could store - in configurations and states - both, markers and
> their corresponding pure positions. Then if, when restoring a
> configuration or state, a marker's position has dropped to 1 while the
> corresponding saved pure position is > 1, use the the pure position
> instead. This should automatically fix your case and not violate any
> others. Juri what do you think?
I see no drawbacks, let's try storing both (maybe together with
metadata like dired-filename).
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-01 22:52 ` Juri Linkov
@ 2018-12-02 8:34 ` martin rudalics
2018-12-03 0:52 ` Juri Linkov
0 siblings, 1 reply; 26+ messages in thread
From: martin rudalics @ 2018-12-02 8:34 UTC (permalink / raw)
To: Juri Linkov; +Cc: 33532, Markus Triska
>> We could store - in configurations and states - both, markers and
>> their corresponding pure positions. Then if, when restoring a
>> configuration or state, a marker's position has dropped to 1 while the
>> corresponding saved pure position is > 1, use the the pure position
>> instead. This should automatically fix your case and not violate any
>> others. Juri what do you think?
>
> I see no drawbacks, let's try storing both (maybe together with
> metadata like dired-filename).
It will fail when a window is stowed away in a list or configuration
and the entire stretch of the buffer from 'point-min' up to some
position at or after the stored point position is deleted. In that
case, the point of any window showing the buffer should rightfully
drop to 'point-min' but in our case it would go to the old position
when the buffer is re-shown in the window. While this might be a rare
use case, it would be confusing nevertheless.
martin
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-02 8:34 ` martin rudalics
@ 2018-12-03 0:52 ` Juri Linkov
2018-12-03 7:45 ` martin rudalics
0 siblings, 1 reply; 26+ messages in thread
From: Juri Linkov @ 2018-12-03 0:52 UTC (permalink / raw)
To: martin rudalics; +Cc: 33532, Markus Triska
>>> We could store - in configurations and states - both, markers and
>>> their corresponding pure positions. Then if, when restoring a
>>> configuration or state, a marker's position has dropped to 1 while the
>>> corresponding saved pure position is > 1, use the the pure position
>>> instead. This should automatically fix your case and not violate any
>>> others. Juri what do you think?
>>
>> I see no drawbacks, let's try storing both (maybe together with
>> metadata like dired-filename).
>
> It will fail when a window is stowed away in a list or configuration
> and the entire stretch of the buffer from 'point-min' up to some
> position at or after the stored point position is deleted. In that
> case, the point of any window showing the buffer should rightfully
> drop to 'point-min' but in our case it would go to the old position
> when the buffer is re-shown in the window. While this might be a rare
> use case, it would be confusing nevertheless.
I still think the problem is in markers dropping to 'point-min'.
Shouldn't a marker remember its previous position as a number
and try to restore it when this position becomes available again?
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-03 0:52 ` Juri Linkov
@ 2018-12-03 7:45 ` martin rudalics
2018-12-03 22:59 ` Juri Linkov
0 siblings, 1 reply; 26+ messages in thread
From: martin rudalics @ 2018-12-03 7:45 UTC (permalink / raw)
To: Juri Linkov; +Cc: 33532, Markus Triska
[-- Attachment #1: Type: text/plain, Size: 613 bytes --]
> I still think the problem is in markers dropping to 'point-min'.
Due to the buffer erasing part when reverting the buffer.
> Shouldn't a marker remember its previous position as a number
> and try to restore it when this position becomes available again?
I think that Stefan's approach to restore windows' point markers does
that in a more sophisticated way. I'll attach a patch.
But that patch does not address window configurations and states -
simply because it can't access them. We need a different solution for
those. And it obviously does not handle non-default reverters like
'dired'.
martin
[-- Attachment #2: fileio.diff --]
[-- Type: text/plain, Size: 4375 bytes --]
diff --git a/src/fileio.c b/src/fileio.c
index d979571..c5c295e 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3513,23 +3513,78 @@ CONTEXT should be a list (USER ROLE TYPE RANGE), where the list
static Lisp_Object
get_window_points_and_markers (void)
{
+ Lisp_Object buffer = Fcurrent_buffer ();
Lisp_Object pt_marker = Fpoint_marker ();
- Lisp_Object windows
- = call3 (Qget_buffer_window_list, Fcurrent_buffer (), Qnil, Qt);
- Lisp_Object window_markers = windows;
- /* Window markers (and point) are handled specially: rather than move to
- just before or just after the modified text, we try to keep the
- markers at the same distance (bug#19161).
- In general, this is wrong, but for window-markers, this should be harmless
- and is convenient for the end user when most of the file is unmodified,
- except for a few minor details near the beginning and near the end. */
+ Lisp_Object windows = window_list ();
+ Lisp_Object window;
+ Lisp_Object window_markers = Qnil;
+ /* Window markers (and point) are handled specially: rather than
+ move to just before or just after the modified text, we try to
+ keep the markers at the same distance (bug#19161).
+
+ In general, this is wrong, but for window markers, this should be
+ harmless and is convenient for the end user when most of the file
+ is unmodified, except for a few minor details near the beginning
+ and near the end.
+
+ Window point markers now include the window point markers from
+ the lists of each live window's previous and next buffers. */
for (; CONSP (windows); windows = XCDR (windows))
- if (WINDOWP (XCAR (windows)))
+ if (WINDOW_LIVE_P (window = XCAR (windows)))
{
- Lisp_Object window_marker = XWINDOW (XCAR (windows))->pointm;
- XSETCAR (windows,
- Fcons (window_marker, Fmarker_position (window_marker)));
+ struct window *w = XWINDOW (window);
+ Lisp_Object prev_buffers = w->prev_buffers;
+ Lisp_Object next_buffers = w->next_buffers;
+
+ /* Look at window's buffer first. */
+ if (EQ (WINDOW_BUFFER (w), buffer))
+ {
+ Lisp_Object window_marker = XWINDOW (XCAR (windows))->pointm;
+
+ window_markers =
+ Fcons (Fcons (window_marker, Fmarker_position (window_marker)),
+ window_markers);
+
+ /* Skip the lists of previous and next buffers. */
+ continue;
+ }
+
+ /* Scan window's previous buffers. */
+ for (; CONSP (prev_buffers); prev_buffers = XCDR (prev_buffers))
+ if (CONSP (XCAR (prev_buffers)))
+ {
+ Lisp_Object triple = XCAR (prev_buffers);
+
+ if (EQ (XCAR (triple), buffer))
+ {
+ Lisp_Object prev_marker = Fnth (make_fixnum (2), triple);
+
+ window_markers =
+ Fcons (Fcons (prev_marker, Fmarker_position (prev_marker)),
+ window_markers);
+
+ /* Skip the list of window's next buffers. */
+ continue;
+ }
+ }
+
+ /* Scan window's next buffers. */
+ for (; CONSP (next_buffers); next_buffers = XCDR (next_buffers))
+ if (CONSP (XCAR (next_buffers)))
+ {
+ Lisp_Object triple = XCAR (next_buffers);
+
+ if (EQ (XCAR (triple), buffer))
+ {
+ Lisp_Object next_marker = Fnth (make_fixnum (2), triple);
+
+ window_markers =
+ Fcons (Fcons (next_marker, Fmarker_position (next_marker)),
+ window_markers);
+ }
+ }
}
+
return Fcons (Fcons (pt_marker, Fpoint ()), window_markers);
}
@@ -3543,6 +3598,7 @@ CONTEXT should be a list (USER ROLE TYPE RANGE), where the list
Lisp_Object car = XCAR (window_markers);
Lisp_Object marker = XCAR (car);
Lisp_Object oldpos = XCDR (car);
+
if (MARKERP (marker) && FIXNUMP (oldpos)
&& XFIXNUM (oldpos) > same_at_start
&& XFIXNUM (oldpos) < same_at_end)
@@ -3552,6 +3608,7 @@ CONTEXT should be a list (USER ROLE TYPE RANGE), where the list
double growth = newsize / (double)oldsize;
ptrdiff_t newpos
= same_at_start + growth * (XFIXNUM (oldpos) - same_at_start);
+
Fset_marker (marker, make_fixnum (newpos), Qnil);
}
}
@@ -6285,7 +6342,6 @@ current when building the annotations (i.e., at least once), with that
DEFSYM (Qdelete_directory, "delete-directory");
DEFSYM (Qsubstitute_env_in_file_name, "substitute-env-in-file-name");
- DEFSYM (Qget_buffer_window_list, "get-buffer-window-list");
DEFSYM (Qstdin, "stdin");
DEFSYM (Qstdout, "stdout");
^ permalink raw reply related [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-03 7:45 ` martin rudalics
@ 2018-12-03 22:59 ` Juri Linkov
2018-12-04 6:41 ` Eli Zaretskii
2018-12-04 8:33 ` martin rudalics
0 siblings, 2 replies; 26+ messages in thread
From: Juri Linkov @ 2018-12-03 22:59 UTC (permalink / raw)
To: martin rudalics; +Cc: 33532, Markus Triska
> But that patch does not address window configurations and states -
> simply because it can't access them. We need a different solution for
> those. And it obviously does not handle non-default reverters like
> 'dired'.
What do you think about implementing the same behavior for
markers like it's implemented by 'comint-move-point-for-output'?
I.e. the same way as 'comint-move-point-for-output' moves point
to the end of the output, after erasing the buffer markers could
move their positions towards their previous valid position until
there is enough reverted text that they reach the old position.
This is straightforward to implement. I see print.c has a question
in the comments:
case PVEC_MARKER:
print_c_string ("#<marker ", printcharfun);
/* Do you think this is necessary? */
if (XMARKER (obj)->insertion_type != 0)
print_c_string ("(moves after insertion) ", printcharfun);
I think this is necessary. And this 'insertion_type' could also
move after insertion until it reaches its old position in the
reverted buffer.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-03 22:59 ` Juri Linkov
@ 2018-12-04 6:41 ` Eli Zaretskii
2018-12-04 21:44 ` Juri Linkov
2018-12-04 8:33 ` martin rudalics
1 sibling, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2018-12-04 6:41 UTC (permalink / raw)
To: Juri Linkov; +Cc: 33532, triska
> From: Juri Linkov <juri@jurta.org>
> Cc: Markus Triska <triska@metalevel.at>, Eli Zaretskii <eliz@gnu.org>, 33532@debbugs.gnu.org
> Date: Tue, 04 Dec 2018 00:59:29 +0200
>
> What do you think about implementing the same behavior for
> markers like it's implemented by 'comint-move-point-for-output'?
> I.e. the same way as 'comint-move-point-for-output' moves point
> to the end of the output, after erasing the buffer markers could
> move their positions towards their previous valid position until
> there is enough reverted text that they reach the old position.
>
> This is straightforward to implement.
Is it? Then perhaps I don't understand what "this" is, because
support for keeping the markers' positions is implemented on the C
level, and every insertion/deletion primitive runs the low-level code
which implements that. I wouldn't call changes in that area
"straightforward" at all.
Please also keep in mind that markers are the basis for other
important features, like overlays and conversion of character to byte
positions and vice versa. We need to consider the implications on all
those features.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-03 22:59 ` Juri Linkov
2018-12-04 6:41 ` Eli Zaretskii
@ 2018-12-04 8:33 ` martin rudalics
2018-12-04 21:47 ` Juri Linkov
1 sibling, 1 reply; 26+ messages in thread
From: martin rudalics @ 2018-12-04 8:33 UTC (permalink / raw)
To: Juri Linkov; +Cc: 33532, Markus Triska
[-- Attachment #1: Type: text/plain, Size: 1785 bytes --]
> What do you think about implementing the same behavior for
> markers like it's implemented by 'comint-move-point-for-output'?
> I.e. the same way as 'comint-move-point-for-output' moves point
> to the end of the output, after erasing the buffer markers could
> move their positions towards their previous valid position until
> there is enough reverted text that they reach the old position.
>
> This is straightforward to implement. I see print.c has a question
> in the comments:
>
> case PVEC_MARKER:
> print_c_string ("#<marker ", printcharfun);
> /* Do you think this is necessary? */
> if (XMARKER (obj)->insertion_type != 0)
> print_c_string ("(moves after insertion) ", printcharfun);
>
> I think this is necessary. And this 'insertion_type' could also
> move after insertion until it reaches its old position in the
> reverted buffer.
'auto-revert-tail-mode' already has
(when buffer-file-name
(setq eob (eobp))
(walk-windows
(lambda (window)
(and (eq (window-buffer window) buffer)
(= (window-point window) (point-max))
(push window eoblist)))
'no-mini t))
plus
(when buffer-file-name
(when eob (goto-char (point-max)))
(dolist (window eoblist)
(set-window-point window (point-max)))))
without changing the markers' point insertion types. We can easily
extend that to handle a window's previous buffers' points. But
changing the insertion type of markers is far too delicate with all
the implications Eli cited. We should avoid that wherever possible.
BTW, the last patch I sent was needlessly complicated - a window's
next buffers don't have any markers. I attach a better one.
martin
[-- Attachment #2: fileio.diff --]
[-- Type: text/plain, Size: 3814 bytes --]
diff --git a/src/fileio.c b/src/fileio.c
index d979571..b3fdc60 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3513,23 +3513,59 @@ CONTEXT should be a list (USER ROLE TYPE RANGE), where the list
static Lisp_Object
get_window_points_and_markers (void)
{
+ Lisp_Object buffer = Fcurrent_buffer ();
Lisp_Object pt_marker = Fpoint_marker ();
- Lisp_Object windows
- = call3 (Qget_buffer_window_list, Fcurrent_buffer (), Qnil, Qt);
- Lisp_Object window_markers = windows;
- /* Window markers (and point) are handled specially: rather than move to
- just before or just after the modified text, we try to keep the
- markers at the same distance (bug#19161).
- In general, this is wrong, but for window-markers, this should be harmless
- and is convenient for the end user when most of the file is unmodified,
- except for a few minor details near the beginning and near the end. */
+ Lisp_Object windows = window_list ();
+ Lisp_Object window;
+ Lisp_Object window_markers = Qnil;
+ /* Window markers (and point) are handled specially: rather than
+ move to just before or just after the modified text, we try to
+ keep the markers at the same distance (bug#19161).
+
+ In general, this is wrong, but for window markers, this should be
+ harmless and is convenient for the end user when most of the file
+ is unmodified, except for a few minor details near the beginning
+ and near the end.
+
+ Window point markers now include the window point markers from
+ the lists of each live window's previous buffers. */
for (; CONSP (windows); windows = XCDR (windows))
- if (WINDOWP (XCAR (windows)))
+ if (WINDOW_LIVE_P (window = XCAR (windows)))
{
- Lisp_Object window_marker = XWINDOW (XCAR (windows))->pointm;
- XSETCAR (windows,
- Fcons (window_marker, Fmarker_position (window_marker)));
+ struct window *w = XWINDOW (window);
+ Lisp_Object prev_buffers = w->prev_buffers;
+
+ /* Look at window's buffer first. */
+ if (EQ (WINDOW_BUFFER (w), buffer))
+ {
+ Lisp_Object window_marker = XWINDOW (XCAR (windows))->pointm;
+
+ window_markers =
+ Fcons (Fcons (window_marker, Fmarker_position (window_marker)),
+ window_markers);
+
+ /* Skip the list of previous buffers. */
+ continue;
+ }
+
+ /* Scan window's previous buffers. */
+ for (; CONSP (prev_buffers); prev_buffers = XCDR (prev_buffers))
+ if (CONSP (XCAR (prev_buffers)))
+ {
+ Lisp_Object triple = XCAR (prev_buffers);
+
+ if (EQ (XCAR (triple), buffer))
+ {
+ Lisp_Object prev_marker = Fnth (make_fixnum (2), triple);
+
+ window_markers =
+ Fcons (Fcons (prev_marker, Fmarker_position (prev_marker)),
+ window_markers);
+ break;
+ }
+ }
}
+
return Fcons (Fcons (pt_marker, Fpoint ()), window_markers);
}
@@ -3543,6 +3579,7 @@ CONTEXT should be a list (USER ROLE TYPE RANGE), where the list
Lisp_Object car = XCAR (window_markers);
Lisp_Object marker = XCAR (car);
Lisp_Object oldpos = XCDR (car);
+
if (MARKERP (marker) && FIXNUMP (oldpos)
&& XFIXNUM (oldpos) > same_at_start
&& XFIXNUM (oldpos) < same_at_end)
@@ -3552,6 +3589,7 @@ CONTEXT should be a list (USER ROLE TYPE RANGE), where the list
double growth = newsize / (double)oldsize;
ptrdiff_t newpos
= same_at_start + growth * (XFIXNUM (oldpos) - same_at_start);
+
Fset_marker (marker, make_fixnum (newpos), Qnil);
}
}
@@ -6285,7 +6323,6 @@ current when building the annotations (i.e., at least once), with that
DEFSYM (Qdelete_directory, "delete-directory");
DEFSYM (Qsubstitute_env_in_file_name, "substitute-env-in-file-name");
- DEFSYM (Qget_buffer_window_list, "get-buffer-window-list");
DEFSYM (Qstdin, "stdin");
DEFSYM (Qstdout, "stdout");
^ permalink raw reply related [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-04 6:41 ` Eli Zaretskii
@ 2018-12-04 21:44 ` Juri Linkov
0 siblings, 0 replies; 26+ messages in thread
From: Juri Linkov @ 2018-12-04 21:44 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 33532, triska
>> What do you think about implementing the same behavior for
>> markers like it's implemented by 'comint-move-point-for-output'?
>> I.e. the same way as 'comint-move-point-for-output' moves point
>> to the end of the output, after erasing the buffer markers could
>> move their positions towards their previous valid position until
>> there is enough reverted text that they reach the old position.
>>
>> This is straightforward to implement.
>
> Is it? Then perhaps I don't understand what "this" is, because
> support for keeping the markers' positions is implemented on the C
> level, and every insertion/deletion primitive runs the low-level code
> which implements that. I wouldn't call changes in that area
> "straightforward" at all.
Straightforward because I thought it could reuse the existing
implementation of `insertion_type' that moves the marker
after text insertion. Maybe I'm mistaken.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-04 8:33 ` martin rudalics
@ 2018-12-04 21:47 ` Juri Linkov
2018-12-05 9:16 ` martin rudalics
0 siblings, 1 reply; 26+ messages in thread
From: Juri Linkov @ 2018-12-04 21:47 UTC (permalink / raw)
To: martin rudalics; +Cc: 33532, Markus Triska
> 'auto-revert-tail-mode' already has
>
> (when buffer-file-name
> (setq eob (eobp))
> (walk-windows
> (lambda (window)
> (and (eq (window-buffer window) buffer)
> (= (window-point window) (point-max))
> (push window eoblist)))
> 'no-mini t))
>
> plus
>
> (when buffer-file-name
> (when eob (goto-char (point-max)))
> (dolist (window eoblist)
> (set-window-point window (point-max)))))
>
> without changing the markers' point insertion types. We can easily
> extend that to handle a window's previous buffers' points.
Again, no support for window configurations and non-writable window
states. But maybe it's possible to access all buffer's windows,
even windows in window configurations/states, and changes their
window points, including previous buffers' points in window
configurations/states.
BTW, I understand why reverting a dired buffer moves its point-marker to
the beginning of the buffer in the selected window window restored from
a window configuration. But I don't understand why point-marker is
moved to the end of the dired buffer in non-selected window restored
from a window configuration.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-04 21:47 ` Juri Linkov
@ 2018-12-05 9:16 ` martin rudalics
2018-12-06 0:09 ` Juri Linkov
2018-12-25 21:49 ` Juri Linkov
0 siblings, 2 replies; 26+ messages in thread
From: martin rudalics @ 2018-12-05 9:16 UTC (permalink / raw)
To: Juri Linkov; +Cc: 33532, Markus Triska
> Again, no support for window configurations and non-writable window
> states. But maybe it's possible to access all buffer's windows,
> even windows in window configurations/states, and changes their
> window points, including previous buffers' points in window
> configurations/states.
How would we handle window configurations? We could add a new
variable say 'window-configuration-list' and make sure that
configurations accessible from that variable are scanned by revert
buffer functions. Applications and users would be responsible for
removing a configuration from that list when it's no more needed.
But we also need accessor/setter functions for Lisp slots like the
windows stored in the configuration and for any such window its list
of previous and next buffers (where "any such window" could be a
deleted one). Doable but certainly non-trivial.
Window states would have to be handled in a similar way. But there
the task would be simpler: Add a variable, say 'window-states-list'
and if a state is on that list, reverting a buffer could scan it right
away. Doable but still requires some work.
> BTW, I understand why reverting a dired buffer moves its point-marker to
> the beginning of the buffer in the selected window window restored from
> a window configuration. But I don't understand why point-marker is
> moved to the end of the dired buffer in non-selected window restored
> from a window configuration.
I have no idea either.
martin
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-05 9:16 ` martin rudalics
@ 2018-12-06 0:09 ` Juri Linkov
2018-12-06 9:09 ` martin rudalics
2018-12-25 21:49 ` Juri Linkov
1 sibling, 1 reply; 26+ messages in thread
From: Juri Linkov @ 2018-12-06 0:09 UTC (permalink / raw)
To: martin rudalics; +Cc: 33532, Markus Triska
>> Again, no support for window configurations and non-writable window
>> states. But maybe it's possible to access all buffer's windows,
>> even windows in window configurations/states, and changes their
>> window points, including previous buffers' points in window
>> configurations/states.
>
> How would we handle window configurations? We could add a new
> variable say 'window-configuration-list' and make sure that
> configurations accessible from that variable are scanned by revert
> buffer functions. Applications and users would be responsible for
> removing a configuration from that list when it's no more needed.
>
> But we also need accessor/setter functions for Lisp slots like the
> windows stored in the configuration and for any such window its list
> of previous and next buffers (where "any such window" could be a
> deleted one). Doable but certainly non-trivial.
>
> Window states would have to be handled in a similar way. But there
> the task would be simpler: Add a variable, say 'window-states-list'
> and if a state is on that list, reverting a buffer could scan it right
> away. Doable but still requires some work.
Then maybe instead of immediately modifying values in windows (like
e.g. comint-postoutput-scroll-to-bottom uses get-buffer-window-list
and comint-adjust-window-point) and instead of trying to do the same
in window configurations/states, better would be to modify these values
when windows are restored from window configurations/states/prev-next-buffers?
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-06 0:09 ` Juri Linkov
@ 2018-12-06 9:09 ` martin rudalics
2018-12-06 23:38 ` Juri Linkov
0 siblings, 1 reply; 26+ messages in thread
From: martin rudalics @ 2018-12-06 9:09 UTC (permalink / raw)
To: Juri Linkov; +Cc: 33532, Markus Triska
> Then maybe instead of immediately modifying values in windows (like
> e.g. comint-postoutput-scroll-to-bottom uses get-buffer-window-list
> and comint-adjust-window-point) and instead of trying to do the same
> in window configurations/states, better would be to modify these values
> when windows are restored from window configurations/states/prev-next-buffers?
That was my idea when I proposed to go to the buffer's point when
restoring a configuration/state and the buffer had been reverted since
the configuration was saved. Note that a configuration already has to
display some live buffer when the one it stored got killed since it was
saved. Still, it might not be what users want, especially if they use
configurations to show the same buffer in multiple windows.
Note in this context that the collector does not scan window
configurations specially (or at least I cannot see where it does that
or whether any pointers in a configuration are weak). So if you save
many configurations (or states) and kill buffers often, the dead
buffer objects and the markers these configurations save - including
those from the windows' previous and next buffers - will steadily pile
up. If someone knows better, please correct me.
martin
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-06 9:09 ` martin rudalics
@ 2018-12-06 23:38 ` Juri Linkov
0 siblings, 0 replies; 26+ messages in thread
From: Juri Linkov @ 2018-12-06 23:38 UTC (permalink / raw)
To: martin rudalics; +Cc: 33532, Markus Triska
>> Then maybe instead of immediately modifying values in windows (like
>> e.g. comint-postoutput-scroll-to-bottom uses get-buffer-window-list
>> and comint-adjust-window-point) and instead of trying to do the same
>> in window configurations/states, better would be to modify these values
>> when windows are restored from window configurations/states/prev-next-buffers?
>
> That was my idea when I proposed to go to the buffer's point when
> restoring a configuration/state and the buffer had been reverted since
> the configuration was saved. Note that a configuration already has to
> display some live buffer when the one it stored got killed since it was
> saved. Still, it might not be what users want, especially if they use
> configurations to show the same buffer in multiple windows.
Also writable states need better point restoring logic, so maybe
window configurations and writable/non-writable states should support
a hook-like functions that will return the window point when
the buffer is re-displayed in the window, so e.g. dired could
set window point to the dired-filename that was displayed in
that window previously.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#33532: 26.1; set-window-configuration does not restore display start
2018-12-05 9:16 ` martin rudalics
2018-12-06 0:09 ` Juri Linkov
@ 2018-12-25 21:49 ` Juri Linkov
1 sibling, 0 replies; 26+ messages in thread
From: Juri Linkov @ 2018-12-25 21:49 UTC (permalink / raw)
To: martin rudalics; +Cc: 33532
>> BTW, I understand why reverting a dired buffer moves its point-marker to
>> the beginning of the buffer in the selected window restored from
>> a window configuration. But I don't understand why point-marker is
>> moved to the end of the dired buffer in non-selected window restored
>> from a window configuration.
>
> I have no idea either.
Please see a complete test case in bug#33871.
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2018-12-25 21:49 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-11-27 22:11 bug#33532: 26.1; set-window-configuration does not restore display start Markus Triska
2018-11-28 6:41 ` Eli Zaretskii
2018-11-28 17:13 ` Markus Triska
2018-11-28 17:41 ` Eli Zaretskii
2018-11-28 17:58 ` Markus Triska
2018-11-28 18:29 ` Eli Zaretskii
2018-11-29 8:31 ` martin rudalics
2018-11-29 18:09 ` Markus Triska
2018-11-29 19:11 ` martin rudalics
2018-11-30 16:58 ` Markus Triska
2018-11-30 17:47 ` martin rudalics
2018-12-01 22:52 ` Juri Linkov
2018-12-02 8:34 ` martin rudalics
2018-12-03 0:52 ` Juri Linkov
2018-12-03 7:45 ` martin rudalics
2018-12-03 22:59 ` Juri Linkov
2018-12-04 6:41 ` Eli Zaretskii
2018-12-04 21:44 ` Juri Linkov
2018-12-04 8:33 ` martin rudalics
2018-12-04 21:47 ` Juri Linkov
2018-12-05 9:16 ` martin rudalics
2018-12-06 0:09 ` Juri Linkov
2018-12-06 9:09 ` martin rudalics
2018-12-06 23:38 ` Juri Linkov
2018-12-25 21:49 ` Juri Linkov
2018-11-30 19:20 ` Eli Zaretskii
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).