GNU bug report logs - #68235
29.1.90; Switching tabs stops following process output in selected window

Previous Next

Package: emacs;

Reported by: Dan McCarthy <daniel.c.mccarthy <at> gmail.com>

Date: Wed, 3 Jan 2024 20:49:02 UTC

Severity: normal

Found in version 29.1.90

Fixed in version 30.0.50

Done: Juri Linkov <juri <at> linkov.net>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 68235 in the body.
You can then email your comments to 68235 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Wed, 03 Jan 2024 20:49:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Dan McCarthy <daniel.c.mccarthy <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Wed, 03 Jan 2024 20:49:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Dan McCarthy <daniel.c.mccarthy <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: 29.1.90;
 Switching tabs stops following process output in selected window
Date: Wed, 3 Jan 2024 15:48:21 -0500
[Message part 1 (text/plain, inline)]
With two tabs open, start a compilation or some other long-running
job. Move point to the bottom with M->. Switch to the other tab, then
switch back. Point will now be fixed at wherever it was when you first
switched.

If the compilation window isn't selected, however, switching tabs does
what I expected: point continues to be at the bottom, following the
output as it appears.

In GNU Emacs 29.1.90 (build 1, x86_64-pc-linux-gnu, GTK+ Version
 2.24.33, cairo version 1.16.0) of 2023-10-23 built on solstice
Windowing system distributor 'The X.Org Foundation', version 11.0.12101007
System Description: Debian GNU/Linux 12 (bookworm)

Configured using:
 'configure --with-dbus'

Configured features:
CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG
LIBSELINUX LIBXML2 MODULES NOTIFY INOTIFY PDUMPER PNG SECCOMP SOUND
SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM XINPUT2 XPM
GTK2 ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Shell

Minor modes in effect:
  bug-reference-mode: t
  desktop-save-mode: t
  global-git-commit-mode: t
  magit-auto-revert-mode: t
  server-mode: t
  shell-dirtrack-mode: t
  hexl-follow-ascii: t
  projectile-mode: t
  comint-fontify-input-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tab-bar-history-mode: t
  tab-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  column-number-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
~/emacs-lisp/ecf-mode/dcm-general hides ~/emacs-lisp/dcm-general
~/emacs-lisp/c-eldoc hides
/home/dan/.emacs.d/elpa/c-eldoc-20201004.2347/c-eldoc
~/emacs-lisp/connection hides
/home/dan/.emacs.d/elpa/connection-20191111.446/connection
~/emacs-lisp/link hides /home/dan/.emacs.d/elpa/link-20191111.446/link
/home/dan/.emacs.d/elpa/transient-20231019.1421/transient hides
/home/dan/build/emacs-29.1.90/lisp/transient
~/emacs-lisp/css-mode hides
/home/dan/build/emacs-29.1.90/lisp/textmodes/css-mode
/home/dan/.emacs.d/elpa/csharp-mode-20221126.2005/csharp-mode hides
/home/dan/build/emacs-29.1.90/lisp/progmodes/csharp-mode
/home/dan/.emacs.d/elpa/dictionary-20201001.1727/dictionary hides
/home/dan/build/emacs-29.1.90/lisp/net/dictionary
~/emacs-lisp/greek hides /home/dan/build/emacs-29.1.90/lisp/language/greek

Features:
(shadow sort mail-extr emacsbug vc-svn pcmpl-gnu sgml-mode facemenu dom
dabbrev cus-edit cus-start mm-archive gnutls network-stream url-cache
url-http url-auth url-gw nsm term/xterm xterm vc git-rebase mule-diag
python emacs-news-mode pcmpl-linux ffap magit-patch display-line-numbers
rect tabify man tramp-cmds doc-view jka-compr js c-ts-common find-dired
rfc2104 noutline outline view cl-print make-mode image-mode exif
cal-move shortdoc help-fns radix-tree pp wid-edit descr-text pcmpl-unix
conf-mode misearch multi-isearch ruler-mode hl-line vc-hg vc-bzr
goto-addr etags fileloop generator xref magit-extras magit-svn
face-remap sh-script smie treesit executable tramp-cache time-stamp
tramp-sh dired-aux term disp-table ehelp mule-util diary-lib
diary-loaddefs cal-menu calendar cal-loaddefs bug-reference desktop
frameset cua-base cus-load clang-format+ clang-format acme-search quack
cmuscheme scheme advice clone-log-mode scc-mode 608-unicode ecf-mode
dcm-general tar-mode arc-mode archive-mode notifications dbus xml
dictionary link connection magit-submodule magit-blame magit-stash
magit-reflog magit-bisect magit-push magit-pull magit-fetch magit-clone
magit-remote magit-commit magit-sequence magit-notes magit-worktree
magit-tag magit-merge magit-branch magit-reset magit-files magit-refs
magit-status magit magit-repos magit-apply magit-wip magit-log
magit-diff smerge-mode diff git-commit log-edit message sendmail
yank-media puny dired dired-loaddefs rfc822 mml mml-sec epa epg rfc6068
epg-config gnus-util mm-decode mm-bodies mm-encode mail-parse rfc2231
rfc2047 rfc2045 mm-util ietf-drums mail-prsvr mailabbrev mail-utils
gmm-utils mailheader pcvs-util add-log magit-core magit-autorevert
autorevert filenotify magit-margin magit-transient magit-process
with-editor server magit-mode derived transient cl-extra edmacro kmacro
help-mode magit-git magit-base which-func vc-git diff-mode easy-mmode
vc-dispatcher ido magit-section cursor-sensor crm dash compat tramp
tramp-loaddefs trampver tramp-integration files-x tramp-compat shell
pcomplete parse-time iso8601 time-date format-spec vanc-init bindat
vanc-mode hexl php-mode mode-local find-func imenu speedbar ezimage
dframe php-face php rx php-project projectile lisp-mnt grep ibuf-ext
ibuffer ibuffer-loaddefs flymake-proc flymake project compile
text-property-search comint ansi-osc ansi-color ring warnings icons
thingatpt css-mode cc-mode cc-fonts cc-guess cc-menus cc-cmds cc-styles
cc-align cc-engine cc-vars cc-defs cl finder-inf archive-rpm-autoloads
c-eldoc-autoloads clang-format-autoloads indent-tools-autoloads
hydra-autoloads lv-autoloads magit-svn-autoloads magit-autoloads pcase
magit-section-autoloads git-commit-autoloads dash-autoloads
php-mode-autoloads projectile-autoloads pydoc-autoloads s-autoloads
tramp-term-autoloads transient-autoloads with-editor-autoloads info
compat-autoloads yafolding-autoloads yaml-mode-autoloads
yaml-pro-autoloads yaml-autoloads package browse-url url url-proxy
url-privacy url-expand url-methods url-history url-cookie
generate-lisp-file url-domsuf url-util mailcap url-handlers url-parse
auth-source cl-seq eieio eieio-core cl-macs password-cache json subr-x
map byte-opt gv bytecomp byte-compile url-vars cl-loaddefs cl-lib rmc
iso-transl tooltip cconv eldoc paren electric uniquify ediff-hook
vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win
term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode lisp-mode prog-mode register
page tab-bar menu-bar rfn-eshadow isearch easymenu timer select
scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors
frame minibuffer nadvice seq simple cl-generic indonesian philippine
cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese composite emoji-zwj charscript
charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp
files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable backquote
threads dbusbind inotify dynamic-setting system-font-setting
font-render-setting cairo move-toolbar gtk x-toolkit xinput2 x multi-tty
make-network-process emacs)

Memory information:
((conses 16 2656374 298496)
 (symbols 48 52033 4)
 (strings 32 391623 32488)
 (string-bytes 1 14644301)
 (vectors 16 100900)
 (vector-slots 8 2407891 129759)
 (floats 8 246 538)
 (intervals 56 300877 27375)
 (buffers 976 170))
[Message part 2 (text/html, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Thu, 04 Jan 2024 06:10:02 GMT) Full text and rfc822 format available.

Message #8 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Dan McCarthy <daniel.c.mccarthy <at> gmail.com>,
 martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90;
 Switching tabs stops following process output in selected window
Date: Thu, 04 Jan 2024 08:09:12 +0200
> From: Dan McCarthy <daniel.c.mccarthy <at> gmail.com>
> Date: Wed, 3 Jan 2024 15:48:21 -0500
> 
> With two tabs open, start a compilation or some other long-running
> job. Move point to the bottom with M->. Switch to the other tab, then
> switch back. Point will now be fixed at wherever it was when you first
> switched.
> 
> If the compilation window isn't selected, however, switching tabs does
> what I expected: point continues to be at the bottom, following the
> output as it appears.

Does playing with the value of switch-to-buffer-preserve-window-point
change anything in what you see?

Martin, is saving and restoring window configuration supposed to
preserve the output following in *compilation* windows?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Thu, 04 Jan 2024 10:24:02 GMT) Full text and rfc822 format available.

Message #11 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Eli Zaretskii <eliz <at> gnu.org>, Dan McCarthy <daniel.c.mccarthy <at> gmail.com>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Thu, 4 Jan 2024 11:23:45 +0100
> Martin, is saving and restoring window configuration supposed to
> preserve the output following in *compilation* windows?

It's supposed to preserve markers other than in the selected window.  So
it will depend on whether the *compilation* window gets selected.  But
note that 'current-window-configuration' uses
'window-point-insertion-type' for the point marker which by default
stays behind inserted text (IIRC).

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Thu, 04 Jan 2024 10:43:02 GMT) Full text and rfc822 format available.

Message #14 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Thu, 04 Jan 2024 12:42:04 +0200
> Date: Thu, 4 Jan 2024 11:23:45 +0100
> Cc: 68235 <at> debbugs.gnu.org
> From: martin rudalics <rudalics <at> gmx.at>
> 
>  > Martin, is saving and restoring window configuration supposed to
>  > preserve the output following in *compilation* windows?
> 
> It's supposed to preserve markers other than in the selected window.  So
> it will depend on whether the *compilation* window gets selected.  But
> note that 'current-window-configuration' uses
> 'window-point-insertion-type' for the point marker which by default
> stays behind inserted text (IIRC).

So I guess what the OP sees is expected behavior, or am I missing
something?

In general, IME the fact that a window follows the end of compilation
output is indeed very ephemeral in Emacs, so hearing that it happens
as result of tab-bing away doesn't surprise me at all.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Thu, 04 Jan 2024 17:14:03 GMT) Full text and rfc822 format available.

Message #17 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: Dan McCarthy <daniel.c.mccarthy <at> gmail.com>, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Thu, 04 Jan 2024 19:07:39 +0200
>> Martin, is saving and restoring window configuration supposed to
>> preserve the output following in *compilation* windows?
>
> It's supposed to preserve markers other than in the selected window.  So
> it will depend on whether the *compilation* window gets selected.  But
> note that 'current-window-configuration' uses
> 'window-point-insertion-type' for the point marker which by default
> stays behind inserted text (IIRC).

Everything works nicely, and point follows the output,
when this code is removed from 'tab-bar-select-tab':

  ;; set-window-configuration does not restore the value of
  ;; point in the current buffer, so restore it separately.
  (when (and (markerp wc-point)
             (marker-buffer wc-point)
             ;; FIXME: After dired-revert, marker relocates to 1.
             ;; window-configuration restores point to global point
             ;; in this dired buffer, not to its window point,
             ;; but this is slightly better than 1.
             ;; Maybe better to save dired-filename in each window?
             (not (eq 1 (marker-position wc-point))))
    (goto-char wc-point))

The problem is that I still can't figure out in what cases point should be
restored manually.  For example, when a buffer was reverted in another
window configuration, then better to restore point manually to override
an invalidated marker?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Thu, 04 Jan 2024 17:49:02 GMT) Full text and rfc822 format available.

Message #20 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Juri Linkov <juri <at> linkov.net>
Cc: rudalics <at> gmx.at, 68235 <at> debbugs.gnu.org, daniel.c.mccarthy <at> gmail.com
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Thu, 04 Jan 2024 19:48:28 +0200
> From: Juri Linkov <juri <at> linkov.net>
> Cc: Eli Zaretskii <eliz <at> gnu.org>,  Dan McCarthy
>  <daniel.c.mccarthy <at> gmail.com>,  68235 <at> debbugs.gnu.org
> Date: Thu, 04 Jan 2024 19:07:39 +0200
> 
> Everything works nicely, and point follows the output,
> when this code is removed from 'tab-bar-select-tab':
> 
>   ;; set-window-configuration does not restore the value of
>   ;; point in the current buffer, so restore it separately.
>   (when (and (markerp wc-point)
>              (marker-buffer wc-point)
>              ;; FIXME: After dired-revert, marker relocates to 1.
>              ;; window-configuration restores point to global point
>              ;; in this dired buffer, not to its window point,
>              ;; but this is slightly better than 1.
>              ;; Maybe better to save dired-filename in each window?
>              (not (eq 1 (marker-position wc-point))))
>     (goto-char wc-point))

Maybe we should make exceptions in buffers like *completions*?

In general, restoring point is a good idea.

> The problem is that I still can't figure out in what cases point should be
> restored manually.

When the buffer was shown in another window, I think.  Martin might
have a definite answer.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Fri, 05 Jan 2024 09:25:01 GMT) Full text and rfc822 format available.

Message #23 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Eli Zaretskii <eliz <at> gnu.org>, Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Fri, 5 Jan 2024 10:24:06 +0100
>> Everything works nicely, and point follows the output,
>> when this code is removed from 'tab-bar-select-tab':
>>
>>    ;; set-window-configuration does not restore the value of
>>    ;; point in the current buffer, so restore it separately.
>>    (when (and (markerp wc-point)
>>               (marker-buffer wc-point)
>>               ;; FIXME: After dired-revert, marker relocates to 1.
>>               ;; window-configuration restores point to global point
>>               ;; in this dired buffer, not to its window point,
>>               ;; but this is slightly better than 1.
>>               ;; Maybe better to save dired-filename in each window?
>>               (not (eq 1 (marker-position wc-point))))
>>      (goto-char wc-point))
>
> Maybe we should make exceptions in buffers like *completions*?
>
> In general, restoring point is a good idea.
>
>> The problem is that I still can't figure out in what cases point should be
>> restored manually.
>
> When the buffer was shown in another window, I think.  Martin might
> have a definite answer.

I think the snippet above should be executed iff the buffer's
'window-point-insertion-type' is nil.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sat, 06 Jan 2024 17:43:02 GMT) Full text and rfc822 format available.

Message #26 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sat, 06 Jan 2024 19:36:25 +0200
>>> Everything works nicely, and point follows the output,
>>> when this code is removed from 'tab-bar-select-tab':
>>>
>>>    ;; set-window-configuration does not restore the value of
>>>    ;; point in the current buffer, so restore it separately.
>>>    (when (and (markerp wc-point)
>>>               (marker-buffer wc-point)
>>>               ;; FIXME: After dired-revert, marker relocates to 1.
>>>               ;; window-configuration restores point to global point
>>>               ;; in this dired buffer, not to its window point,
>>>               ;; but this is slightly better than 1.
>>>               ;; Maybe better to save dired-filename in each window?
>>>               (not (eq 1 (marker-position wc-point))))
>>>      (goto-char wc-point))
>>
>> Maybe we should make exceptions in buffers like *completions*?
>>
>> In general, restoring point is a good idea.
>>
>>> The problem is that I still can't figure out in what cases point should be
>>> restored manually.
>>
>> When the buffer was shown in another window, I think.  Martin might
>> have a definite answer.
>
> I think the snippet above should be executed iff the buffer's
> 'window-point-insertion-type' is nil.

window-point-insertion-type is nil by default, but I'd definitely want
point to follow the output, that means not using the snippet above.

OTOH, this snippet can't be removed because it supports tab-local point.
For example, open the same buffer in two tabs and move point to another
place.  Like with window-point, the position of point in tabs should be
preserved as well.  So probably we need to add special-casing for comint
buffers to follow the output.

But could you explain why such special-casing is not needed for
non-selected windows?  How set-window-configuration does the right
thing for points in non-selected windows to follow the output?
Maybe it's possible to do the same with point in the selected window?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 07 Jan 2024 14:56:02 GMT) Full text and rfc822 format available.

Message #29 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Sun, 7 Jan 2024 15:54:44 +0100
> window-point-insertion-type is nil by default, but I'd definitely want
> point to follow the output, that means not using the snippet above.

But 'window-point-insertion-type' is buffer-locally t in all sorts of
compilation buffers and that is the subject of this bug report.  Right?

> OTOH, this snippet can't be removed because it supports tab-local point.
> For example, open the same buffer in two tabs and move point to another
> place.  Like with window-point, the position of point in tabs should be
> preserved as well.  So probably we need to add special-casing for comint
> buffers to follow the output.

And I meant to use the buffer-local value of
'window-point-insertion-type' as insertion type for 'wc-point'.

> But could you explain why such special-casing is not needed for
> non-selected windows?  How set-window-configuration does the right
> thing for points in non-selected windows to follow the output?
> Maybe it's possible to do the same with point in the selected window?

For an unselected window, 'set-window-configuration' uses that window's
point marker from the saved configuration and that one should follow
inserted text according to the value of 'window-point-insertion-type' in
that window's buffer.  For the selected window, that window's buffer's
point is "usually" unchanged from where it was just before restoring the
configuration.

In either case I doubt that the 'set-window-configuration' code does
anything wrong here.  IIRC there were problems in the dired buffer
reverting code, namely that it did not preserve the position of point
reasonably and you tried to handle that via 'wc-point'.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 07 Jan 2024 16:53:02 GMT) Full text and rfc822 format available.

Message #32 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sun, 07 Jan 2024 18:45:33 +0200
>> window-point-insertion-type is nil by default, but I'd definitely want
>> point to follow the output, that means not using the snippet above.
>
> But 'window-point-insertion-type' is buffer-locally t in all sorts of
> compilation buffers and that is the subject of this bug report.  Right?

Thanks, now I see that 'comint-mode', 'compilation-mode' and some
other modes set buffer-local 'window-point-insertion-type' to t.

> And I meant to use the buffer-local value of
> 'window-point-insertion-type' as insertion type for 'wc-point'.

Ah, now I see that 'copy-marker' supports the argument for
'window-point-insertion-type'.

>> But could you explain why such special-casing is not needed for
>> non-selected windows?  How set-window-configuration does the right
>> thing for points in non-selected windows to follow the output?
>> Maybe it's possible to do the same with point in the selected window?
>
> For an unselected window, 'set-window-configuration' uses that window's
> point marker from the saved configuration and that one should follow
> inserted text according to the value of 'window-point-insertion-type' in
> that window's buffer.  For the selected window, that window's buffer's
> point is "usually" unchanged from where it was just before restoring the
> configuration.

Indeed, the difference between selected/non-selected windows is here:

	  /* Save w's value of point in the window configuration.  If w
	     is the selected window, then get the value of point from
	     the buffer; pointm is garbage in the selected window.  */
	  if (EQ (window, selected_window))
	    p->pointm = build_marker (XBUFFER (w->contents),
				      BUF_PT (XBUFFER (w->contents)),
				      BUF_PT_BYTE (XBUFFER (w->contents)));
	  else
	    p->pointm = Fcopy_marker (w->pointm, Qnil);
	  p->old_pointm = Fcopy_marker (w->old_pointm, Qnil);
	  XMARKER (p->pointm)->insertion_type = window_point_insertion_type;
	  XMARKER (p->old_pointm)->insertion_type = window_point_insertion_type;

So the complete fix is just in 1 line:

diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 7d491dc2f38..80cf94016b8 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -1302,7 +1302,7 @@ tab-bar--tab
       (ws . ,(window-state-get
               (frame-root-window (or frame (selected-frame))) 'writable))
       (wc . ,(current-window-configuration))
-      (wc-point . ,(point-marker))
+      (wc-point . ,(copy-marker (window-point) window-point-insertion-type))
       (wc-bl . ,bl)
       (wc-bbl . ,bbl)
       ,@(when tab-bar-history-mode




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 07 Jan 2024 16:53:02 GMT) Full text and rfc822 format available.

Message #35 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sun, 07 Jan 2024 18:49:36 +0200
> In either case I doubt that the 'set-window-configuration' code does
> anything wrong here.  IIRC there were problems in the dired buffer
> reverting code, namely that it did not preserve the position of point
> reasonably and you tried to handle that via 'wc-point'.

The dired revert is a separate problem unrelated to this bug report.
But still we need to remove this ad-hoc condition:

            (when (and (markerp wc-point)
                       (marker-buffer wc-point)
                       ;; FIXME: After dired-revert, marker relocates to 1.
                       ;; window-configuration restores point to global point
                       ;; in this dired buffer, not to its window point,
                       ;; but this is slightly better than 1.
                       ;; Maybe better to save dired-filename in each window?
                       (not (eq 1 (marker-position wc-point))))
              (goto-char wc-point))

Checking for (not (eq 1 (marker-position wc-point)))
is the wrong thing to do because it also affects non-dired buffers.

But I have no idea how to handle dired revert that moves the marker
to the top of the buffer.  Adding special-handling for dired here
also doesn't look right.

Maybe it's possible to mark the marker as invalidated after reverting?
Then could check for the invalidated status here.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 08 Jan 2024 08:56:02 GMT) Full text and rfc822 format available.

Message #38 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Mon, 8 Jan 2024 09:55:01 +0100
> Indeed, the difference between selected/non-selected windows is here:
>
> 	  /* Save w's value of point in the window configuration.  If w
> 	     is the selected window, then get the value of point from
> 	     the buffer; pointm is garbage in the selected window.  */

This is one difference among many.  Fset_window_configuration also deals
with the cases that the selected window and/or the current buffer
changed in between saving and restoring the configuration.

> +      (wc-point . ,(copy-marker (window-point) window-point-insertion-type))

I didn't look but note that the window's buffer must be current here to
get the buffer-local value of 'window-point-insertion-type'.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 09 Jan 2024 17:31:02 GMT) Full text and rfc822 format available.

Message #41 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Tue, 09 Jan 2024 19:23:17 +0200
close 68235 30.0.50
thanks

>> +      (wc-point . ,(copy-marker (window-point) window-point-insertion-type))
>
> I didn't look but note that the window's buffer must be current here to
> get the buffer-local value of 'window-point-insertion-type'.

Thanks for the notice.  This looks correct since the buffer
is expected to be current.

This change took so unexpected shape that I'm unsure about fixing this
on the emacs-29 branch.  So now pushed to master, and closed.




bug marked as fixed in version 30.0.50, send any further explanations to 68235 <at> debbugs.gnu.org and Dan McCarthy <daniel.c.mccarthy <at> gmail.com> Request was from Juri Linkov <juri <at> linkov.net> to control <at> debbugs.gnu.org. (Tue, 09 Jan 2024 17:31:03 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 09 Jan 2024 17:32:02 GMT) Full text and rfc822 format available.

Message #46 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Tue, 09 Jan 2024 19:25:14 +0200
> The dired revert is a separate problem unrelated to this bug report.
> But still we need to remove this ad-hoc condition:
>
>             (when (and (markerp wc-point)
>                        (marker-buffer wc-point)
>                        ;; FIXME: After dired-revert, marker relocates to 1.
>                        ;; window-configuration restores point to global point
>                        ;; in this dired buffer, not to its window point,
>                        ;; but this is slightly better than 1.
>                        ;; Maybe better to save dired-filename in each window?
>                        (not (eq 1 (marker-position wc-point))))
>               (goto-char wc-point))
>
> Checking for (not (eq 1 (marker-position wc-point)))
> is the wrong thing to do because it also affects non-dired buffers.
>
> But I have no idea how to handle dired revert that moves the marker
> to the top of the buffer.  Adding special-handling for dired here
> also doesn't look right.
>
> Maybe it's possible to mark the marker as invalidated after reverting?
> Then could check for the invalidated status here.

Actually the problem is somewhere else because after dired revert
point is relocated to the top of the buffer even in non-selected windows
in window-configuration.  So trying to manually preserve point
in the selected window is not of much help.  Therefore I just
removed the special-handling of dired revert in master.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Wed, 10 Jan 2024 08:38:02 GMT) Full text and rfc822 format available.

Message #49 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Wed, 10 Jan 2024 09:37:33 +0100
> Actually the problem is somewhere else because after dired revert
> point is relocated to the top of the buffer even in non-selected windows
> in window-configuration.  So trying to manually preserve point
> in the selected window is not of much help.  Therefore I just
> removed the special-handling of dired revert in master.

Do you remember the bug this was supposed to fix?

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Wed, 10 Jan 2024 17:22:03 GMT) Full text and rfc822 format available.

Message #52 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Wed, 10 Jan 2024 19:08:45 +0200
>> Actually the problem is somewhere else because after dired revert
>> point is relocated to the top of the buffer even in non-selected windows
>> in window-configuration.  So trying to manually preserve point
>> in the selected window is not of much help.  Therefore I just
>> removed the special-handling of dired revert in master.
>
> Do you remember the bug this was supposed to fix?

The dedicated bug report is this:

bug#33871: Revert Dired window saved in window configuration

Also something related was discussed in:

bug#27243: dired-auto-revert-buffer jumps point to beginning of buffer
bug#33458: dired loses position when reverted from outside place

and maybe more.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Thu, 11 Jan 2024 09:15:02 GMT) Full text and rfc822 format available.

Message #55 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Thu, 11 Jan 2024 10:14:48 +0100
>>> Actually the problem is somewhere else because after dired revert
>>> point is relocated to the top of the buffer even in non-selected windows
>>> in window-configuration.  So trying to manually preserve point
>>> in the selected window is not of much help.  Therefore I just
>>> removed the special-handling of dired revert in master.
>>
>> Do you remember the bug this was supposed to fix?
>
> The dedicated bug report is this:
>
> bug#33871: Revert Dired window saved in window configuration
>
> Also something related was discussed in:
>
> bug#27243: dired-auto-revert-buffer jumps point to beginning of buffer
> bug#33458: dired loses position when reverted from outside place
>
> and maybe more.

IIUC 'dired-save-positions' and 'dired-restore-positions' are supposed
to handle these bug scenarios in "normal" (user driven) dired reverting.
Do they?  If so, why does saving and restoring a window configuration
not use them?

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Fri, 12 Jan 2024 07:47:02 GMT) Full text and rfc822 format available.

Message #58 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Fri, 12 Jan 2024 09:37:59 +0200
>>>> Actually the problem is somewhere else because after dired revert
>>>> point is relocated to the top of the buffer even in non-selected windows
>>>> in window-configuration.  So trying to manually preserve point
>>>> in the selected window is not of much help.  Therefore I just
>>>> removed the special-handling of dired revert in master.
>>>
>>> Do you remember the bug this was supposed to fix?
>>
>> The dedicated bug report is this:
>>
>> bug#33871: Revert Dired window saved in window configuration
>>
>> Also something related was discussed in:
>>
>> bug#27243: dired-auto-revert-buffer jumps point to beginning of buffer
>> bug#33458: dired loses position when reverted from outside place
>>
>> and maybe more.
>
> IIUC 'dired-save-positions' and 'dired-restore-positions' are supposed
> to handle these bug scenarios in "normal" (user driven) dired reverting.
> Do they?  If so, why does saving and restoring a window configuration
> not use them?

This is because 'dired-save-positions' and 'dired-restore-positions'
can't update positions in all existing window configurations
that are not yet garbage-collected.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sat, 13 Jan 2024 10:40:02 GMT) Full text and rfc822 format available.

Message #61 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Sat, 13 Jan 2024 11:38:56 +0100
>> IIUC 'dired-save-positions' and 'dired-restore-positions' are supposed
>> to handle these bug scenarios in "normal" (user driven) dired reverting.
>> Do they?  If so, why does saving and restoring a window configuration
>> not use them?
>
> This is because 'dired-save-positions' and 'dired-restore-positions'
> can't update positions in all existing window configurations
> that are not yet garbage-collected.

So we'd need a persistent window parameter

(1) whose value is set to dired's file name at point in
'current-window-configuration'

(2) and allows to restore the window's point appropriately in
'set-window-configuration'.

For (1) we have two possibilities.  Either dired itself maintains it
every time its window point changes which is very tedious.  Or we make
the parameter a function that is run by 'current-window-configuration'
here:

		    /* If the window has a value for the parameter,
		       save it.  */
		    p->window_parameters = Fcons (Fcons (XCAR (par), XCDR (par)),
					   p->window_parameters);

When XCAR (par) is a function, that function would store the current
file name at the window's point in the cdr of the saved parameter.  This
would mean to offer one more facility for people to shoot themselves in
their foot.

For (2) we can either provide a hook that 'set-window-configuration'
runs or in

		    /* Always restore a non-nil value.  */
		    Fset_window_parameter (window, XCAR (pers), XCDR (pers));

restore the saved position when XCAR (pers) is a function - the file
name would be in XCDR (pers).  Not for the faint of heart either,
because of the current buffer/selected window dances in
'set-window-configuration'.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sat, 13 Jan 2024 15:03:02 GMT) Full text and rfc822 format available.

Message #64 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Sat, 13 Jan 2024 16:02:32 +0100
> So we'd need a persistent window parameter
>
> (1) whose value is set to dired's file name at point in
> 'current-window-configuration'
>
> (2) and allows to restore the window's point appropriately in
> 'set-window-configuration'.

I now think that we need two or three hooks:

- 'pre-current-window-configuration-functions', an abnormal hook that
  receives one argument - the frame whose configuration shall be
  recorded.  'dired' has to set a persistent window parameter, for each
  window on that frame it uses, whose value is whatever is needed to
  restore the present state of the buffer in that window.

- 'pre-set-window-configuration', an abnormal hook that receives one
  argument - the frame whose configuration is about to be restored.
  'dired' would have to save away its parameter values of all windows
  it currently owns on that frame.

- 'post-set-window-configuration-functions', an abnormal hook that
  receives one argument - the frame whose configuration was just
  restored.  'dired' would have to examine its persistent parameters of
  all windows on that frame and restore the previous state for them
  unless maybe a parameter in 'pre-set-window-configuration' tells it
  not to do that.

The latter would be responsible for resolving conflicts like what to do
when the same dired buffer is shown in the selected window of the saved
and current configuration but their points are on different file names.
Whether 'pre-set-window-configuration' is really need for that or some
simpler approach would suffice is something I can't tell yet.  Also
considering the case where the same directory is shown in a non-selected
window with saved and current points on different file names and the
saved name's file has been deleted meanwhile.

For dired the value to save in a parameter would at least be that of the
file name point is on - maybe also the number of that line.  It's
completely up to the major mode like 'dired' to store there whatever it
wants.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sat, 13 Jan 2024 18:43:02 GMT) Full text and rfc822 format available.

Message #67 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sat, 13 Jan 2024 20:20:38 +0200
>> So we'd need a persistent window parameter
>>
>> (1) whose value is set to dired's file name at point in
>> 'current-window-configuration'
>>
>> (2) and allows to restore the window's point appropriately in
>> 'set-window-configuration'.
>
> I now think that we need two or three hooks:
>
> - 'pre-current-window-configuration-functions', an abnormal hook that
>   receives one argument - the frame whose configuration shall be
>   recorded.  'dired' has to set a persistent window parameter, for each
>   window on that frame it uses, whose value is whatever is needed to
>   restore the present state of the buffer in that window.

Actually one hook 'pre-current-window-configuration-functions' should be
sufficient.  Like there is only 'isearch-push-state-function' that can
be used to save a lambda that can restore the current window-start, then
on going back this lambda is called and restores the previous window-start.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 14 Jan 2024 08:15:02 GMT) Full text and rfc822 format available.

Message #70 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Sun, 14 Jan 2024 09:13:54 +0100
> Actually one hook 'pre-current-window-configuration-functions' should be
> sufficient.  Like there is only 'isearch-push-state-function' that can
> be used to save a lambda that can restore the current window-start, then
> on going back this lambda is called and restores the previous window-start.

IIUC we have to move some point to some position somewhere in
'set-window-configuration'.  Who would trigger that?  Calling a function
from within 'set-window-configuration' seems hairy to me.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 14 Jan 2024 18:56:02 GMT) Full text and rfc822 format available.

Message #73 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sun, 14 Jan 2024 20:53:12 +0200
>> Actually one hook 'pre-current-window-configuration-functions' should be
>> sufficient.  Like there is only 'isearch-push-state-function' that can
>> be used to save a lambda that can restore the current window-start, then
>> on going back this lambda is called and restores the previous window-start.
>
> IIUC we have to move some point to some position somewhere in
> 'set-window-configuration'.  Who would trigger that?  Calling a function
> from within 'set-window-configuration' seems hairy to me.

I see no other way than calling this hook from 'set-window-configuration'.
The problem is that running the hook afterwards would be too late.
What I mean here is the annoying problem that when a buffer is killed,
then on restoring a window configuration its window is deleted.

This case could be fixed here with the same change as well.
When a window parameter will contain a lambda called from
'set-window-configuration', this lambda could do something useful
to preserve the window whose buffer was killed.  Something like
displaying a placeholder with a button to restore the buffer.

The same window parameter could be used in a window with
a reverted dired buffer to move point to a previous file name.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 15 Jan 2024 10:25:02 GMT) Full text and rfc822 format available.

Message #76 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Mon, 15 Jan 2024 11:24:06 +0100
>> IIUC we have to move some point to some position somewhere in
>> 'set-window-configuration'.  Who would trigger that?  Calling a function
>> from within 'set-window-configuration' seems hairy to me.
>
> I see no other way than calling this hook from 'set-window-configuration'.

Agreed.  But I meant to use one or two hooks 'set-window-configuration'
would call.

> The problem is that running the hook afterwards would be too late.
> What I mean here is the annoying problem that when a buffer is killed,
> then on restoring a window configuration its window is deleted.

If there is only one window left, we have to show another buffer in it.

> This case could be fixed here with the same change as well.
> When a window parameter will contain a lambda called from
> 'set-window-configuration', this lambda could do something useful
> to preserve the window whose buffer was killed.  Something like
> displaying a placeholder with a button to restore the buffer.

We'd have to handle that here

      /* Scan dead buffer windows.  */
      for (; CONSP (dead_buffer_windows);
	   dead_buffer_windows = XCDR (dead_buffer_windows))
	{
	  window = XCAR (dead_buffer_windows);
	  if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
	    delete_deletable_window (window);
	}

which will be a bit hairy to be on the safe side.  This could not be
solved with a 'post-set-window-configuration-hook' because at that time
the window would have been deleted already.

> The same window parameter could be used in a window with
> a reverted dired buffer to move point to a previous file name.

Finding the right place to do that within 'set-window-configuration'
might be non-trivial.  Here using 'post-set-window-configuration-hook'
would be probably better.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 15 Jan 2024 17:58:02 GMT) Full text and rfc822 format available.

Message #79 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Mon, 15 Jan 2024 19:53:13 +0200
>       /* Scan dead buffer windows.  */
>       for (; CONSP (dead_buffer_windows);
> 	   dead_buffer_windows = XCDR (dead_buffer_windows))
> 	{
> 	  window = XCAR (dead_buffer_windows);
> 	  if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
> 	    delete_deletable_window (window);
> 	}
> which will be a bit hairy to be on the safe side.  This could not be
> solved with a 'post-set-window-configuration-hook' because at that time
> the window would have been deleted already.

Maybe then at least would be possible to display a message
that will list the names of dead buffers.  That might help
the users to restore the buffers killed accidentally.

OTOH, this is not needed in case of using the tab-bar
because before switching to the tab with the killed buffer,
the name of the killed buffer is visible as the tab name.

>> The same window parameter could be used in a window with
>> a reverted dired buffer to move point to a previous file name.
>
> Finding the right place to do that within 'set-window-configuration'
> might be non-trivial.  Here using 'post-set-window-configuration-hook'
> would be probably better.

Or maybe instead of 'post-set-window-configuration-hook' it's easy
to call a post-processing function after 'set-window-configuration'.

BTW, there is another problem when the same buffer is displayed
in two tabs/window-configurations. For example, in the first tab
point is near the top of the buffer, and in the second tab point
is near the bottom of the same buffer.  The user edits the top
of the buffer in the first tab and saves writable window states
to the desktop.

At this point, all positions saved in the second tab are wrong
because writable window states save point instead of the marker.

One workaround is before saving the desktop to revisit all tabs
that will update points from markers in writable window states.

But this won't help too much because there is still the same
problem after restoring the desktop.  When the desktop is
restored with right positions of all points, and the user
edits the top of the buffer in the first tab before visiting
the second tab, then after switching to the second tab
point will be at wrong position, because the tab is
restored from window states.

Here the same workaround is possible: to revisit all tabs after
restoring the desktop, that will create window configurations
from window states.

But automatically revisiting all tabs is too harmful
because some tabs might lost their names: when a buffer
was killed, then the tab will be renamed to the name
of the buffer that replaces the killed buffer,
and the user loses the hint what buffer was displayed
in the tab originally.

To solve the problem of outdated points/markers in window states
maybe in addition to point, window states could also store
context strings like bookmark.el does?
I don't know how reliable these bookmark contexts are.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 16 Jan 2024 10:20:02 GMT) Full text and rfc822 format available.

Message #82 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Tue, 16 Jan 2024 11:19:28 +0100
> Maybe then at least would be possible to display a message
> that will list the names of dead buffers.  That might help
> the users to restore the buffers killed accidentally.

The name of a killed buffer is nil as long as the buffer object has not
been collected.  But would buffer names be of great use anyway? Isn't it
the name of the file, the info node, or the directory name the buffer
was visiting that counts?

> OTOH, this is not needed in case of using the tab-bar
> because before switching to the tab with the killed buffer,
> the name of the killed buffer is visible as the tab name.

Does the tab-bar code store the buffer name separately?  But again -
that name won't help you much anyway once the buffer was killed.
Incidentally, the name of the file a killed buffer was visiting will be
available as long as the buffer object exists.  Do you mean that?

> Or maybe instead of 'post-set-window-configuration-hook' it's easy
> to call a post-processing function after 'set-window-configuration'.

'post-set-window-configuration-functions' that's what I meant earlier -
with the frame as argument.  But if a buffer is dead now, this won't
help in neither regard.  First and foremost, 'set-window-configuration'
must be able to deal with dead buffers in a safe fashion.  We could,
optionally, display *scratch* in all windows that have a dead buffer
now.  Still 'post-set-window-configuration-functions' (and also the
desktop routines) would have to know enough about how to restore the
earlier state.  This is something only a buffer's major mode itself may
know.

> BTW, there is another problem when the same buffer is displayed
> in two tabs/window-configurations. For example, in the first tab
> point is near the top of the buffer, and in the second tab point
> is near the bottom of the same buffer.  The user edits the top
> of the buffer in the first tab and saves writable window states
> to the desktop.
>
> At this point, all positions saved in the second tab are wrong
> because writable window states save point instead of the marker.

But 'window--state-get-1' does

		(let ((point (window-point window))

which should reliable give the value of point in window and then

		     (point . ,(if writable
                                   point
                                 (with-current-buffer buffer
                                   (copy-marker point
                                                (buffer-local-value
                                                 'window-point-insertion-type
                                                 buffer)))))

'window--state-put-2' OTOH does

		  (set-window-point window (cdr (assq 'point state))))

Do you see the problem here?

> One workaround is before saving the desktop to revisit all tabs
> that will update points from markers in writable window states.
>
> But this won't help too much because there is still the same
> problem after restoring the desktop.  When the desktop is
> restored with right positions of all points, and the user
> edits the top of the buffer in the first tab before visiting
> the second tab, then after switching to the second tab
> point will be at wrong position, because the tab is
> restored from window states.

So IIUC you mean that restoring the desktop (writable) does things
differently than restoring tabs (non-writable)?  Can you tell me more
precisely the order of desktop/tab-bar operations involved in that
scenario?

> Here the same workaround is possible: to revisit all tabs after
> restoring the desktop, that will create window configurations
> from window states.

I'd still have to understand: A non-writable state should behave like a
window configuration.  A writable state should do the same but for using
numbers instead of markers for positions.

> But automatically revisiting all tabs is too harmful
> because some tabs might lost their names: when a buffer
> was killed, then the tab will be renamed to the name
> of the buffer that replaces the killed buffer,
> and the user loses the hint what buffer was displayed
> in the tab originally.

Again I'm not sure how you would retrieve the name of a killed buffer.
What am I missing?

> To solve the problem of outdated points/markers in window states
> maybe in addition to point, window states could also store
> context strings like bookmark.el does?
> I don't know how reliable these bookmark contexts are.

It would help when the file a buffer is visiting was modified outside
Emacs.  In all other cases, the stored point should suffice.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 16 Jan 2024 16:44:02 GMT) Full text and rfc822 format available.

Message #85 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Tue, 16 Jan 2024 18:30:22 +0200
>> Maybe then at least would be possible to display a message
>> that will list the names of dead buffers.  That might help
>> the users to restore the buffers killed accidentally.
>
> The name of a killed buffer is nil as long as the buffer object has not
> been collected.  But would buffer names be of great use anyway? Isn't it
> the name of the file, the info node, or the directory name the buffer
> was visiting that counts?

The buffer name often has a hint about the file/directory name.

>> OTOH, this is not needed in case of using the tab-bar
>> because before switching to the tab with the killed buffer,
>> the name of the killed buffer is visible as the tab name.
>
> Does the tab-bar code store the buffer name separately?  But again -
> that name won't help you much anyway once the buffer was killed.

By default the buffer name is stored as a tab name.  And it helps
to know the purpose of why that tab was created.  When the buffer
was killed in another tab, it helps to decide whether the tab
that displayed the killed buffer should be closed as well.

> Incidentally, the name of the file a killed buffer was visiting will be
> available as long as the buffer object exists.  Do you mean that?

What would be more useful to keep for the killed buffer
is the value of its revert-buffer-function.  Often calling
this function can reconstruct the buffer contents.

>> Or maybe instead of 'post-set-window-configuration-hook' it's easy
>> to call a post-processing function after 'set-window-configuration'.
>
> 'post-set-window-configuration-functions' that's what I meant earlier -
> with the frame as argument.  But if a buffer is dead now, this won't
> help in neither regard.  First and foremost, 'set-window-configuration'
> must be able to deal with dead buffers in a safe fashion.  We could,
> optionally, display *scratch* in all windows that have a dead buffer now.

Instead of *scratch*, is it possible to display some special buffer
that will display the name of the killed buffer, and a button
that runs its revert-buffer-function?

> Still 'post-set-window-configuration-functions' (and also the
> desktop routines) would have to know enough about how to restore the
> earlier state.  This is something only a buffer's major mode itself may
> know.

Or revert-buffer-function.

>> BTW, there is another problem when the same buffer is displayed
>> in two tabs/window-configurations. For example, in the first tab
>> point is near the top of the buffer, and in the second tab point
>> is near the bottom of the same buffer.  The user edits the top
>> of the buffer in the first tab and saves writable window states
>> to the desktop.
>>
>> At this point, all positions saved in the second tab are wrong
>> because writable window states save point instead of the marker.
>
> But 'window--state-get-1' does
>
> 		(let ((point (window-point window))
>
> which should reliable give the value of point in window and then
>
> 		     (point . ,(if writable
>                                    point
>                                  (with-current-buffer buffer
>                                    (copy-marker point
>                                                 (buffer-local-value
>                                                  'window-point-insertion-type
>                                                  buffer)))))
>
> 'window--state-put-2' OTOH does
>
> 		  (set-window-point window (cdr (assq 'point state))))
>
> Do you see the problem here?

The problem is that for writable window states 'window--state-get-1'
saves point as a number from the marker.

>> One workaround is before saving the desktop to revisit all tabs
>> that will update points from markers in writable window states.
>>
>> But this won't help too much because there is still the same
>> problem after restoring the desktop.  When the desktop is
>> restored with right positions of all points, and the user
>> edits the top of the buffer in the first tab before visiting
>> the second tab, then after switching to the second tab
>> point will be at wrong position, because the tab is
>> restored from window states.
>
> So IIUC you mean that restoring the desktop (writable) does things
> differently than restoring tabs (non-writable)?  Can you tell me more
> precisely the order of desktop/tab-bar operations involved in that
> scenario?

The desktop saves writable window states with point as a number.
Switching tabs uses window configurations with point as a marker.

>> Here the same workaround is possible: to revisit all tabs after
>> restoring the desktop, that will create window configurations
>> from window states.
>
> I'd still have to understand: A non-writable state should behave like a
> window configuration.  A writable state should do the same but for using
> numbers instead of markers for positions.

Indeed.  Only writable window states saved to the desktop.

>> But automatically revisiting all tabs is too harmful
>> because some tabs might lost their names: when a buffer
>> was killed, then the tab will be renamed to the name
>> of the buffer that replaces the killed buffer,
>> and the user loses the hint what buffer was displayed
>> in the tab originally.
>
> Again I'm not sure how you would retrieve the name of a killed buffer.
> What am I missing?

Currently there is no solution to this problem.

>> To solve the problem of outdated points/markers in window states
>> maybe in addition to point, window states could also store
>> context strings like bookmark.el does?
>> I don't know how reliable these bookmark contexts are.
>
> It would help when the file a buffer is visiting was modified outside
> Emacs.  In all other cases, the stored point should suffice.

The stored point is not sufficient when saved as a number to the desktop file.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Wed, 17 Jan 2024 11:43:01 GMT) Full text and rfc822 format available.

Message #88 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Wed, 17 Jan 2024 12:42:44 +0100
> The buffer name often has a hint about the file/directory name.

But not the name of a dead buffer.

> By default the buffer name is stored as a tab name.  And it helps
> to know the purpose of why that tab was created.  When the buffer
> was killed in another tab, it helps to decide whether the tab
> that displayed the killed buffer should be closed as well.

How do you synchronize tabs with 'kill-buffer'?  If, in a tab, you
retain a link to a killed buffer, that buffer can't be collected as long
as the tab exists.  If you just keep the buffer name and the user
creates a new buffer with the same name but for a different file, things
may get confusing.

> What would be more useful to keep for the killed buffer
> is the value of its revert-buffer-function.  Often calling
> this function can reconstruct the buffer contents.

But that function should be available even for a killed buffer as long
as its object is referenced by a tab.

> Instead of *scratch*, is it possible to display some special buffer
> that will display the name of the killed buffer, and a button
> that runs its revert-buffer-function?

We can set up a buffer local variable whose value is a function that
'set-window-configuration' would call whenever it finds a window with
that buffer dead. 'set-window-configuration' would then check whether
that function correctly returned a live buffer to show in that window.
If the function succeeded, 'set-window-configuration' could try to
restore the earlier values of window point and start in the window.  If
the function failed, 'set-window-configuration' would either delete the
window or display *scratch* in it.

>> Still 'post-set-window-configuration-functions' (and also the
>> desktop routines) would have to know enough about how to restore the
>> earlier state.  This is something only a buffer's major mode itself may
>> know.
>
> Or revert-buffer-function.

Which is usually set up by the major mode.

> The stored point is not sufficient when saved as a number to the desktop file.

In what sense?  You have a state you store in a desktop file and restore
from that file.  The stored state is immutable.  If a file whose buffer
is stored in that state gets modified in between, any positions stored
in the state must be considered invalid.

martin





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Wed, 17 Jan 2024 16:46:01 GMT) Full text and rfc822 format available.

Message #91 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Wed, 17 Jan 2024 18:36:05 +0200
>> Instead of *scratch*, is it possible to display some special buffer
>> that will display the name of the killed buffer, and a button
>> that runs its revert-buffer-function?
>
> We can set up a buffer local variable whose value is a function that
> 'set-window-configuration' would call whenever it finds a window with
> that buffer dead. 'set-window-configuration' would then check whether
> that function correctly returned a live buffer to show in that window.
> If the function succeeded, 'set-window-configuration' could try to
> restore the earlier values of window point and start in the window.  If
> the function failed, 'set-window-configuration' would either delete the
> window or display *scratch* in it.

Probably better to keep this function in a window parameter
like you proposed earlier to restore dired positions.

>> The stored point is not sufficient when saved as a number to the desktop file.
>
> In what sense?  You have a state you store in a desktop file and restore
> from that file.  The stored state is immutable.  If a file whose buffer
> is stored in that state gets modified in between, any positions stored
> in the state must be considered invalid.

Indeed.  And bookmark.el solves the problem of invalid positions
by adding more context: `front-context-string' and `rear-context-string'.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Thu, 18 Jan 2024 10:49:02 GMT) Full text and rfc822 format available.

Message #94 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Thu, 18 Jan 2024 11:47:52 +0100
>> We can set up a buffer local variable whose value is a function that
>> 'set-window-configuration' would call whenever it finds a window with
>> that buffer dead. 'set-window-configuration' would then check whether
>> that function correctly returned a live buffer to show in that window.
>> If the function succeeded, 'set-window-configuration' could try to
>> restore the earlier values of window point and start in the window.  If
>> the function failed, 'set-window-configuration' would either delete the
>> window or display *scratch* in it.
>
> Probably better to keep this function in a window parameter
> like you proposed earlier to restore dired positions.

I just tried what I proposed above and noticed that it's virtually
impossible to come up with a safe solution.  Running Lisp from the
middle of 'set-window-configuration' is madness because the respective
frame may be still under construction at that time with windows, their
respective links, sizes and buffers missing.

What we can safely do is the following: Give 'set-window-configuration'
a new argument, say 'keep-dead-buffer-windows'.  If non-nil,
'set-window-configuration' does not delete dead buffer windows but shows
*scratch* in them.  'post-set-window-configuration-functions' would then
pass two arguments: the respective frame and a list of four entries for
each dead buffer window it found: The window, the buffer it previously
showed, its window point and its window start position.  A function run
by that hook would then be able to replace *scratch* with, for example,
a new buffer visiting the file the previously shown buffer visited and
also restore point and window start of that window.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Thu, 18 Jan 2024 16:52:02 GMT) Full text and rfc822 format available.

Message #97 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Thu, 18 Jan 2024 18:50:07 +0200
> What we can safely do is the following: Give 'set-window-configuration'
> a new argument, say 'keep-dead-buffer-windows'.  If non-nil,
> 'set-window-configuration' does not delete dead buffer windows but shows
> *scratch* in them.  'post-set-window-configuration-functions' would then
> pass two arguments: the respective frame and a list of four entries for
> each dead buffer window it found: The window, the buffer it previously
> showed, its window point and its window start position.  A function run
> by that hook would then be able to replace *scratch* with, for example,
> a new buffer visiting the file the previously shown buffer visited and
> also restore point and window start of that window.

This looks promising.  One thing I don't understand is how to get
the previously visited file name from this list of four entries?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sat, 20 Jan 2024 09:46:01 GMT) Full text and rfc822 format available.

Message #100 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Sat, 20 Jan 2024 10:44:51 +0100
[Message part 1 (text/plain, inline)]
> This looks promising.

I attach a patch.  Note that in my Emacs, window configurations are much
more lightweight so I cannot reliably test it.  You would have to do all
the testing yourself.

> One thing I don't understand is how to get
> the previously visited file name from this list of four entries?

But it's still there in the dead buffer (the only things that can get
collected as long as a window is in a tab are the previous and next
buffers shown in that window).  Try the scenario below, using some
suitable file as argument to 'find-file-noselect'.

(defun foo (frame windows)
  (while windows
    (let* ((quad (car windows))
	   (window (car quad))
	   (buffer (find-file-noselect
		    (buffer-file-name (nth 1 quad)))))
      (when buffer
	(set-window-buffer window buffer)
	(set-window-point window (nth 3 quad))
	(set-window-start window (nth 2 quad) t)))
    (setq windows (cdr windows))))

(add-hook 'post-set-window-configuration-functions 'foo)

(let ((window (selected-window))
      (buffer (pop-to-buffer
	       (find-file-noselect "...")))
      (window-1 (split-window))
      (window-2 (split-window nil nil t))
      configuration)
  (set-window-point window-1 5000)
  (set-window-point window-2 10000)
  (setq configuration (current-window-configuration))
  (y-or-n-p "Configuration saved ...")
  (delete-other-windows window)
  (kill-buffer buffer)
  (y-or-n-p "Configuration reset ...")
  (set-window-configuration configuration nil nil t)
  (message "Configuration restored"))

Note that window point and start are stored as positions and not as
markers which means that if you modify the buffer after the call of
'current-window-configuration', they may not be accurate any more.

One could try to get their last position before the buffer was deleted
but that would mean to give ‘marker-position’ an extra argument to omit
the

  if (XMARKER (marker)->buffer)

check with some "use at your own risk" caveats ('marker-buffer' at the
same time would still have to return nil).

martin
[keep-windows.diff (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 22 Jan 2024 07:56:01 GMT) Full text and rfc822 format available.

Message #103 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Mon, 22 Jan 2024 09:43:09 +0200
> I attach a patch.  Note that in my Emacs, window configurations are much
> more lightweight so I cannot reliably test it.  You would have to do all
> the testing yourself.

Thanks, this works great.  Some observations:

1. 'post-set-window-configuration-functions' is called even
after 'delete-other-windows' and 'kill-buffer', albeit with
windows=nil, so no problems.

2. It seems there is no way to get the name of the killed buffer
from '(nth 1 quad)'?

Here is what I tried:

(defun foo (frame windows)
  (while windows
    (let* ((quad (car windows))
	   (window (car quad))
	   (buffer (generate-new-buffer
                    (format " *Old buffer %s*" (nth 1 quad)))))
      (with-current-buffer buffer
        (insert (format "Restore the original buffer named %s:\n"
			(nth 1 quad)))
	(insert-button
	 "[Restore]"
         'action
	 (lambda (_button)
           (set-window-buffer window (find-file-noselect
                                      (buffer-file-name (nth 1 quad))))
	   (set-window-point window (nth 3 quad))
	   (set-window-start window (nth 2 quad) t)))
	(set-window-buffer window buffer)))
    (setq windows (cdr windows))))

It inserts to the transient buffer this text without the real buffer name:

  Restore the original buffer named #<killed buffer>:
  [Restore]

But the button really restores the original buffer.

3. It seems the buffer-local value of 'revert-buffer-function'
   is not preserved in the killed buffer?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 23 Jan 2024 09:32:01 GMT) Full text and rfc822 format available.

Message #106 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Tue, 23 Jan 2024 10:30:49 +0100
> 1. 'post-set-window-configuration-functions' is called even
> after 'delete-other-windows' and 'kill-buffer', albeit with
> windows=nil, so no problems.

I don't understand what you mean here.  Do you mean that it gets called
because for some reason 'set-window-configuration' gets called after
'delete-other-windows' and 'kill-buffer'?

> 2. It seems there is no way to get the name of the killed buffer
> from '(nth 1 quad)'?

No way.  'buffer-name' with a killed buffer as argument has to return
nil - too many functions may rely on that.

> Here is what I tried:
>
> (defun foo (frame windows)
>    (while windows
>      (let* ((quad (car windows))
> 	   (window (car quad))
> 	   (buffer (generate-new-buffer
>                      (format " *Old buffer %s*" (nth 1 quad)))))
>        (with-current-buffer buffer
>          (insert (format "Restore the original buffer named %s:\n"
> 			(nth 1 quad)))
> 	(insert-button
> 	 "[Restore]"
>           'action
> 	 (lambda (_button)
>             (set-window-buffer window (find-file-noselect
>                                        (buffer-file-name (nth 1 quad))))
> 	   (set-window-point window (nth 3 quad))
> 	   (set-window-start window (nth 2 quad) t)))
> 	(set-window-buffer window buffer)))
>      (setq windows (cdr windows))))
>
> It inserts to the transient buffer this text without the real buffer name:
>
>    Restore the original buffer named #<killed buffer>:
>    [Restore]

I'd say Restore buffer from ... and use the file name here.

> But the button really restores the original buffer.

Because many functions with a buffer as argument like 'buffer-file-name'
don't check whether that buffer is live.  You can find such functions by
looking for "decode_buffer (buffer)" in buffer.c.  'buffer-name' fails
because the name of the buffer _is_ reset to nil when the buffer is
killed.  We could add a new field to the buffer structure and a function
say 'buffer-last-name' which would return the last name a buffer had
before it was renamed: nil for a new buffer, the old name before the
last 'rename-buffer' and the last buffer name for a dead buffer.

And always think about what to propose when a new buffer with the same
name has been created meanwhile.

> 3. It seems the buffer-local value of 'revert-buffer-function'
>     is not preserved in the killed buffer?

'kill-buffer' calls reset_buffer_local_variables which scans the local
variables alist of the buffer and resets all values to their default
values.  Giving the variable either a 'permanent-local' property or
binding the default value to the buffer local value around 'kill-buffer'
could work around that but I'd rather try to save this (and other buffer
local values) in a separate alist for buffers stored in a configuration.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Wed, 24 Jan 2024 08:02:02 GMT) Full text and rfc822 format available.

Message #109 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Wed, 24 Jan 2024 09:54:16 +0200
>> 1. 'post-set-window-configuration-functions' is called even
>> after 'delete-other-windows' and 'kill-buffer', albeit with
>> windows=nil, so no problems.
>
> I don't understand what you mean here.  Do you mean that it gets called
> because for some reason 'set-window-configuration' gets called after
> 'delete-other-windows' and 'kill-buffer'?

When I instrumented the function 'foo', it entered edebug
between 'y-or-n-p' in

  (y-or-n-p "Configuration saved ...")
  (delete-other-windows window)
  (kill-buffer buffer)
  (y-or-n-p "Configuration reset ...")

So I supposed that maybe from 'delete-other-windows' and 'kill-buffer',
but now I understand this is because exiting the minibuffer from
'y-or-n-p' calls 'set-window-configuration'.

> We could add a new field to the buffer structure and a function
> say 'buffer-last-name' which would return the last name a buffer had
> before it was renamed: nil for a new buffer, the old name before the
> last 'rename-buffer' and the last buffer name for a dead buffer.

Looks nice.

> And always think about what to propose when a new buffer with the same
> name has been created meanwhile.

Something using uniquify could help.

>> 3. It seems the buffer-local value of 'revert-buffer-function'
>>     is not preserved in the killed buffer?
>
> 'kill-buffer' calls reset_buffer_local_variables which scans the local
> variables alist of the buffer and resets all values to their default
> values.  Giving the variable either a 'permanent-local' property or
> binding the default value to the buffer local value around 'kill-buffer'
> could work around that but I'd rather try to save this (and other buffer
> local values) in a separate alist for buffers stored in a configuration.

To save revert-buffer-functions like saving positions of dired files
in window parameters?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Thu, 25 Jan 2024 09:41:02 GMT) Full text and rfc822 format available.

Message #112 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Thu, 25 Jan 2024 10:39:51 +0100
[Message part 1 (text/plain, inline)]
> When I instrumented the function 'foo', it entered edebug
> between 'y-or-n-p' in
>
>    (y-or-n-p "Configuration saved ...")
>    (delete-other-windows window)
>    (kill-buffer buffer)
>    (y-or-n-p "Configuration reset ...")
>
> So I supposed that maybe from 'delete-other-windows' and 'kill-buffer',
> but now I understand this is because exiting the minibuffer from
> 'y-or-n-p' calls 'set-window-configuration'.

Unless 'read-minibuffer-restore-windows' is nil.  Saving and restoring
the configuration with 'y-or-n-p' makes no sense because in practice the
user cannot change the configuration while 'y-or-n-p' is in progress.

>> We could add a new field to the buffer structure and a function
>> say 'buffer-last-name' which would return the last name a buffer had
>> before it was renamed: nil for a new buffer, the old name before the
>> last 'rename-buffer' and the last buffer name for a dead buffer.
>
> Looks nice.

I attach a patch.

>> And always think about what to propose when a new buffer with the same
>> name has been created meanwhile.
>
> Something using uniquify could help.

Maybe.  Here I had problems with uniquify not always restoring the base
name of a buffer when I killed the last other buffer with the same base
name.  Maybe the fault is all mine.

>> 'kill-buffer' calls reset_buffer_local_variables which scans the local
>> variables alist of the buffer and resets all values to their default
>> values.  Giving the variable either a 'permanent-local' property or
>> binding the default value to the buffer local value around 'kill-buffer'
>> could work around that but I'd rather try to save this (and other buffer
>> local values) in a separate alist for buffers stored in a configuration.
>
> To save revert-buffer-functions like saving positions of dired files
> in window parameters?

For example, yes.

martin
[buffer-last-name.diff (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Thu, 25 Jan 2024 17:57:01 GMT) Full text and rfc822 format available.

Message #115 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Thu, 25 Jan 2024 19:46:28 +0200
>>> We could add a new field to the buffer structure and a function
>>> say 'buffer-last-name' which would return the last name a buffer had
>>> before it was renamed: nil for a new buffer, the old name before the
>>> last 'rename-buffer' and the last buffer name for a dead buffer.
>>
>> Looks nice.
>
> I attach a patch.

Thanks, will try to use.

>>> 'kill-buffer' calls reset_buffer_local_variables which scans the local
>>> variables alist of the buffer and resets all values to their default
>>> values.  Giving the variable either a 'permanent-local' property or
>>> binding the default value to the buffer local value around 'kill-buffer'
>>> could work around that but I'd rather try to save this (and other buffer
>>> local values) in a separate alist for buffers stored in a configuration.
>>
>> To save revert-buffer-functions like saving positions of dired files
>> in window parameters?
>
> For example, yes.

OTOH, since there is a need to save more variables together with the
window configuration such as dired-filename and revert-buffer-function
anyway, maybe it would be possible to save the last buffer name in the
same alist?  Or the last buffer name should be used as a key in such
an alist?  Probably no.  It seems a key should be a window unless
such data is saved in a window parameter.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Fri, 26 Jan 2024 09:57:02 GMT) Full text and rfc822 format available.

Message #118 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Fri, 26 Jan 2024 10:56:32 +0100
> OTOH, since there is a need to save more variables together with the
> window configuration such as dired-filename and revert-buffer-function
> anyway, maybe it would be possible to save the last buffer name in the
> same alist?  Or the last buffer name should be used as a key in such
> an alist?  Probably no.  It seems a key should be a window unless
> such data is saved in a window parameter.

Note that the name of a buffer may change in the period lasting from
when you saved the window configuration until the buffer gets killed.
Any such change is handled by 'kill-buffer' but cannot be easily traced
when you save the name together with a window configuration.  You could
try 'buffer-list-update-hook' but that might be overkill.  And if you
saved that name in a permanent window parameter, you are lost anyway
because you cannot access the parameter in the saved configuration.

A similar thing may happen to dired-filename and revert-buffer-function
but there are hardly any suitable means to reasonably trace changes to
what these stand for in the first place.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sat, 27 Jan 2024 18:07:02 GMT) Full text and rfc822 format available.

Message #121 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sat, 27 Jan 2024 19:58:51 +0200
>> OTOH, since there is a need to save more variables together with the
>> window configuration such as dired-filename and revert-buffer-function
>> anyway, maybe it would be possible to save the last buffer name in the
>> same alist?  Or the last buffer name should be used as a key in such
>> an alist?  Probably no.  It seems a key should be a window unless
>> such data is saved in a window parameter.
>
> Note that the name of a buffer may change in the period lasting from
> when you saved the window configuration until the buffer gets killed.
> Any such change is handled by 'kill-buffer' but cannot be easily traced
> when you save the name together with a window configuration.  You could
> try 'buffer-list-update-hook' but that might be overkill.  And if you
> saved that name in a permanent window parameter, you are lost anyway
> because you cannot access the parameter in the saved configuration.

Depends on the needs.  With your patch that adds 'keep_windows'
it doesn't matter what an old buffer name to show in the window
with the killed buffer.  It even makes more sense to show the
same buffer name that was displayed in that window configuration
before the buffer was renamed later.

> A similar thing may happen to dired-filename and revert-buffer-function
> but there are hardly any suitable means to reasonably trace changes to
> what these stand for in the first place.

Indeed, currently 'dired-revert' can't reasonably handle the
situation with the deleted files even in another window.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 28 Jan 2024 10:07:02 GMT) Full text and rfc822 format available.

Message #124 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: daniel.c.mccarthy <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>,
 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Sun, 28 Jan 2024 11:06:37 +0100
> Depends on the needs.  With your patch that adds 'keep_windows'
> it doesn't matter what an old buffer name to show in the window
> with the killed buffer.  It even makes more sense to show the
> same buffer name that was displayed in that window configuration
> before the buffer was renamed later.

But you must have stowed away that name somewhere because 'kill-buffer'
will have reset it to nil without mercy.

> Indeed, currently 'dired-revert' can't reasonably handle the
> situation with the deleted files even in another window.

Can you give a scenario?

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 04 Feb 2024 17:30:02 GMT) Full text and rfc822 format available.

Message #127 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sun, 04 Feb 2024 19:27:40 +0200
[Message part 1 (text/plain, inline)]
>> Do you remember the bug this was supposed to fix?
>
> The dedicated bug report is this:
>
> bug#33871: Revert Dired window saved in window configuration

I finished designing the feature that will restore Dired positions
in window-configurations and window-states used on the tab-bar.

It will be easy also to add a default more general function
that would use bookmark-like rear/front context in any buffer.

[window-context.patch (text/x-diff, inline)]
diff --git a/lisp/dired.el b/lisp/dired.el
index cef93ab757c..3a80cfffc04 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -2743,6 +2745,8 @@ dired-mode
               '(dired-font-lock-keywords t nil nil beginning-of-line))
   (setq-local desktop-save-buffer 'dired-desktop-buffer-misc-data)
   (setq-local grep-read-files-function #'dired-grep-read-files)
+  (setq-local window-set-context-function (lambda () (dired-get-filename nil t)))
+  (setq-local window-use-context-function (lambda (context) (dired-goto-file context)))
   (setq dired-switches-alist nil)
   (hack-dir-local-variables-non-file-buffer) ; before sorting
   (dired-sort-other dired-actual-switches t)
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 3e1d8278b04..6c6f3ece9c2 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -1283,6 +1283,10 @@ frameset-filter-tabs
 
 (push '(tabs . frameset-filter-tabs) frameset-filter-alist)
 
+(defvar window-set-context-function nil)
+(defvar window-use-context-function nil)
+(add-to-list 'window-persistent-parameters '(context . writable))
+
 (defun tab-bar--tab (&optional frame)
   "Make a new tab data structure that can be added to tabs on the FRAME."
   (let* ((tab (tab-bar--current-tab-find nil frame))
@@ -1292,6 +1296,14 @@ tab-bar--tab
                                            frame 'buffer-list)))
          (bbl (seq-filter #'buffer-live-p (frame-parameter
                                            frame 'buried-buffer-list))))
+    (walk-windows
+     (lambda (w)
+       (with-selected-window w
+         (when (functionp window-set-context-function)
+           (when-let ((context (funcall window-set-context-function)))
+             (set-window-parameter w 'context (cons (buffer-name) context))))))
+     'nomini)
+
     `(tab
       (name . ,(if tab-explicit-name
                    (alist-get 'name tab)
@@ -1479,6 +1491,15 @@ tab-bar-select-tab
             (select-window (get-mru-window)))
           (window-state-put ws nil 'safe)))
 
+        (walk-windows
+         (lambda (w)
+           (with-selected-window w
+             (when-let ((context (window-parameter w 'context)))
+               (when (and (functionp window-use-context-function)
+                          (equal (buffer-name) (car context)))
+                 (funcall window-use-context-function (cdr context))))))
+         'nomini)
+
         ;; Select the minibuffer when it was active before switching tabs
         (when (and minibuffer-was-active (active-minibuffer-window))
           (select-window (active-minibuffer-window)))

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 05 Feb 2024 07:29:01 GMT) Full text and rfc822 format available.

Message #130 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Mon, 05 Feb 2024 09:17:24 +0200
> I attach a patch.  Note that in my Emacs, window configurations are much
> more lightweight so I cannot reliably test it.  You would have to do all
> the testing yourself.
> [...]
>  DEFUN ("set-window-configuration", Fset_window_configuration,
> -       Sset_window_configuration, 1, 3, 0,
> +       Sset_window_configuration, 1, 4, 0,
> [...]
> -   Lisp_Object dont_set_miniwindow)
> +   Lisp_Object dont_set_miniwindow, Lisp_Object keep_windows)

Is 'keep-windows' doable for 'window-state-put' as well?

It seems windows are deleted here:

      (while window-state-put-stale-windows
	(let ((window (pop window-state-put-stale-windows)))
          ;; Avoid that 'window-deletable-p' throws an error if window
          ;; was already deleted when exiting 'with-temp-buffer' above
          ;; (Bug#54028).
	  (when (and (window-valid-p window)
                     (eq (window-deletable-p window) t))
	    (delete-window window))))

After commenting out the code above, this test doesn't delete windows:

  (let (ws)
    (pop-to-buffer "*Messages*")
    (setq ws (window-state-get nil 'writable))
    (kill-buffer "*Messages*")
    (window-state-put ws nil 'safe))

So maybe the same option 'keep-windows' could call the same hook
'post-set-window-configuration-functions' from 'window-state-put' too?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 06 Feb 2024 10:36:01 GMT) Full text and rfc822 format available.

Message #133 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Tue, 6 Feb 2024 11:34:54 +0100
[Message part 1 (text/plain, inline)]
> Is 'keep-windows' doable for 'window-state-put' as well?

I attach a patch that adds a fourth argument to 'window-state-put'.  It
and a new 'set-window-configuration' now use a new function I called
'marker-last-position' that returns the last position of a marker even
after its buffer was killed.

The patch also fixes a bug in 'window--state-put-2' that can be
reproduced with the following simple scenario

(let ((buffer (get-buffer-create "*foo*"))
      state)
  (pop-to-buffer buffer)
  (setq state (window-state-get))
  (kill-buffer buffer)
  (window-state-put state))

Did you never see it?

> So maybe the same option 'keep-windows' could call the same hook
> 'post-set-window-configuration-functions' from 'window-state-put' too?

I added a new hook called 'window-state-put-keep-window-functions' with
the same arguments as 'post-set-window-configuration-functions'.  Maybe
people wanted to keep them apart.  If you think the hook should be also
run when there are no "kept" windows, we can do that as well.

I tested it here with

(defun foo (frame windows)
  (while windows
    (let* ((quad (car windows))
	   (window (car quad))
	   (buffer (find-file-noselect
		    (buffer-file-name (nth 1 quad)))))
      (when buffer
	(set-window-buffer window buffer)
	(set-window-point window (nth 3 quad))
	(set-window-start window (nth 2 quad) t)))
    (setq windows (cdr windows))))

(add-hook 'window-state-put-keep-window-functions 'foo)

(let ((window (selected-window))
      (buffer (pop-to-buffer
	       (find-file-noselect "...")))
      (window-1 (split-window))
      (window-2 (split-window nil nil t))
      state)
  (set-window-point window-1 5000)
  (set-window-point window-2 10000)
  (setq state (window-state-get))
  (y-or-n-p "State saved ...")
  (delete-other-windows window)
  (kill-buffer buffer)
  (y-or-n-p "State reset ...")
  (window-state-put state nil nil t)
  (message "State restored"))

martin
[keep-windows-2.diff (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 06 Feb 2024 18:16:02 GMT) Full text and rfc822 format available.

Message #136 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Tue, 06 Feb 2024 20:03:35 +0200
>> Is 'keep-windows' doable for 'window-state-put' as well?
>
> I attach a patch that adds a fourth argument to 'window-state-put'.  It
> and a new 'set-window-configuration' now use a new function I called
> 'marker-last-position' that returns the last position of a marker even
> after its buffer was killed.

Thanks, will test it.

> The patch also fixes a bug in 'window--state-put-2' that can be
> reproduced with the following simple scenario
>
> (let ((buffer (get-buffer-create "*foo*"))
>       state)
>   (pop-to-buffer buffer)
>   (setq state (window-state-get))
>   (kill-buffer buffer)
>   (window-state-put state))
>
> Did you never see it?

I have seen it when created the first version of the test case:

  (let (ws)
    (pop-to-buffer "*Messages*")
    (setq ws (window-state-get))
    (kill-buffer "*Messages*")
    (window-state-put ws))

But then added both 'writable' to 'window-state-get'
and at the same time 'safe' to 'window-state-put':

  (let (ws)
    (pop-to-buffer "*Messages*")
    (setq ws (window-state-get nil 'writable))
    (kill-buffer "*Messages*")
    (window-state-put ws nil 'safe))

And it didn't fail anymore, so I assumed that
'safe' fixed it ;-)

But now I see that actually 'writable' "fixed" it.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Thu, 15 Feb 2024 07:44:02 GMT) Full text and rfc822 format available.

Message #139 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Thu, 15 Feb 2024 09:34:33 +0200
>> Is 'keep-windows' doable for 'window-state-put' as well?
>
> I attach a patch that adds a fourth argument to 'window-state-put'.  It
> and a new 'set-window-configuration' now use a new function I called
> 'marker-last-position' that returns the last position of a marker even
> after its buffer was killed.

Thanks, I tested, and both hooks work nicely.

One problem is that whether to run the hook is defined by the fourth argument.
This means that it a user needs to use the hook, there is no way to change
the fourth argument of the existing function calls in core commands.

Maybe better to keep windows when the hook is not empty?
I.e. something like this for 'window--state-put-2':

  (when window-state-put-keep-window-functions
    ...
    (push (list window old-buffer-or-name start-pos point-pos)
          window-state-put-kept-windows))

> I added a new hook called 'window-state-put-keep-window-functions' with
> the same arguments as 'post-set-window-configuration-functions'.  Maybe
> people wanted to keep them apart.  If you think the hook should be also
> run when there are no "kept" windows, we can do that as well.

Running the hook with an empty list of windows makes sense as well.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Fri, 16 Feb 2024 09:41:02 GMT) Full text and rfc822 format available.

Message #142 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Fri, 16 Feb 2024 10:40:02 +0100
> One problem is that whether to run the hook is defined by the fourth argument.
> This means that it a user needs to use the hook, there is no way to change
> the fourth argument of the existing function calls in core commands.
>
> Maybe better to keep windows when the hook is not empty?
> I.e. something like this for 'window--state-put-2':
>
>    (when window-state-put-keep-window-functions
>      ...
>      (push (list window old-buffer-or-name start-pos point-pos)
>            window-state-put-kept-windows))

You mean to do away with the KEEP-WINDOWS argument and keep windows iff
`window-state-put-keep-window-functions' is non-nil?  This would be up
to you to decide.  Only some practice can tell what's better here.

>> I added a new hook called 'window-state-put-keep-window-functions' with
>> the same arguments as 'post-set-window-configuration-functions'.  Maybe
>> people wanted to keep them apart.  If you think the hook should be also
>> run when there are no "kept" windows, we can do that as well.
>
> Running the hook with an empty list of windows makes sense as well.

For some time we don't run hooks any more when windows and their buffers
change but rather wait until redisplay detects that some change occurred.
`window-state-put-keep-window-functions' already opens the backdoor to
the previous behavior so I'm not sure about opening it even further.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 18 Feb 2024 07:48:01 GMT) Full text and rfc822 format available.

Message #145 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sun, 18 Feb 2024 09:35:58 +0200
>> One problem is that whether to run the hook is defined by the fourth argument.
>> This means that it a user needs to use the hook, there is no way to change
>> the fourth argument of the existing function calls in core commands.
>>
>> Maybe better to keep windows when the hook is not empty?
>> I.e. something like this for 'window--state-put-2':
>>
>>    (when window-state-put-keep-window-functions
>>      ...
>>      (push (list window old-buffer-or-name start-pos point-pos)
>>            window-state-put-kept-windows))
>
> You mean to do away with the KEEP-WINDOWS argument and keep windows iff
> `window-state-put-keep-window-functions' is non-nil?

Yes, I meant removing the KEEP-WINDOWS argument.

> This would be up to you to decide.  Only some practice can tell what's
> better here.

Otherwise users won't be able to use this hook for existing commands
that don't set the KEEP-WINDOWS argument.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 19 Feb 2024 09:43:02 GMT) Full text and rfc822 format available.

Message #148 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Mon, 19 Feb 2024 10:42:09 +0100
[Message part 1 (text/plain, inline)]
>> You mean to do away with the KEEP-WINDOWS argument and keep windows iff
>> `window-state-put-keep-window-functions' is non-nil?
>
> Yes, I meant removing the KEEP-WINDOWS argument.

Patch attached.  I now provide only one hook I called
'window-kept-windows-functions' which is run by both
'set-window-configuration' and 'window-state-put'.
Tested with

(defun foo (frame windows)
  (while windows
    (let* ((quad (car windows))
	   (window (car quad))
	   (name (buffer-file-name (nth 1 quad)))
	   (buffer
	    (and name (find-file-noselect name))))
      (when buffer
	(set-window-buffer window buffer)
	(set-window-point window (nth 3 quad))
	(set-window-start window (nth 2 quad) t)))
    (setq windows (cdr windows))))

(add-hook 'window-kept-windows-functions 'foo)

(let ((window (selected-window))
      (buffer (pop-to-buffer
	       (find-file-noselect "...")))
      (window-1 (split-window))
      (window-2 (split-window nil nil t))
      configuration)
  (set-window-point window-1 5000)
  (set-window-point window-2 10000)
  (setq configuration (current-window-configuration))
  (y-or-n-p "Configuration saved ...")
  (delete-other-windows window)
  (kill-buffer buffer)
  (y-or-n-p "Configuration reset ...")
  (set-window-configuration configuration)
  (message "Configuration restored"))

(let ((window (selected-window))
      (buffer (pop-to-buffer
	       (find-file-noselect "...")))
      (window-1 (split-window))
      (window-2 (split-window nil nil t))
      state)
  (set-window-point window-1 5000)
  (set-window-point window-2 10000)
  (setq state (window-state-get))
  (y-or-n-p "State saved ...")
  (delete-other-windows window)
  (kill-buffer buffer)
  (y-or-n-p "State reset ...")
  (window-state-put state)
  (message "State restored"))

>> This would be up to you to decide.  Only some practice can tell what's
>> better here.
>
> Otherwise users won't be able to use this hook for existing commands
> that don't set the KEEP-WINDOWS argument.

OK.  But note that we now run this hook even if nothing in the window
configuration changes, typically, when calling 'read-minibuffer'.  So
use it with due care (for example, have the tab code bind it exclusively
around its calls of 'set-window-configuration').

martin
[keep-windows.diff (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 20 Feb 2024 17:46:01 GMT) Full text and rfc822 format available.

Message #151 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Tue, 20 Feb 2024 19:44:27 +0200
> Patch attached.  I now provide only one hook I called
> 'window-kept-windows-functions' which is run by both
> 'set-window-configuration' and 'window-state-put'.

Thanks, it works nicely with

(defun default-window-keep-windows (_frame windows)
  (dolist (quad windows)
    (unless (window-minibuffer-p (nth 0 quad))
      (let* ((window (nth 0 quad))
             (old-buffer (nth 1 quad))
             (file (when (bufferp old-buffer)
                     (buffer-file-name old-buffer)))
             (name (or file old-buffer))
             (new-buffer (generate-new-buffer
                          (format "*Old buffer %s*" name))))
        (with-current-buffer new-buffer
          (set-auto-mode)
          (insert "This window displayed the "
                  (if file "file" "buffer")
                  (format " %s\n" name))
          (when file
            (insert-button
             "[Restore]" 'action
	     (lambda (_button)
               (set-window-buffer window (find-file-noselect file))
	       (set-window-point window (nth 3 quad))
	       (set-window-start window (nth 2 quad) t))))
          (goto-char (point-min))
          (setq buffer-read-only t)
	  (set-window-buffer window new-buffer))))))

(add-hook 'window-kept-windows-functions 'default-window-keep-windows)

that works even for (window-state-get nil 'writable).
In this case only the old buffer name is displayed as a string.
I guess there is no more data that could be extracted
from buffer's writable state.

> OK.  But note that we now run this hook even if nothing in the window
> configuration changes, typically, when calling 'read-minibuffer'.  So
> use it with due care

Indeed, this required adding such guard:

  (unless (window-minibuffer-p (nth 0 quad))

> (for example, have the tab code bind it exclusively
> around its calls of 'set-window-configuration').

Thanks for suggestion, will let-bind it in 'tab-bar-select-tab'.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 04 Mar 2024 09:42:02 GMT) Full text and rfc822 format available.

Message #154 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Mon, 4 Mar 2024 10:40:34 +0100
> Patch attached.  I now provide only one hook I called
> 'window-kept-windows-functions' which is run by both
> 'set-window-configuration' and 'window-state-put'.

Should be on master now.

Thanks for testing, martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 05 Mar 2024 17:33:01 GMT) Full text and rfc822 format available.

Message #157 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Tue, 05 Mar 2024 19:27:18 +0200
[Message part 1 (text/plain, inline)]
>> Patch attached.  I now provide only one hook I called
>> 'window-kept-windows-functions' which is run by both
>> 'set-window-configuration' and 'window-state-put'.
>
> Should be on master now.

Thanks.  This will allow such option:

[tab-bar-select-keep-windows-function.patch (text/x-diff, inline)]
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 61efa332e0b..b2eb1c9d576 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -1393,6 +1405,44 @@ tab-bar-tab-post-select-functions
   :group 'tab-bar
   :version "30.1")
 
+(defcustom tab-bar-select-keep-windows-function #'tab-bar-select-keep-windows
+  "Function that handles the killed buffers after selecting a tab."
+  :type '(choice (const :tag "Show placeholder buffers"
+                        tab-bar-select-keep-windows)
+                 (function  :tag "Function"))
+  :group 'tab-bar
+  :version "30.1")
+
+(defun tab-bar-select-keep-windows (_frame windows)
+  (dolist (quad windows)
+    (when (and (window-live-p (nth 0 quad))
+               (not (window-minibuffer-p (nth 0 quad))))
+      (let* ((window (nth 0 quad))
+             (old-buffer (nth 1 quad))
+             (file (when (bufferp old-buffer)
+                     (buffer-file-name old-buffer)))
+             (name (or file
+                       (and (fboundp 'buffer-last-name)
+                            (buffer-last-name old-buffer))
+                       old-buffer))
+             (new-buffer (generate-new-buffer
+                          (format "*Old buffer %s*" name))))
+        (with-current-buffer new-buffer
+          (set-auto-mode)
+          (insert (format-message "This window displayed the %s `%s'.\n"
+                                  (if file "file" "buffer")
+                                  name))
+          (when file
+            (insert-button
+             "[Restore]" 'action
+	     (lambda (_button)
+               (set-window-buffer window (find-file-noselect file))
+	       (set-window-start window (nth 2 quad) t)
+	       (set-window-point window (nth 3 quad)))))
+          (goto-char (point-min))
+          (setq buffer-read-only t)
+	  (set-window-buffer window new-buffer))))))
+
 (defvar tab-bar-minibuffer-restore-tab nil
   "Tab number for `tab-bar-minibuffer-restore-tab'.")
 
@@ -1438,7 +1488,10 @@ tab-bar-select-tab
       (let* ((from-tab (tab-bar--tab))
              (to-tab (nth to-index tabs))
              (wc (alist-get 'wc to-tab))
-             (ws (alist-get 'ws to-tab)))
+             (ws (alist-get 'ws to-tab))
+             (window-kept-windows-functions
+              (delq nil (cons tab-bar-select-keep-windows-function
+                              window-kept-windows-functions))))
 
         ;; During the same session, use window-configuration to switch
         ;; tabs, because window-configurations are more reliable

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 05 Mar 2024 17:42:02 GMT) Full text and rfc822 format available.

Message #160 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Tue, 05 Mar 2024 19:37:47 +0200
>> Patch attached.  I now provide only one hook I called
>> 'window-kept-windows-functions' which is run by both
>> 'set-window-configuration' and 'window-state-put'.
>
> Should be on master now.

In addition to the previous patch I also have more questions:

1. window-kept-windows-functions should be announced in etc/NEWS?

2. window-kept-windows-functions is called too often.
Most of the calls contain just the minibuffer:

   ((#<window 4 on  *Minibuf-0*> #<buffer  *Minibuf-0*> 1 1))

Is it possible not to include the minibuffer window?
So when most of the time this list of kept windows will be empty,
then maybe better to not call the hook at all?

3. Very often the message inserted by the patch that I posted
are quite useless because they look like this:

   This window displayed the buffer #<killed buffer>.

This would be much more informative:

   This window displayed the buffer *Help*.

Maybe 'buffer-last-name' could help to achieve this?

4. I don't understand this part, but maybe this is already correct:

      /* Scan dead buffer windows.  */
      if (!NILP (Vwindow_kept_windows_functions))
	for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
	  {
	    window = XCAR (dead_windows);
	    if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
	      delete_deletable_window (window);
	  }

Should it be if(NILP (Vwindow_kept_windows_functions)) instead?
However, this already works correctly in my tests.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 05 Mar 2024 17:47:02 GMT) Full text and rfc822 format available.

Message #163 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Juri Linkov <juri <at> linkov.net>
Cc: rudalics <at> gmx.at, 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90;
 Switching tabs stops following process output in selected window
Date: Tue, 05 Mar 2024 19:45:17 +0200
> Cc: 68235 <at> debbugs.gnu.org
> From: Juri Linkov <juri <at> linkov.net>
> Date: Tue, 05 Mar 2024 19:27:18 +0200
> 
> +(defcustom tab-bar-select-keep-windows-function #'tab-bar-select-keep-windows
> +  "Function that handles the killed buffers after selecting a tab."

This doc string doesn't explain enough: it begs the question "what
does selecting a tab have to do with killing buffers?"

Thanks.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Wed, 06 Mar 2024 10:21:02 GMT) Full text and rfc822 format available.

Message #166 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Wed, 6 Mar 2024 11:19:51 +0100
[Message part 1 (text/plain, inline)]
> In addition to the previous patch I also have more questions:
>
> 1. window-kept-windows-functions should be announced in etc/NEWS?

Maybe, once we fixed all bugs and know how to make good use of it.

> 2. window-kept-windows-functions is called too often.
> Most of the calls contain just the minibuffer:
>
>     ((#<window 4 on  *Minibuf-0*> #<buffer  *Minibuf-0*> 1 1))
>
> Is it possible not to include the minibuffer window?

Yes.  Emacs master never deletes a minibuffer window unless it's about
to delete its frame.

> So when most of the time this list of kept windows will be empty,
> then maybe better to not call the hook at all?

But earlier you said "Running the hook with an empty list of windows
makes sense as well."  So it's up to you.

> 3. Very often the message inserted by the patch that I posted
> are quite useless because they look like this:
>
>     This window displayed the buffer #<killed buffer>.
>
> This would be much more informative:
>
>     This window displayed the buffer *Help*.
>
> Maybe 'buffer-last-name' could help to achieve this?

I tried to implement it.  Tested with

(let ((buffer (get-buffer-create "*foo*")))
  (y-or-n-p (format "current %s last %s"
		    (buffer-name buffer) (buffer-last-name buffer)))
  (with-current-buffer buffer
    (rename-buffer "*bar*"))
  (y-or-n-p (format "current %s last %s"
		    (buffer-name buffer) (buffer-last-name buffer)))
  (kill-buffer buffer)
  (y-or-n-p (format "current %s last %s"
		    (buffer-name buffer) (buffer-last-name buffer))))

> 4. I don't understand this part, but maybe this is already correct:
>
>        /* Scan dead buffer windows.  */
>        if (!NILP (Vwindow_kept_windows_functions))
> 	for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
> 	  {
> 	    window = XCAR (dead_windows);
> 	    if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
> 	      delete_deletable_window (window);
> 	  }
>
> Should it be if(NILP (Vwindow_kept_windows_functions)) instead?

It should.  Thanks for catching it.

> However, this already works correctly in my tests.

Because 'set-window-configuration' does not try to delete a window with
a dead buffer unless that window was dedicated to its buffer.  That's
the way it was coded back in 2011.  'window-state-put' OTOH deletes
such a window even if it was not dedicated to its buffer.  I now made
'window-state-put' behave like 'set-window-configuration' in this
regard.

Have a look at the attached patch.

martin
[buffer-last-name.diff (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Wed, 06 Mar 2024 18:11:01 GMT) Full text and rfc822 format available.

Message #169 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Wed, 06 Mar 2024 19:57:53 +0200
>> So when most of the time this list of kept windows will be empty,
>> then maybe better to not call the hook at all?
>
> But earlier you said "Running the hook with an empty list of windows
> makes sense as well."  So it's up to you.

We could leave it called on every set-window-configuration
even with an empty window list, as a general post-hook.

BTW, I didn't test yet what happens when
window-kept-windows-functions is non-nil but does nothing.
Here is what happens:

  Error muted by safe_call: (get-scratch-buffer-create)
  signaled (wrong-type-argument window-live-p #<window 7>)

But maybe this is ok.

>> 3. Very often the message inserted by the patch that I posted
>> are quite useless because they look like this:
>>
>>     This window displayed the buffer #<killed buffer>.
>>
>> This would be much more informative:
>>
>>     This window displayed the buffer *Help*.
>>
>> Maybe 'buffer-last-name' could help to achieve this?
>
> I tried to implement it.  Tested with
>
> (let ((buffer (get-buffer-create "*foo*")))
>   (y-or-n-p (format "current %s last %s"
> 		    (buffer-name buffer) (buffer-last-name buffer)))
>   (with-current-buffer buffer
>     (rename-buffer "*bar*"))
>   (y-or-n-p (format "current %s last %s"
> 		    (buffer-name buffer) (buffer-last-name buffer)))
>   (kill-buffer buffer)
>   (y-or-n-p (format "current %s last %s"
> 		    (buffer-name buffer) (buffer-last-name buffer))))
> [...]
> Have a look at the attached patch.

Thanks.  I tested, and everything works nicely.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Wed, 06 Mar 2024 18:11:02 GMT) Full text and rfc822 format available.

Message #172 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: rudalics <at> gmx.at, 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Wed, 06 Mar 2024 20:03:50 +0200
[Message part 1 (text/plain, inline)]
>> +(defcustom tab-bar-select-keep-windows-function #'tab-bar-select-keep-windows
>> +  "Function that handles the killed buffers after selecting a tab."
>
> This doc string doesn't explain enough: it begs the question "what
> does selecting a tab have to do with killing buffers?"

Here is a better docstring:

[tab-bar-select-keep-windows.patch (text/x-diff, inline)]
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 61efa332e0b..f05596d5ed9 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -1393,6 +1405,53 @@ tab-bar-tab-post-select-functions
   :group 'tab-bar
   :version "30.1")
 
+(defcustom tab-bar-select-keep-windows-function #'tab-bar-select-keep-windows
+  "Function that keeps windows after selecting a tab.
+When a previously selected tab displayed a buffer that was later killed,
+this function defines what to do with the window that displayed that buffer
+after switching back to the previous tab.  By default, either a random
+buffer is displayed instead of the killed buffer, or the window gets deleted.
+However, with the help of `window-kept-windows-functions' it's possible
+to handle such situations better by displaying an information about
+the killed buffer."
+  :type '(choice (const :tag "No special handling" nil)
+                 (const :tag "Show placeholder buffers"
+                        tab-bar-select-keep-windows)
+                 (function :tag "Function"))
+  :group 'tab-bar
+  :version "30.1")
+
+(defun tab-bar-select-keep-windows (_frame windows)
+  "Display a placeholder buffer in the window with killed buffer.
+A button allows to restore a killed file buffer."
+  (dolist (quad windows)
+    (when (window-live-p (nth 0 quad))
+      (let* ((window (nth 0 quad))
+             (old-buffer (nth 1 quad))
+             (file (when (bufferp old-buffer)
+                     (buffer-file-name old-buffer)))
+             (name (or file
+                       (and (fboundp 'buffer-last-name)
+                            (buffer-last-name old-buffer))
+                       old-buffer))
+             (new-buffer (generate-new-buffer
+                          (format "*Old buffer %s*" name))))
+        (with-current-buffer new-buffer
+          (set-auto-mode)
+          (insert (format-message "This window displayed the %s `%s'.\n"
+                                  (if file "file" "buffer")
+                                  name))
+          (when file
+            (insert-button
+             "[Restore]" 'action
+             (lambda (_button)
+               (set-window-buffer window (find-file-noselect file))
+               (set-window-start window (nth 2 quad) t)
+               (set-window-point window (nth 3 quad)))))
+          (goto-char (point-min))
+          (setq buffer-read-only t)
+          (set-window-buffer window new-buffer))))))
+
 (defvar tab-bar-minibuffer-restore-tab nil
   "Tab number for `tab-bar-minibuffer-restore-tab'.")
 
@@ -1438,7 +1497,10 @@ tab-bar-select-tab
       (let* ((from-tab (tab-bar--tab))
              (to-tab (nth to-index tabs))
              (wc (alist-get 'wc to-tab))
-             (ws (alist-get 'ws to-tab)))
+             (ws (alist-get 'ws to-tab))
+             (window-kept-windows-functions
+              (delq nil (cons tab-bar-select-keep-windows-function
+                              window-kept-windows-functions))))
 
         ;; During the same session, use window-configuration to switch
         ;; tabs, because window-configurations are more reliable

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Fri, 08 Mar 2024 09:22:02 GMT) Full text and rfc822 format available.

Message #175 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Fri, 8 Mar 2024 10:21:04 +0100
[Message part 1 (text/plain, inline)]
> We could leave it called on every set-window-configuration
> even with an empty window list, as a general post-hook.

I've now reworked the patch for the following reasons:

- Changing the existing behavior of 'window-state-put' in order to make
  it behave like 'set-window-configuration' in certain regards is a bad
  idea IMO.  Someone, somewhere might be used to the current behavior.

- The entire idea of deleting windows when their buffers are dead might
  annoy people who prefer a fixed frame layout with a predefined number
  of windows.

The new patch attached renames 'window-kept-windows-functions' to
`window-restore-dead-buffer-windows'.  That variable is no more a hook
but may be

- t to never delete a dead buffer window,

- 'delete' to do what 'window-state-put' does now

- 'dedicated' to do what 'set-window-configuration' does now

- nil to keep the current behavior

- a function to do what 'window-kept-windows-functions' did.

I abandoned the hook idea because having more than one function work on
a list of kept windows means asking for troubles.  In addition, I now
pass a third argument to that function - 'configuration' if called by
'set-window-configuration' and 'state' if called by 'window-state-put'.

When looking into this I (re)discovered that 'set-window-configuration'
leaves dead buffer windows alone if they do have a buffer in the
configuration that function is about to replace.  This comment

      /* Kludge Alert!
	 Mark all windows now on frame as "deleted".
	 Restoring the new configuration "undeletes" any that are in it.

	 Save their current buffers in their height fields, since we may
	 need it later, if a buffer saved in the configuration is now
	 dead.  */

tells how this was done in the past and these two snippets

      /* Since combination limit makes sense for an internal windows
	 only, we use this slot to save the buffer for the sake of
	 possible resurrection in Fset_window_configuration.  */
      wset_combination_limit (w, w->contents);

and

	  /* If we squirreled away the buffer, restore it now.  */
	  if (BUFFERP (w->combination_limit))
	    wset_buffer (w, w->combination_limit);

explain how this is done now.  (Calling delete_all_child_windows and
running SAFE_NALLOCA in 'set-window-configuration' is a bad idea given
the fact that the body of 'save-window-excursion' practically never
changes the existing configuration, but I won't discuss that here.)

Suffice it to say that 'set-window-configuration' leaves a dead buffer
window alone if it shows a buffer in the configuration it is about to
replace.  'window-state-put' does not do that because it has no idea of
the identity of windows and making it map the current window tree into
the window tree it is about to restore does not look like an appealing
endeavor to me (besides the fact that it would change existing behavior
again).

Now what I did was to add two more entries for each window passed to the
'window-restore-dead-buffer-windows' function:

- One for the dedicated status of the window in the saved configuration
  or state.  If you restore the old buffer, you should also set that, I
  suppose.

- One that is t if the window was live in the configuration replaced by
  'set-window-configuration'.  It might help to decide whether the new
  buffer would be a better alternative than restoring the dead buffer.
  I don't think the tab bar code would need it.

Have a look.

> BTW, I didn't test yet what happens when
> window-kept-windows-functions is non-nil but does nothing.
> Here is what happens:
>
>    Error muted by safe_call: (get-scratch-buffer-create)
>    signaled (wrong-type-argument window-live-p #<window 7>)
>
> But maybe this is ok.

I now made it call 'window-restore-dead-buffer-windows' iff it is a
function (it may still have the wrong number of arguments though).  BTW
the "Error muted by safe_call" messages are helpful - once you get used
to them.

martin
[window-restore-dead-buffer-windows.diff (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sat, 09 Mar 2024 08:36:01 GMT) Full text and rfc822 format available.

Message #178 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Juri Linkov <juri <at> linkov.net>
Cc: rudalics <at> gmx.at, 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sat, 09 Mar 2024 10:35:01 +0200
> From: Juri Linkov <juri <at> linkov.net>
> Cc: rudalics <at> gmx.at,  68235 <at> debbugs.gnu.org
> Date: Wed, 06 Mar 2024 20:03:50 +0200
> 
> > This doc string doesn't explain enough: it begs the question "what
> > does selecting a tab have to do with killing buffers?"
> 
> Here is a better docstring:
> 
> +(defcustom tab-bar-select-keep-windows-function #'tab-bar-select-keep-windows
> +  "Function that keeps windows after selecting a tab.
> +When a previously selected tab displayed a buffer that was later killed,
> +this function defines what to do with the window that displayed that buffer
> +after switching back to the previous tab.

Thanks, this is much more clear now.  I suggest a slight rewording:

    Function called when selecting a tab to handle windows whose buffer was killed.
  When a tab-bar tab displays a window whose buffer was killed since
  this tab was last selected, this function determines what to do with
  that window.

> +(defun tab-bar-select-keep-windows (_frame windows)
> +  "Display a placeholder buffer in the window with killed buffer.
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
"...in the window whose buffer was killed."

> +A button allows to restore a killed file buffer."

"A button in the window allows to restore the killed buffer, if
it was visiting a file."





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 10 Mar 2024 17:34:01 GMT) Full text and rfc822 format available.

Message #181 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sun, 10 Mar 2024 19:23:39 +0200
> The new patch attached renames 'window-kept-windows-functions' to
> `window-restore-dead-buffer-windows'.

Thanks.  I finished testing your new patch, and everything works nicely.

Regarding the name `window-restore-dead-buffer-windows',
I thought that the epithet "dead" is applied only to windows,
but buffers are called "killed", but maybe I got the wrong impression.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 11 Mar 2024 09:15:01 GMT) Full text and rfc822 format available.

Message #184 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Mon, 11 Mar 2024 10:13:32 +0100
> Regarding the name `window-restore-dead-buffer-windows',
> I thought that the epithet "dead" is applied only to windows,
> but buffers are called "killed", but maybe I got the wrong impression.

I'll call it `window-restore-killed-buffer-windows' and install in a
week unless new issues come up.

Thanks, martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Fri, 15 Mar 2024 09:40:02 GMT) Full text and rfc822 format available.

Message #187 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Fri, 15 Mar 2024 10:38:18 +0100
>> The new patch attached renames 'window-kept-windows-functions' to
>> `window-restore-dead-buffer-windows'.
>
> Thanks.  I finished testing your new patch, and everything works nicely.
>
> Regarding the name `window-restore-dead-buffer-windows',
> I thought that the epithet "dead" is applied only to windows,
> but buffers are called "killed", but maybe I got the wrong impression.

Pushed to master now.  Please check again.

Thanks, martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Fri, 15 Mar 2024 10:13:01 GMT) Full text and rfc822 format available.

Message #190 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Andreas Schwab <schwab <at> linux-m68k.org>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Fri, 15 Mar 2024 11:11:32 +0100
On Mär 08 2024, martin rudalics wrote:

> diff --git a/src/buffer.h b/src/buffer.h
> index 87ba2802b39..bbe1aeff668 100644
> --- a/src/buffer.h
> +++ b/src/buffer.h
> @@ -309,6 +309,9 @@ #define BVAR(buf, field) ((buf)->field ## _)
>    /* The name of this buffer.  */
>    Lisp_Object name_;
>  
> +  /* The last name of this buffer before it was renamed or killed.  */
> +  Lisp_Object last_name_;
> +
>    /* The name of the file visited in this buffer, or nil.  */
>    Lisp_Object filename_;
>  

../../emacs/src/pdumper.c: In function ‘dump_buffer’:
../../emacs/src/pdumper.c:2800:3: error: #error "buffer changed. See CHECK_STRUCTS comment in config.h."
 2800 | # error "buffer changed. See CHECK_STRUCTS comment in config.h."
      |   ^~~~~

-- 
Andreas Schwab, schwab <at> linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Fri, 15 Mar 2024 10:58:02 GMT) Full text and rfc822 format available.

Message #193 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Andreas Schwab <schwab <at> linux-m68k.org>
Cc: 68235 <at> debbugs.gnu.org, Juri Linkov <juri <at> linkov.net>
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Fri, 15 Mar 2024 11:56:37 +0100
> ../../emacs/src/pdumper.c: In function ‘dump_buffer’:
> ../../emacs/src/pdumper.c:2800:3: error: #error "buffer changed. See CHECK_STRUCTS comment in config.h."
>   2800 | # error "buffer changed. See CHECK_STRUCTS comment in config.h."
>        |   ^~~~~

Hopefully fixed now.  Please try again.

Thanks, martin

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 17 Mar 2024 18:00:02 GMT) Full text and rfc822 format available.

Message #196 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sun, 17 Mar 2024 19:47:44 +0200
> Pushed to master now.  Please check again.

Thank you very much.  Everything is working nicely.

One thing I don't understand what is the purpose of
`marker-last-position'?  It's intended to be used in
a function in `window-restore-killed-buffer-windows'?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 17 Mar 2024 18:22:02 GMT) Full text and rfc822 format available.

Message #199 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: rudalics <at> gmx.at, 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sun, 17 Mar 2024 19:57:27 +0200
> Thanks, this is much more clear now.  I suggest a slight rewording:
>
>     Function called when selecting a tab to handle windows whose buffer was killed.
>   When a tab-bar tab displays a window whose buffer was killed since
>   this tab was last selected, this function determines what to do with
>   that window.
>
>> +(defun tab-bar-select-keep-windows (_frame windows)
>> +  "Display a placeholder buffer in the window with killed buffer.
>                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> "...in the window whose buffer was killed."
>
>> +A button allows to restore a killed file buffer."
>
> "A button in the window allows to restore the killed buffer, if
> it was visiting a file."

So now the patch is pushed with these changes.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 18 Mar 2024 10:19:02 GMT) Full text and rfc822 format available.

Message #202 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Mon, 18 Mar 2024 11:13:02 +0100
> One thing I don't understand what is the purpose of
> `marker-last-position'?  It's intended to be used in
> a function in `window-restore-killed-buffer-windows'?

It's needed in 'set-window-configuration' and 'window-state-put' to
provide the last positions of a window's start and point when its buffer
was killed.  It could be used in 'window-restore-killed-buffer-windows'
to restore other markers as well but I'm currently not aware of whether
such markers exist and whether restoring them would be useful.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 09 Apr 2024 06:58:01 GMT) Full text and rfc822 format available.

Message #205 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Tue, 09 Apr 2024 09:53:41 +0300
> I'll call it `window-restore-killed-buffer-windows' and install in a
> week unless new issues come up.

I found one interesting problem with `window-restore-killed-buffer-windows'.
Here is a reproducible test case:

0. emacs -Q
1. cd etc/images/
2. RET to visit the first image
3. C-x t 2
4. n to visit the next image
5. C-x t o

The previous tab shows:

  "This window displayed the buffer ‘ **lose**’."

What it expected here instead of **lose**
is the real file buffer with the previous image.

The problem is that 'image-next-file' calls 'find-alternate-file'
that does such buffer renaming:

    (if (get-buffer " **lose**")
	(kill-buffer " **lose**"))
    (rename-buffer " **lose**")

and 'rename-buffer' changes the buffer's last name to **lose**.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 09 Apr 2024 07:38:03 GMT) Full text and rfc822 format available.

Message #208 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Juri Linkov <juri <at> linkov.net>
Cc: rudalics <at> gmx.at, 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90;
 Switching tabs stops following process output in selected window
Date: Tue, 09 Apr 2024 10:36:44 +0300
> Cc: 68235 <at> debbugs.gnu.org
> From: Juri Linkov <juri <at> linkov.net>
> Date: Tue, 09 Apr 2024 09:53:41 +0300
> 
> The previous tab shows:
> 
>   "This window displayed the buffer ‘ **lose**’."
> 
> What it expected here instead of **lose**
> is the real file buffer with the previous image.
> 
> The problem is that 'image-next-file' calls 'find-alternate-file'
> that does such buffer renaming:
> 
>     (if (get-buffer " **lose**")
> 	(kill-buffer " **lose**"))
>     (rename-buffer " **lose**")
> 
> and 'rename-buffer' changes the buffer's last name to **lose**.

Any idea why does image-next-file do that?  Or is this problem
specific to using tabs?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 09 Apr 2024 09:23:01 GMT) Full text and rfc822 format available.

Message #211 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Tue, 9 Apr 2024 11:22:21 +0200
[Message part 1 (text/plain, inline)]
> The problem is that 'image-next-file' calls 'find-alternate-file'
> that does such buffer renaming:
>
>      (if (get-buffer " **lose**")
> 	(kill-buffer " **lose**"))
>      (rename-buffer " **lose**")
>
> and 'rename-buffer' changes the buffer's last name to **lose**.

Isn't the problem that it leaves the last name nil?  Does the attached
diff fix it?

Thanks, martin
[rename-buffer.diff (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Tue, 09 Apr 2024 16:48:04 GMT) Full text and rfc822 format available.

Message #214 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Tue, 09 Apr 2024 19:40:03 +0300
>> The problem is that 'image-next-file' calls 'find-alternate-file'
>> that does such buffer renaming:
>>
>>      (if (get-buffer " **lose**")
>> 	(kill-buffer " **lose**"))
>>      (rename-buffer " **lose**")
>>
>> and 'rename-buffer' changes the buffer's last name to **lose**.
>
> Isn't the problem that it leaves the last name nil?  Does the attached
> diff fix it?
>
> diff --git a/src/buffer.c b/src/buffer.c
> index 291c7d3f911..5e2386c94fa 100644
> --- a/src/buffer.c
> +++ b/src/buffer.c
> @@ -1686,7 +1686,11 @@ DEFUN ("rename-buffer", Frename_buffer, Srename_buffer, 1, 2,
>  	 with the original name.  It makes UNIQUE equivalent to
>  	 (rename-buffer (generate-new-buffer-name NEWNAME)).  */
>        if (NILP (unique) && XBUFFER (tem) == current_buffer)
> -	return BVAR (current_buffer, name);
> +	{
> +	  bset_last_name (current_buffer, oldname);
> +
> +	  return BVAR (current_buffer, name);
> +	}
>        if (!NILP (unique))
>  	newname = Fgenerate_new_buffer_name (newname, oldname);
>        else

Alas, this doesn't help.  Because 'find-alternate-file' renames
the buffer with (rename-buffer " **lose**") before killing it.
So 'kill-buffer' remembers the last buffer name " **lose**".




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Wed, 10 Apr 2024 08:48:05 GMT) Full text and rfc822 format available.

Message #217 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Wed, 10 Apr 2024 10:47:23 +0200
> Alas, this doesn't help.

I will have to install it nonetheless.  Otherwise, I would have to
change the doc-string of 'buffer-last-name' which says

  This is the name BUFFER had before the last time it was renamed or
  immediately before it was killed.

> Because 'find-alternate-file' renames
> the buffer with (rename-buffer " **lose**") before killing it.
> So 'kill-buffer' remembers the last buffer name " **lose**".

But that's correct and reflects what the doc-string says.  The problem
must be elsewhere.  Basically, it seems to me that when we have a live
buffer whose name is " **lose**" and a killed buffer with the same last
name (or maybe two or more killed buffers with the same last name) we
have a conflict that we have to resolve somehow.  Right?  I don't
understand why we can't "prefer" the live buffer to the dead buffer
here.  For dead buffers, the problem might be that of finding the right
one, in particular when they have different file names.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Wed, 10 Apr 2024 18:04:01 GMT) Full text and rfc822 format available.

Message #220 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Wed, 10 Apr 2024 20:35:20 +0300
>> Because 'find-alternate-file' renames
>> the buffer with (rename-buffer " **lose**") before killing it.
>> So 'kill-buffer' remembers the last buffer name " **lose**".
>
> But that's correct and reflects what the doc-string says.  The problem
> must be elsewhere.  Basically, it seems to me that when we have a live
> buffer whose name is " **lose**" and a killed buffer with the same last
> name (or maybe two or more killed buffers with the same last name) we
> have a conflict that we have to resolve somehow.  Right?  I don't
> understand why we can't "prefer" the live buffer to the dead buffer
> here.  For dead buffers, the problem might be that of finding the right
> one, in particular when they have different file names.

What is worse is that 'find-alternate-file' also resets
'buffer-file-name' to nil before killing the " **lose**" buffer.
So even can't use a file name.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Thu, 11 Apr 2024 09:18:02 GMT) Full text and rfc822 format available.

Message #223 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Thu, 11 Apr 2024 11:16:54 +0200
> What is worse is that 'find-alternate-file' also resets
> 'buffer-file-name' to nil before killing the " **lose**" buffer.
> So even can't use a file name.

Would replacing

	  (kill-buffer obuf))))))

with

	  (setq buffer-file-name ofile)
	  (setq buffer-file-number onum)
	  (setq buffer-file-truename otrue)
	  (kill-buffer obuf))))))

fix that?

I never used 'find-alternate-file' and, after looking at its code for
the first time now, wouldn't touch it with a ten foot pole.  Using it in
'image-next-file' seems a very bad idea: Is there any guarantee that the
assumptions about which buffer is current hold when running things like
'kill-buffer-query-functions' or 'kill-buffer-hook' manually?

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Fri, 12 Apr 2024 06:50:02 GMT) Full text and rfc822 format available.

Message #226 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Fri, 12 Apr 2024 09:30:37 +0300
>> What is worse is that 'find-alternate-file' also resets
>> 'buffer-file-name' to nil before killing the " **lose**" buffer.
>> So even can't use a file name.
>
> Would replacing
>
> 	  (kill-buffer obuf))))))
>
> with
>
> 	  (setq buffer-file-name ofile)
> 	  (setq buffer-file-number onum)
> 	  (setq buffer-file-truename otrue)
> 	  (kill-buffer obuf))))))
>
> fix that?
>
> I never used 'find-alternate-file' and, after looking at its code for
> the first time now, wouldn't touch it with a ten foot pole.

Indeed, I have the same impression.

> Using it in
> 'image-next-file' seems a very bad idea: Is there any guarantee that the
> assumptions about which buffer is current hold when running things like
> 'kill-buffer-query-functions' or 'kill-buffer-hook' manually?

Using 'find-alternate-file' in 'image-next-file' looks fine.
There are no other problems.  And revealing " **lose**"
while restoring windows is not a bug deal.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Fri, 12 Apr 2024 08:19:01 GMT) Full text and rfc822 format available.

Message #229 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Fri, 12 Apr 2024 10:18:03 +0200
[Message part 1 (text/plain, inline)]
> Using 'find-alternate-file' in 'image-next-file' looks fine.
> There are no other problems.  And revealing " **lose**"
> while restoring windows is not a bug deal.

OK.  Please try the attached patch.  With something like

(let ((buffer (find-file-noselect "~/foo.el")))
  (with-current-buffer buffer
    (find-alternate-file "~/bar.el")
    (message "%s..%s" (buffer-last-name buffer) (buffer-file-name buffer))))

it should work fine thus fixing the image mode problem.  With

(let ((buffer (find-file-noselect "~/foo/bar.el")))
  (with-current-buffer buffer
    (find-alternate-file "~/bar/bar.el")
    (message "%s..%s" (buffer-last-name buffer) (buffer-file-name buffer))))

you can still use the old file name to restore the buffer.

martin
[files.el.diff (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Fri, 12 Apr 2024 16:32:03 GMT) Full text and rfc822 format available.

Message #232 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Fri, 12 Apr 2024 19:20:47 +0300
> OK.  Please try the attached patch.  With something like
>
> (let ((buffer (find-file-noselect "~/foo.el")))
>   (with-current-buffer buffer
>     (find-alternate-file "~/bar.el")
>     (message "%s..%s" (buffer-last-name buffer) (buffer-file-name buffer))))
>
> it should work fine thus fixing the image mode problem.  With
>
> (let ((buffer (find-file-noselect "~/foo/bar.el")))
>   (with-current-buffer buffer
>     (find-alternate-file "~/bar/bar.el")
>     (message "%s..%s" (buffer-last-name buffer) (buffer-file-name buffer))))
>
> you can still use the old file name to restore the buffer.

Thanks, I confirm this completely fixes the original test case.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 15 Apr 2024 09:23:04 GMT) Full text and rfc822 format available.

Message #235 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Mon, 15 Apr 2024 11:21:43 +0200
> Thanks, I confirm this completely fixes the original test case.

Should be installed now.  Please have a look.

Thanks, martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 21 Apr 2024 07:16:01 GMT) Full text and rfc822 format available.

Message #238 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Sun, 21 Apr 2024 09:59:28 +0300
>> Thanks, I confirm this completely fixes the original test case.
>
> Should be installed now.  Please have a look.

I noticed that now 'find-alternate-file' has such a problem
that it updates the modification timestamp of the directory.

This is because 'find-alternate-file' calls 'rename-buffer'
before setting back the value of 'buffer-file-name'.
So this code in 'rename-buffer' is fired and changes
the directory modification timestamp:

  if (NILP (BVAR (current_buffer, filename))
      && !NILP (BVAR (current_buffer, auto_save_file_name)))
    call0 (intern ("rename-auto-save-file"));

A possible fix would be to swap the order of
setting of 'buffer-file-name' and 'rename-buffer':

diff --git a/lisp/files.el b/lisp/files.el
index 1e11dd44bad..5ef1160ab18 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -2113,15 +2113,15 @@ find-alternate-file
 	(rename-buffer oname)))
     (unless (eq (current-buffer) obuf)
       (with-current-buffer obuf
+	;; Restore original buffer's file names so they can be still
+	;; used when referencing the now defunct buffer (Bug#68235).
+	(setq buffer-file-name ofile)
+	(setq buffer-file-number onum)
+	(setq buffer-file-truename otrue)
 	(unless (get-buffer oname)
 	  ;; Restore original's buffer name so 'kill-buffer' can use it
 	  ;; to assign its last name (Bug#68235).
 	  (rename-buffer oname))
-	;; Restore original buffer's file names so they can be still
-	;; used when referencing the now defunct buffer (Bug#68235).
-	(setq buffer-file-name ofile)
-	(setq buffer-file-number onum)
-	(setq buffer-file-truename otrue)
 	;; We already ran these; don't run them again.
 	(let (kill-buffer-query-functions kill-buffer-hook)
 	  (kill-buffer obuf))))))




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 21 Apr 2024 08:57:01 GMT) Full text and rfc822 format available.

Message #241 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Juri Linkov <juri <at> linkov.net>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process output
 in selected window
Date: Sun, 21 Apr 2024 10:56:15 +0200
> I noticed that now 'find-alternate-file' has such a problem
> that it updates the modification timestamp of the directory.
>
> This is because 'find-alternate-file' calls 'rename-buffer'
> before setting back the value of 'buffer-file-name'.
> So this code in 'rename-buffer' is fired and changes
> the directory modification timestamp:
>
>    if (NILP (BVAR (current_buffer, filename))
>        && !NILP (BVAR (current_buffer, auto_save_file_name)))
>      call0 (intern ("rename-auto-save-file"));

Why does an auto-save file exist at all in this situation?  If the
original buffer was modified, 'find-alternate-file' should have saved it
into its file and deleted the auto-save file.  Does your code rely on
fine tuned directory timestamps?

> A possible fix would be to swap the order of
> setting of 'buffer-file-name' and 'rename-buffer':

I see no problems doing that so please install.

Thanks, martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Sun, 21 Apr 2024 09:29:01 GMT) Full text and rfc822 format available.

Message #244 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Juri Linkov <juri <at> linkov.net>
Cc: rudalics <at> gmx.at, 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90;
 Switching tabs stops following process output in selected window
Date: Sun, 21 Apr 2024 12:27:52 +0300
> Cc: 68235 <at> debbugs.gnu.org
> From: Juri Linkov <juri <at> linkov.net>
> Date: Sun, 21 Apr 2024 09:59:28 +0300
> 
> >> Thanks, I confirm this completely fixes the original test case.
> >
> > Should be installed now.  Please have a look.
> 
> I noticed that now 'find-alternate-file' has such a problem
> that it updates the modification timestamp of the directory.

Why is this a problem?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 22 Apr 2024 06:58:02 GMT) Full text and rfc822 format available.

Message #247 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: rudalics <at> gmx.at, 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Mon, 22 Apr 2024 09:40:06 +0300
>> >> Thanks, I confirm this completely fixes the original test case.
>> >
>> > Should be installed now.  Please have a look.
>>
>> I noticed that now 'find-alternate-file' has such a problem
>> that it updates the modification timestamp of the directory.
>
> Why is this a problem?

Because it doesn't do any modification.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 22 Apr 2024 06:58:03 GMT) Full text and rfc822 format available.

Message #250 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: martin rudalics <rudalics <at> gmx.at>
Cc: 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Mon, 22 Apr 2024 09:46:00 +0300
>> I noticed that now 'find-alternate-file' has such a problem
>> that it updates the modification timestamp of the directory.
>>
>> This is because 'find-alternate-file' calls 'rename-buffer'
>> before setting back the value of 'buffer-file-name'.
>> So this code in 'rename-buffer' is fired and changes
>> the directory modification timestamp:
>>
>>    if (NILP (BVAR (current_buffer, filename))
>>        && !NILP (BVAR (current_buffer, auto_save_file_name)))
>>      call0 (intern ("rename-auto-save-file"));
>
> Why does an auto-save file exist at all in this situation?  If the
> original buffer was modified, 'find-alternate-file' should have saved it
> into its file and deleted the auto-save file.  Does your code rely on
> fine tuned directory timestamps?

Nothing special is done.  The problem is reproducible in 'emacs -Q'
with the original test case.

This is because image-mode modifies the timestamp unless a special handling
is used such as in 'image-toggle-display-image':

    (let ((create-lockfiles nil)) ; avoid changing dir mtime by lock_file
      (add-text-properties (point-min) (point-max) props)
      (restore-buffer-modified-p modified))

But 'rename-buffer' can't do the same.

>> A possible fix would be to swap the order of
>> setting of 'buffer-file-name' and 'rename-buffer':
>
> I see no problems doing that so please install.

Thanks, so now installed.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 22 Apr 2024 07:01:03 GMT) Full text and rfc822 format available.

Message #253 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Juri Linkov <juri <at> linkov.net>
Cc: rudalics <at> gmx.at, 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Mon, 22 Apr 2024 10:00:10 +0300
> From: Juri Linkov <juri <at> linkov.net>
> Cc: rudalics <at> gmx.at,  68235 <at> debbugs.gnu.org
> Date: Mon, 22 Apr 2024 09:40:06 +0300
> 
> >> >> Thanks, I confirm this completely fixes the original test case.
> >> >
> >> > Should be installed now.  Please have a look.
> >>
> >> I noticed that now 'find-alternate-file' has such a problem
> >> that it updates the modification timestamp of the directory.
> >
> > Why is this a problem?
> 
> Because it doesn't do any modification.

Sorry, I don't understand: you said it renames a file, didn't you?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 22 Apr 2024 16:38:04 GMT) Full text and rfc822 format available.

Message #256 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: rudalics <at> gmx.at, 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Mon, 22 Apr 2024 19:36:16 +0300
>> >> >> Thanks, I confirm this completely fixes the original test case.
>> >> >
>> >> > Should be installed now.  Please have a look.
>> >>
>> >> I noticed that now 'find-alternate-file' has such a problem
>> >> that it updates the modification timestamp of the directory.
>> >
>> > Why is this a problem?
>>
>> Because it doesn't do any modification.
>
> Sorry, I don't understand: you said it renames a file, didn't you?

It renames a buffer.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68235; Package emacs. (Mon, 22 Apr 2024 19:24:03 GMT) Full text and rfc822 format available.

Message #259 received at 68235 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Juri Linkov <juri <at> linkov.net>
Cc: rudalics <at> gmx.at, 68235 <at> debbugs.gnu.org
Subject: Re: bug#68235: 29.1.90; Switching tabs stops following process
 output in selected window
Date: Mon, 22 Apr 2024 22:22:48 +0300
> From: Juri Linkov <juri <at> linkov.net>
> Cc: rudalics <at> gmx.at,  68235 <at> debbugs.gnu.org
> Date: Mon, 22 Apr 2024 19:36:16 +0300
> 
> >> >> >> Thanks, I confirm this completely fixes the original test case.
> >> >> >
> >> >> > Should be installed now.  Please have a look.
> >> >>
> >> >> I noticed that now 'find-alternate-file' has such a problem
> >> >> that it updates the modification timestamp of the directory.
> >> >
> >> > Why is this a problem?
> >>
> >> Because it doesn't do any modification.
> >
> > Sorry, I don't understand: you said it renames a file, didn't you?
> 
> It renames a buffer.

Could you possibly be a bit more friendly by explaining the issue in
more than just 4 words?  Renaming a buffer will not cause a change in
directory's timestamp, so there must be something else involved.

And my original question, which is still unanswered, was why this is a
problem.  My point is that I don't see why changing the timestamp of
some directory should be a problem for Emacs users.  I'd still would
like to understand this.




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Tue, 21 May 2024 11:24:09 GMT) Full text and rfc822 format available.

This bug report was last modified 167 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.