unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: martin rudalics via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: Juri Linkov <juri@linkov.net>
Cc: 68235@debbugs.gnu.org
Subject: bug#68235: 29.1.90; Switching tabs stops following process output in selected window
Date: Mon, 19 Feb 2024 10:42:09 +0100	[thread overview]
Message-ID: <3fe7e4b4-bc9a-4303-a87f-a360765c597f@gmx.at> (raw)
In-Reply-To: <86il2mxmxd.fsf@mail.linkov.net>

[-- Attachment #1: Type: text/plain, Size: 2293 bytes --]

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

[-- Attachment #2: keep-windows.diff --]
[-- Type: text/x-patch, Size: 10808 bytes --]

diff --git a/lisp/window.el b/lisp/window.el
index e100f25526b..868eef0b63c 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -6174,6 +6174,9 @@ window-state-put-list
 (defvar window-state-put-stale-windows nil
   "Helper variable for `window-state-put'.")
 
+(defvar window-state-put-kept-windows nil
+  "Helper variable for `window-state-put'.")
+
 (defun window--state-put-1 (state &optional window ignore totals pixelwise)
   "Helper function for `window-state-put'."
   (let ((type (car state)))
@@ -6278,9 +6281,10 @@ window--state-put-2
 	  (set-window-parameter window (car parameter) (cdr parameter))))
       ;; Process buffer related state.
       (when state
-	(let ((buffer (get-buffer (car state)))
-	      (state (cdr state)))
-	  (if buffer
+	(let* ((old-buffer-or-name (car state))
+	       (buffer (get-buffer old-buffer-or-name))
+	       (state (cdr state)))
+	  (if (buffer-live-p buffer)
 	      (with-current-buffer buffer
 		(set-window-buffer window buffer)
 		(set-window-hscroll window (cdr (assq 'hscroll state)))
@@ -6375,7 +6379,20 @@ window--state-put-2
 	    ;; save the window with the intention of deleting it later
 	    ;; if possible.
 	    (switch-to-prev-buffer window)
-	    (push window window-state-put-stale-windows)))))))
+	    (if window-kept-windows-functions
+		(let* ((start (cdr (assq 'start state)))
+		       ;; Handle both - marker positions from writable
+		       ;; states and markers from non-writable states.
+		       (start-pos (if (markerp start)
+				      (marker-last-position start)
+				    start))
+		       (point (cdr (assq 'point state)))
+		       (point-pos (if (markerp point)
+				      (marker-last-position point)
+				    point)))
+		  (push (list window old-buffer-or-name start-pos point-pos)
+			window-state-put-kept-windows))
+	      (push window window-state-put-stale-windows))))))))
 
 (defun window-state-put (state &optional window ignore)
   "Put window state STATE into WINDOW.
@@ -6388,8 +6405,20 @@ window-state-put
 Optional argument IGNORE non-nil means ignore minimum window
 sizes and fixed size restrictions.  IGNORE equal `safe' means
 windows can get as small as `window-safe-min-height' and
-`window-safe-min-width'."
+`window-safe-min-width'.
+
+If the abnormal hook `window-kept-windows-functions' is non-nil,
+never delete any windows saved by STATE whose buffers were
+deleted since STATE was saved.  Rather show some live buffer in
+them and call each function in `window-kept-windows-functions'
+with a list of two arguments: the frame where STATE was put and a
+list of entries for each such window.  Each entry contains four
+elements - the window, its old buffer and the last positions of
+`window-start' and `window-point' for the buffer in that window.
+Always check the window for liveness because another function run
+by this hook may have deleted it."
   (setq window-state-put-stale-windows nil)
+  (setq window-state-put-kept-windows nil)
 
   ;; When WINDOW is internal or nil, reduce it to a live one,
   ;; then create a new window on the same frame to put STATE into.
@@ -6492,12 +6521,17 @@ window-state-put
 	(window--state-put-2 ignore pixelwise))
       (while window-state-put-stale-windows
 	(let ((window (pop window-state-put-stale-windows)))
-          ;; Avoid that 'window-deletable-p' throws an error if window
+	  ;; 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))))
+      (when window-kept-windows-functions
+	(run-hook-with-args
+	 'window-kept-windows-functions
+	 frame window-state-put-kept-windows)
+	(setq window-state-put-kept-windows nil))
       (window--check frame))))
 
 (defun window-state-buffers (state)
diff --git a/src/marker.c b/src/marker.c
index 377f6fbe8db..14b9f63f0cd 100644
--- a/src/marker.c
+++ b/src/marker.c
@@ -458,6 +458,18 @@ DEFUN ("marker-position", Fmarker_position, Smarker_position, 1, 1, 0,
   return Qnil;
 }
 
+DEFUN ("marker-last-position", Fmarker_last_position, Smarker_last_position, 1, 1, 0,
+       doc: /* Return last position of MARKER in its buffer.
+This is like `marker-position' with one exception:  If the buffer of
+MARKER is dead, it returns the last position of MARKER in that buffer
+before it was killed.  */)
+  (Lisp_Object marker)
+{
+  CHECK_MARKER (marker);
+
+  return make_fixnum (XMARKER (marker)->charpos);
+}
+
 /* Change M so it points to B at CHARPOS and BYTEPOS.  */
 
 static void
@@ -825,6 +837,7 @@ verify_bytepos (ptrdiff_t charpos)
 syms_of_marker (void)
 {
   defsubr (&Smarker_position);
+  defsubr (&Smarker_last_position);
   defsubr (&Smarker_buffer);
   defsubr (&Sset_marker);
   defsubr (&Scopy_marker);
diff --git a/src/window.c b/src/window.c
index 3a54f7ce7b1..8e002d70db6 100644
--- a/src/window.c
+++ b/src/window.c
@@ -7090,6 +7090,24 @@ DEFUN ("set-window-configuration", Fset_window_configuration,
 the mini-window of the frame doesn't get set to the corresponding element
 of CONFIGURATION.
 
+Normally, this function will try to delete any dead window in
+CONFIGURATION whose buffer has been deleted since CONFIGURATION was
+made.  However, if the abnormal hook `window-kept-windows-functions' is
+non-nil, it will preserve such a window in the restored layout and show
+another buffer in it.
+
+After restoring the frame layout, this function runs the abnormal hook
+`window-kept-windows-functions' with two arguments - the frame whose
+layout it has restored and a list of entries for each window whose
+buffer has been found dead when it tried to restore CONFIGURATION: Each
+entry is a list of four elements <window, buffer, start, point> where
+`window' denotes the window whose buffer was found dead, `buffer'
+denotes the dead buffer, and `start' and `point' denote the last known
+positions of `window-start' and `window-point' of the buffer in that
+window.  Any function run by this hook should check the window for
+liveness because another function run by this hook may have deleted it
+in the meantime."
+
 If CONFIGURATION was made from a frame that is now deleted,
 only frame-independent values can be restored.  In this case,
 the return value is nil.  Otherwise the value is t.  */)
@@ -7100,6 +7118,7 @@ DEFUN ("set-window-configuration", Fset_window_configuration,
   struct Lisp_Vector *saved_windows;
   Lisp_Object new_current_buffer;
   Lisp_Object frame;
+  Lisp_Object kept_windows = Qnil;
   Lisp_Object old_frame = selected_frame;
   struct frame *f;
   ptrdiff_t old_point = -1;
@@ -7340,6 +7359,11 @@ DEFUN ("set-window-configuration", Fset_window_configuration,
 		   BUF_PT (XBUFFER (w->contents)),
 		   BUF_PT_BYTE (XBUFFER (w->contents)));
 	      w->start_at_line_beg = true;
+	      if (!NILP (Vwindow_kept_windows_functions))
+		kept_windows = Fcons (list4 (window, p->buffer,
+					     Fmarker_last_position (p->start),
+					     Fmarker_last_position (p->pointm)),
+				      kept_windows);
 	    }
 	  else if (!NILP (w->start))
 	    /* Leaf window has no live buffer, get one.  */
@@ -7360,6 +7384,11 @@ DEFUN ("set-window-configuration", Fset_window_configuration,
 		dead_windows = Fcons (window, dead_windows);
 	      /* Make sure window is no more dedicated.  */
 	      wset_dedicated (w, Qnil);
+	      if (!NILP (Vwindow_kept_windows_functions))
+		kept_windows = Fcons (list4 (window, p->buffer,
+					     Fmarker_last_position (p->start),
+					     Fmarker_last_position (p->pointm)),
+				      kept_windows);
 	    }
 	}
 
@@ -7411,12 +7440,13 @@ DEFUN ("set-window-configuration", Fset_window_configuration,
       unblock_input ();
 
       /* Scan dead buffer windows.  */
-      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);
-	}
+      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);
+	  }
 
       /* Record the selected window's buffer here.  The window should
 	 already be the selected one from the call above.  */
@@ -7463,6 +7493,11 @@ DEFUN ("set-window-configuration", Fset_window_configuration,
   minibuf_selected_window = data->minibuf_selected_window;
 
   SAFE_FREE ();
+
+  if (!NILP (Vrun_hooks) && !NILP (Vwindow_kept_windows_functions))
+    run_hook_with_args_2 (Qwindow_kept_windows_functions, frame,
+			  kept_windows);
+
   return FRAME_LIVE_P (f) ? Qt : Qnil;
 }
 
@@ -8460,6 +8495,8 @@ syms_of_window (void)
   DEFSYM (Qheader_line_format, "header-line-format");
   DEFSYM (Qtab_line_format, "tab-line-format");
   DEFSYM (Qno_other_window, "no-other-window");
+  DEFSYM (Qwindow_kept_windows_functions,
+	  "window-kept-windows-functions");
 
   DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
 	       doc: /* Non-nil means call as function to display a help buffer.
@@ -8617,6 +8654,28 @@ syms_of_window (void)
 call is performed with the frame temporarily selected.  */);
   Vwindow_configuration_change_hook = Qnil;
 
+  DEFVAR_LISP ("window-kept-windows-functions",
+	       Vwindow_kept_windows_functions,
+	       doc: /* Functions run after restoring a window configuration or state.
+These functions are called by `set-window-configuration' and
+`window-state-put'.  When the value of this variable is non-nil, these
+functions restore any window whose buffer has been deleted since the
+corresponding configuration or state was saved.  Rather than deleting
+such a window, `set-window-configuration' and `window-state-put' show
+some live buffer in it.
+
+The value should be a list of functions that take two arguments.  The
+first argument specifies the frame whose configuration has been
+restored.  The second argument, if non-nil, specifies a list of entries
+for each window whose buffer has been found dead at the time
+'set-window-configuration' or `window-state-put' tried to restore it in
+that window.  Each entry is a list of four values - the window whose
+buffer was found dead, the dead buffer, and the positions of start and
+point of the buffer in that window.  Note that the window may be already
+dead since another function on this list may have deleted it in the
+meantime.  */);
+  Vwindow_kept_windows_functions = Qnil;
+
   DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
 	       doc: /* Non-nil means `recenter' redraws entire frame.
 If this option is non-nil, then the `recenter' command with a nil

  reply	other threads:[~2024-02-19  9:42 UTC|newest]

Thread overview: 85+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-03 20:48 bug#68235: 29.1.90; Switching tabs stops following process output in selected window Dan McCarthy
2024-01-04  6:09 ` Eli Zaretskii
2024-01-04 10:23   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-04 10:42     ` Eli Zaretskii
2024-01-04 17:07     ` Juri Linkov
2024-01-04 17:48       ` Eli Zaretskii
2024-01-05  9:24         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-06 17:36           ` Juri Linkov
2024-01-07 14:54             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-07 16:45               ` Juri Linkov
2024-01-08  8:55                 ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-09 17:23                   ` Juri Linkov
2024-01-07 16:49               ` Juri Linkov
2024-01-09 17:25                 ` Juri Linkov
2024-01-10  8:37                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-10 17:08                     ` Juri Linkov
2024-01-11  9:14                       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-12  7:37                         ` Juri Linkov
2024-01-13 10:38                           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-13 15:02                             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-13 18:20                               ` Juri Linkov
2024-01-14  8:13                                 ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-14 18:53                                   ` Juri Linkov
2024-01-15 10:24                                     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-15 17:53                                       ` Juri Linkov
2024-01-16 10:19                                         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-16 16:30                                           ` Juri Linkov
2024-01-17 11:42                                             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-17 16:36                                               ` Juri Linkov
2024-01-18 10:47                                                 ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-18 16:50                                                   ` Juri Linkov
2024-01-20  9:44                                                     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-22  7:43                                                       ` Juri Linkov
2024-01-23  9:30                                                         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-24  7:54                                                           ` Juri Linkov
2024-01-25  9:39                                                             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-25 17:46                                                               ` Juri Linkov
2024-01-26  9:56                                                                 ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-01-27 17:58                                                                   ` Juri Linkov
2024-01-28 10:06                                                                     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-02-05  7:17                                                       ` Juri Linkov
2024-02-06 10:34                                                         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-02-06 18:03                                                           ` Juri Linkov
2024-02-15  7:34                                                           ` Juri Linkov
2024-02-16  9:40                                                             ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-02-18  7:35                                                               ` Juri Linkov
2024-02-19  9:42                                                                 ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2024-02-20 17:44                                                                   ` Juri Linkov
2024-03-04  9:40                                                                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-05 17:27                                                                     ` Juri Linkov
2024-03-05 17:45                                                                       ` Eli Zaretskii
2024-03-06 18:03                                                                         ` Juri Linkov
2024-03-09  8:35                                                                           ` Eli Zaretskii
2024-03-17 17:57                                                                             ` Juri Linkov
2024-03-05 17:37                                                                     ` Juri Linkov
2024-03-06 10:19                                                                       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-06 17:57                                                                         ` Juri Linkov
2024-03-08  9:21                                                                           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-10 17:23                                                                             ` Juri Linkov
2024-03-11  9:13                                                                               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-09  6:53                                                                                 ` Juri Linkov
2024-04-09  7:36                                                                                   ` Eli Zaretskii
2024-04-09  9:22                                                                                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-09 16:40                                                                                     ` Juri Linkov
2024-04-10  8:47                                                                                       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-10 17:35                                                                                         ` Juri Linkov
2024-04-11  9:16                                                                                           ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-12  6:30                                                                                             ` Juri Linkov
2024-04-12  8:18                                                                                               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-12 16:20                                                                                                 ` Juri Linkov
2024-04-15  9:21                                                                                                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-21  6:59                                                                                                     ` Juri Linkov
2024-04-21  8:56                                                                                                       ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-22  6:46                                                                                                         ` Juri Linkov
2024-04-21  9:27                                                                                                       ` Eli Zaretskii
2024-04-22  6:40                                                                                                         ` Juri Linkov
2024-04-22  7:00                                                                                                           ` Eli Zaretskii
2024-04-22 16:36                                                                                                             ` Juri Linkov
2024-04-22 19:22                                                                                                               ` Eli Zaretskii
2024-03-15  9:38                                                                               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-17 17:47                                                                                 ` Juri Linkov
2024-03-18 10:13                                                                                   ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-03-15 10:11                                                                             ` Andreas Schwab
2024-03-15 10:56                                                                               ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-02-04 17:27                       ` Juri Linkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3fe7e4b4-bc9a-4303-a87f-a360765c597f@gmx.at \
    --to=bug-gnu-emacs@gnu.org \
    --cc=68235@debbugs.gnu.org \
    --cc=juri@linkov.net \
    --cc=rudalics@gmx.at \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).