unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* [ELPA] Brief v5.90: neighboring window merge on deletion
@ 2024-03-22 11:23 路客
  2024-03-22 13:22 ` Emanuel Berg
  2024-03-23 18:33 ` Juri Linkov
  0 siblings, 2 replies; 12+ messages in thread
From: 路客 @ 2024-03-22 11:23 UTC (permalink / raw)
  To: Emacs developers

Hi all,

In case you are interested.  I've just released the Brief editor mode
v5.90 targeting the feature `merge neighboring window on deletion'.
This functionality merges two aligned adjacent windows regardless of how
Emacs currently splits the frame.  It meaning that even if two aligned
neighboring windows in the same frame belong to different parent
(internal) windows, they can almost always be merged by reconstructing
the window tree properly.

This is probably not a big deal but for me this task had been postponed
for over 20 years due to not finding time to implement them until
recently.  It took me sometime early this year to figure out an
efficient algorithm.  It reconstructs window subtree reorganizing
vertical/horizontal spliter lines to achieve the desired window layout.
However, due to the restriction on how Emacs split windows there are
still layouts that can't be displayed by Emacs.  A typical such window
layout is:
 ______
|____| |
| |__|_|
|_|____|

Any such structure within any sub-window of a frame cannot be displayed,
as far as I know (let me know if any of you know a simple way to do so).
But for regular daily use we don't really need this kind of window
layout so it won't be supported unless a simple approach is found.

Notice that the atomic window is not yet properly handled and is
on-going, if you find any other window attribute not taken care of
properly, please be sure to let me know.

Thanks!

-- 
Best regards,
Luke Lee



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ELPA] Brief v5.90: neighboring window merge on deletion
  2024-03-22 11:23 路客
@ 2024-03-22 13:22 ` Emanuel Berg
  2024-03-23 18:33 ` Juri Linkov
  1 sibling, 0 replies; 12+ messages in thread
From: Emanuel Berg @ 2024-03-22 13:22 UTC (permalink / raw)
  To: emacs-devel

路客 wrote:

> In case you are interested. I've just released the Brief
> editor mode v5.90 targeting the feature `merge neighboring
> window on deletion'. This functionality merges two aligned
> adjacent windows regardless of how Emacs currently splits
> the frame. It meaning that even if two aligned neighboring
> windows in the same frame belong to different parent
> (internal) windows, they can almost always be merged by
> reconstructing the window tree properly.

Sounds interesting, good work! URL to source? This?

  https://elpa.gnu.org/packages/brief.html

> This is probably not a big deal but for me this task had
> been postponed for over 20 years due to not finding time

Everything always in time!

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ELPA] Brief v5.90: neighboring window merge on deletion
  2024-03-22 11:23 路客
  2024-03-22 13:22 ` Emanuel Berg
@ 2024-03-23 18:33 ` Juri Linkov
  2024-03-24  5:13   ` 路客
  1 sibling, 1 reply; 12+ messages in thread
From: Juri Linkov @ 2024-03-23 18:33 UTC (permalink / raw)
  To: 路客; +Cc: Emacs developers, martin rudalics

> In case you are interested.  I've just released the Brief editor mode
> v5.90 targeting the feature `merge neighboring window on deletion'.
> This functionality merges two aligned adjacent windows regardless of how
> Emacs currently splits the frame.  It meaning that even if two aligned
> neighboring windows in the same frame belong to different parent
> (internal) windows, they can almost always be merged by reconstructing
> the window tree properly.

Please explain how this differs from the value 'pos'
of 'delete-window-choose-selected'.

> This is probably not a big deal but for me this task had been postponed
> for over 20 years due to not finding time to implement them until
> recently.  It took me sometime early this year to figure out an
> efficient algorithm.  It reconstructs window subtree reorganizing
> vertical/horizontal spliter lines to achieve the desired window layout.
> However, due to the restriction on how Emacs split windows there are
> still layouts that can't be displayed by Emacs.  A typical such window
> layout is:
>  ______
> |____| |
> | |__|_|
> |_|____|
>
> Any such structure within any sub-window of a frame cannot be displayed,
> as far as I know (let me know if any of you know a simple way to do so).
> But for regular daily use we don't really need this kind of window
> layout so it won't be supported unless a simple approach is found.
>
> Notice that the atomic window is not yet properly handled and is
> on-going, if you find any other window attribute not taken care of
> properly, please be sure to let me know.



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ELPA] Brief v5.90: neighboring window merge on deletion
@ 2024-03-24  3:25 路客
  0 siblings, 0 replies; 12+ messages in thread
From: 路客 @ 2024-03-24  3:25 UTC (permalink / raw)
  To: Emacs developers

Emanuel Berg wrote:

> Sounds interesting, good work! URL to source? This?
> https://elpa.gnu.org/packages/brief.html

Thanks!  And yes, that's one place you can get the source.  If you like to
browse it, here is a pretty cool GNU git interface: lines #1246 ~ #1285:

http://git.savannah.gnu.org/cgit/emacs/elpa.git/tree/brief.el?h=externals/brief&id=30c5bf48784a7de2e18069a1065fa14a6ff843fe#n1246

and mainly lines #2715 ~ #3378:

http://git.savannah.gnu.org/cgit/emacs/elpa.git/tree/brief.el?h=externals/brief&id=30c5bf48784a7de2e18069a1065fa14a6ff843fe#n2715

-- 
Best regards,
Luke Lee



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ELPA] Brief v5.90: neighboring window merge on deletion
  2024-03-23 18:33 ` Juri Linkov
@ 2024-03-24  5:13   ` 路客
  2024-03-24  9:54     ` martin rudalics
  0 siblings, 1 reply; 12+ messages in thread
From: 路客 @ 2024-03-24  5:13 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Emacs developers, martin rudalics

> Please explain how this differs from the value 'pos'
> of 'delete-window-choose-selected'.

I will try, not sure if I can explain it well with pure texts.  You
will need fixed-fonts configuration to see my ASCII graphs below.

This paragraph explains how the MS-DOS Brief behaves, feel free to
skip if you already know.  In Brief, the `<F4> <arrow>' key command can
`delete and merge' the target window into your current selected window,
as long as the target window is aligned (of the same width or height
with your current selected window.  Well, I put a tolerance value of 1
character so that the target window and your selected window need only
to be `almost' the same width or height, instead of `exact match'
requirement of the original legacy MS-DOS Brief).  The target window is
chosen from your current cursor point of your selected window, to the
direction your <arrow> key points to.  So if you press `<F4> <right>',
it will try to `delete and merge' the right-side neighboring window into
your current selected window, not just deleting the right side window
and letting Emacs decide how to show the other affected windows.

Now we come to the difference between how Emacs' original `deletion'
behaves and the Brief `delete and merge' behavior.  Sometimes they are
identical.  If you use Emacs to divide your single window frame into
four parts by first vertically split the window via `C-x 3' and then
followed by two `C-x 2' in each of the just split window, you will get
a window layout like:
 _____
|_S|T_|
|__|__|

Say if we would like to delete the target upper-right window where I
marked as `T', in Emacs you need to select it and `C-x 0'.  Then the
window layout will become:
 _____
|_S|  |
|__|__|

because we split the frame vertically first so the `T' window is bound
to the right half side of the frame, regardless of the setting of the
variable `delete-window-choose-selected'.  `S' and `T' are of different
(internal) parent windows so they are not mergeable.

Now if we use Brief `<F4> <right>' command from the `S' (`S'elected)
window to delete the `T' (`T'arget) window, it will reconstruct the
windows by deleting all the windows keeping only `S', then re-split
the frame by first split horizontally the window, then reconstruct
the bottom two windows achieving the desired layout:
 _____
|_S___|
|__|__|

This reconstruction happens instantaneously so it's almost not
noticeable to users unless on slow terminals.  Sometimes in X windows
the affected window boundary might shift a little if the original layout
is complicated or is 1-character in width/height difference between
`S' and `T' (my default 1-character tolerance setting).

This also explains why the following `circular' layout is not possible
as we can't find a split line either vertically or horizontally.
 ______
|____| |
| |__|_|
|_|____|

Hope this is clarified.

On Sun, Mar 24, 2024 at 2:34 AM Juri Linkov <juri@linkov.net> wrote:
>
> > In case you are interested.  I've just released the Brief editor mode
> > v5.90 targeting the feature `merge neighboring window on deletion'.
> > This functionality merges two aligned adjacent windows regardless of how
> > Emacs currently splits the frame.  It meaning that even if two aligned
> > neighboring windows in the same frame belong to different parent
> > (internal) windows, they can almost always be merged by reconstructing
> > the window tree properly.
>
> Please explain how this differs from the value 'pos'
> of 'delete-window-choose-selected'.
>
> > This is probably not a big deal but for me this task had been postponed
> > for over 20 years due to not finding time to implement them until
> > recently.  It took me sometime early this year to figure out an
> > efficient algorithm.  It reconstructs window subtree reorganizing
> > vertical/horizontal spliter lines to achieve the desired window layout.
> > However, due to the restriction on how Emacs split windows there are
> > still layouts that can't be displayed by Emacs.  A typical such window
> > layout is:
> >  ______
> > |____| |
> > | |__|_|
> > |_|____|
> >
> > Any such structure within any sub-window of a frame cannot be displayed,
> > as far as I know (let me know if any of you know a simple way to do so).
> > But for regular daily use we don't really need this kind of window
> > layout so it won't be supported unless a simple approach is found.
> >
> > Notice that the atomic window is not yet properly handled and is
> > on-going, if you find any other window attribute not taken care of
> > properly, please be sure to let me know.



-- 
Best regards,
Luke Lee



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ELPA] Brief v5.90: neighboring window merge on deletion
  2024-03-24  5:13   ` 路客
@ 2024-03-24  9:54     ` martin rudalics
  2024-03-24 15:51       ` 路客
  0 siblings, 1 reply; 12+ messages in thread
From: martin rudalics @ 2024-03-24  9:54 UTC (permalink / raw)
  To: 路客, Juri Linkov; +Cc: Emacs developers

 > Now if we use Brief `<F4> <right>' command from the `S' (`S'elected)
 > window to delete the `T' (`T'arget) window, it will reconstruct the
 > windows by deleting all the windows keeping only `S', then re-split
 > the frame by first split horizontally the window, then reconstruct
 > the bottom two windows achieving the desired layout:
 >   _____
 > |_S___|
 > |__|__|
 >
 > This reconstruction happens instantaneously so it's almost not
 > noticeable to users unless on slow terminals.  Sometimes in X windows
 > the affected window boundary might shift a little if the original layout
 > is complicated or is 1-character in width/height difference between
 > `S' and `T' (my default 1-character tolerance setting).

Your reconstruction kills all previously live windows but 'S' and
produces new ones.  This means that buffer overlays with a 'window'
property will not work correctly in any of the new ones.  Moreover, if
such windows were stored in Lisp variables, they would be considered
dead although they apparently still exist like the ones in the lower
part of your frame.

 > This also explains why the following `circular' layout is not possible
 > as we can't find a split line either vertically or horizontally.
 >   ______
 > |____| |
 > | |__|_|
 > |_|____|

Emacs frames are guillotine-patterns.  Each window split corresponds to
a non-intersecting guillotine-cut of the parent window.

martin



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ELPA] Brief v5.90: neighboring window merge on deletion
  2024-03-24  9:54     ` martin rudalics
@ 2024-03-24 15:51       ` 路客
  2024-03-25  9:40         ` martin rudalics
  0 siblings, 1 reply; 12+ messages in thread
From: 路客 @ 2024-03-24 15:51 UTC (permalink / raw)
  To: martin rudalics; +Cc: Juri Linkov, Emacs developers

> This means that buffer overlays with a 'window' property will not work
> correctly in any of the new ones.

Overlay is a good point, but can be saved before reconstruction and
restored afterwards in the affected windows.  My code try to restore as
many window properties as possible but the overlay is surely a missed
one.  It will be taken care of in my next release.

> Moreover, if such windows were stored in Lisp variables, they would be
> considered dead although they apparently still exist like the ones in
> the lower part of your frame.

If some code store windows in variables, Emacs native window deletion
will also make it dead, besides, Emacs does not seem to provide a hook
for deleting windows thus codes that store windows in variables should
always consider the possibility if a window is dead.  I know the point
is that my window reconstruction makes it appear to be still alive.  As
with most other features, it can be configured to default OFF and switch
back to native Emacs window deletion behavior when causing problems.
But so far I haven't met such a problem yet.  If there is such a case I
hope the designers who store windows in variables provide hooks so that
I can add support on this.

Luke



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ELPA] Brief v5.90: neighboring window merge on deletion
  2024-03-24 15:51       ` 路客
@ 2024-03-25  9:40         ` martin rudalics
  2024-03-26  2:31           ` 路客
  0 siblings, 1 reply; 12+ messages in thread
From: martin rudalics @ 2024-03-25  9:40 UTC (permalink / raw)
  To: 路客; +Cc: Juri Linkov, Emacs developers

 >> This means that buffer overlays with a 'window' property will not work
 >> correctly in any of the new ones.
 >
 > Overlay is a good point, but can be saved before reconstruction and
 > restored afterwards in the affected windows.  My code try to restore as
 > many window properties as possible but the overlay is surely a missed
 > one.  It will be taken care of in my next release.

The problem is not a new one - it's been present in 'window-state-put'
ever since.  It could be easily mitigated with the help of the
'clone-of' window parameter which would have to be processed here in
xdisp.c's load_overlay_strings

       Lisp_Object window = Foverlay_get (overlay, Qwindow);
       if (WINDOWP (window) && XWINDOW (window) != it->w)
         continue;

but I never got around to do that.

 >> Moreover, if such windows were stored in Lisp variables, they would be
 >> considered dead although they apparently still exist like the ones in
 >> the lower part of your frame.
 >
 > If some code store windows in variables, Emacs native window deletion
 > will also make it dead,

Right - but IIUC your code pretends that such a window is alive, yet
with another identity.  Still, the same problem exists with
configurations produced by 'window-state-put' and the only remedy I see
is to use the 'clone-of' parameter and maybe some special function like
'windows-equal-p' that would handle it.

 > besides, Emacs does not seem to provide a hook
 > for deleting windows

'window-state-change-functions' is called in such case but it does not
provide you with a list of the windows that have been deleted.  The
Elisp manual says:

      Note that window change functions provide no information about which
   windows have been deleted since the last time they were run.  If
   necessary, applications should remember any window showing a specific
   buffer in a local variable of that buffer and update it in a function
   run by the default values of any of the hooks that are run when a window
   buffer change was detected.

We could provide a frame-based 'window-old-window-list' though if you
think it's needed.

 > thus codes that store windows in variables should
 > always consider the possibility if a window is dead.  I know the point
 > is that my window reconstruction makes it appear to be still alive.  As
 > with most other features, it can be configured to default OFF and switch
 > back to native Emacs window deletion behavior when causing problems.
 > But so far I haven't met such a problem yet.  If there is such a case I
 > hope the designers who store windows in variables provide hooks so that
 > I can add support on this.

martin



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ELPA] Brief v5.90: neighboring window merge on deletion
  2024-03-25  9:40         ` martin rudalics
@ 2024-03-26  2:31           ` 路客
  2024-03-26  9:57             ` martin rudalics
  0 siblings, 1 reply; 12+ messages in thread
From: 路客 @ 2024-03-26  2:31 UTC (permalink / raw)
  To: martin rudalics; +Cc: Juri Linkov, Emacs developers

On Mon, Mar 25, 2024 at 5:40 PM martin rudalics <rudalics@gmx.at> wrote:
> We could provide a frame-based 'window-old-window-list' though if you
> think it's needed.

Is it possible to provide some means so that we can `recycle' or
`reuse' the deleted window ID to prevent this kind of problem? In
`winner-mode' I saw the window ID is restored even after being deleted.
But that seems to be the nice side effect of `set-window-configuration'
which is not available for `window-state-put'.  With the latter I can at
best make it a `clone-of' the original deleted window.

However, as an `emulation' mode, we usually can only expect it to be `as
close as possible' to the emulated target application.  After added the
`overlay' and full window state save/restoration it's quite close, but
of course it's best if I have a way to do it better -- a way to
`recycle', `reuse' or even `restore' the deleted window ID like
`winner-mode' does.

Actually, even if so, it's still not possible to fully emulate the
`merge upon deletion' behavior while 100% keeping original Emacs
functionality -- the atomic property of two windows will gone if I force
to split them into two different window subtree, which lose the original
intention of atomicity so I might again need to add a customization
option for users who concern more about merging windows than breaking
window atomicity.  It's always a trade-off that users need to decide.

Luke



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ELPA] Brief v5.90: neighboring window merge on deletion
  2024-03-26  2:31           ` 路客
@ 2024-03-26  9:57             ` martin rudalics
  2024-03-26 12:51               ` Eli Zaretskii
  0 siblings, 1 reply; 12+ messages in thread
From: martin rudalics @ 2024-03-26  9:57 UTC (permalink / raw)
  To: 路客; +Cc: Juri Linkov, Emacs developers

 > Is it possible to provide some means so that we can `recycle' or
 > `reuse' the deleted window ID to prevent this kind of problem? In
 > `winner-mode' I saw the window ID is restored even after being deleted.
 > But that seems to be the nice side effect of `set-window-configuration'
 > which is not available for `window-state-put'.  With the latter I can at
 > best make it a `clone-of' the original deleted window.

It would be non-trivial to provide such a mechanism.  There are many
restrictions that allow 'set-window-configuration' to operate
satisfactorily and any new mechanism would have to adopt them somehow.

'undelete-frame', for example, uses 'window-state-put' to restore its
frame's windows, probably because its authors wanted to avoid the
pitfalls of making 'set-window-configuration' work for dead frames.

 > However, as an `emulation' mode, we usually can only expect it to be `as
 > close as possible' to the emulated target application.  After added the
 > `overlay' and full window state save/restoration it's quite close, but
 > of course it's best if I have a way to do it better -- a way to
 > `recycle', `reuse' or even `restore' the deleted window ID like
 > `winner-mode' does.

IIUC handling overlays with a 'window' property with current means is
much too cumbersome.  One would have to investigate all overlays in the
window's buffer and duplicate them if they have a 'window' property that
references the cloned window.  In practice, most overlays don't have
such a property.

 > Actually, even if so, it's still not possible to fully emulate the
 > `merge upon deletion' behavior while 100% keeping original Emacs
 > functionality -- the atomic property of two windows will gone if I force
 > to split them into two different window subtree, which lose the original
 > intention of atomicity so I might again need to add a customization
 > option for users who concern more about merging windows than breaking
 > window atomicity.  It's always a trade-off that users need to decide.

Atomicity is a property of a parent window.  If your operation clones
the parent window, it should retain the property regardless of which its
new child windows are.

martin



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ELPA] Brief v5.90: neighboring window merge on deletion
  2024-03-26  9:57             ` martin rudalics
@ 2024-03-26 12:51               ` Eli Zaretskii
  2024-03-27  7:35                 ` martin rudalics
  0 siblings, 1 reply; 12+ messages in thread
From: Eli Zaretskii @ 2024-03-26 12:51 UTC (permalink / raw)
  To: martin rudalics; +Cc: luke.yx.lee, juri, emacs-devel

> Date: Tue, 26 Mar 2024 10:57:23 +0100
> Cc: Juri Linkov <juri@linkov.net>, Emacs developers <emacs-devel@gnu.org>
> From: martin rudalics <rudalics@gmx.at>
> 
>  > However, as an `emulation' mode, we usually can only expect it to be `as
>  > close as possible' to the emulated target application.  After added the
>  > `overlay' and full window state save/restoration it's quite close, but
>  > of course it's best if I have a way to do it better -- a way to
>  > `recycle', `reuse' or even `restore' the deleted window ID like
>  > `winner-mode' does.
> 
> IIUC handling overlays with a 'window' property with current means is
> much too cumbersome.  One would have to investigate all overlays in the
> window's buffer and duplicate them if they have a 'window' property that
> references the cloned window.  In practice, most overlays don't have
> such a property.

But crucially, the overlay that implements region highlighting does.



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [ELPA] Brief v5.90: neighboring window merge on deletion
  2024-03-26 12:51               ` Eli Zaretskii
@ 2024-03-27  7:35                 ` martin rudalics
  0 siblings, 0 replies; 12+ messages in thread
From: martin rudalics @ 2024-03-27  7:35 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: luke.yx.lee, juri, emacs-devel

 >> IIUC handling overlays with a 'window' property with current means is
 >> much too cumbersome.  One would have to investigate all overlays in the
 >> window's buffer and duplicate them if they have a 'window' property that
 >> references the cloned window.  In practice, most overlays don't have
 >> such a property.
 >
 > But crucially, the overlay that implements region highlighting does.

This, cursor face highlighting and rectangle overlays are special.  They
change with the selected window, the region and/or the position of point
and must be regenerated in every redisplay cycle anyway.  Which means
that they need no special attention when cloning a frame or window
configuration.  Others, like the one used by 'hl-line-mode' are handled
via a post command hook and probably need no special attention either.

The overlays used by 'compare-windows-highlight' or
'isearch-lazy-highlight-match' seem more sensitive in this regard.  I
doubt that they would survive a change where windows do not preserve
their identity.

martin



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2024-03-27  7:35 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-24  3:25 [ELPA] Brief v5.90: neighboring window merge on deletion 路客
  -- strict thread matches above, loose matches on Subject: below --
2024-03-22 11:23 路客
2024-03-22 13:22 ` Emanuel Berg
2024-03-23 18:33 ` Juri Linkov
2024-03-24  5:13   ` 路客
2024-03-24  9:54     ` martin rudalics
2024-03-24 15:51       ` 路客
2024-03-25  9:40         ` martin rudalics
2024-03-26  2:31           ` 路客
2024-03-26  9:57             ` martin rudalics
2024-03-26 12:51               ` Eli Zaretskii
2024-03-27  7:35                 ` martin rudalics

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).