Subject: bug#68235: 29.1.90; Switching tabs stops following process output in selected window

From: martin rudalics <[email-masked]>
Date: Thu, 25 Jan 2024 10:39:51 +0100

> 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

diff --git a/src/buffer.c b/src/buffer.c
index 352aca8ddfd..f79b1e06119 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -327,6 +327,11 @@ bset_name (struct buffer *b, Lisp_Object val)
   b->name_ = val;
 }
 static void
+bset_lastname (struct buffer *b, Lisp_Object val)
+{
+  b->lastname_ = val;
+}
+static void
 bset_overwrite_mode (struct buffer *b, Lisp_Object val)
 {
   b->overwrite_mode_ = val;
@@ -1276,6 +1281,19 @@ DEFUN ("buffer-name", Fbuffer_name, Sbuffer_name, 0, 1, 0,
   return BVAR (decode_buffer (buffer), name);
 }
 
+DEFUN ("buffer-last-name", Fbuffer_last_name, Sbuffer_last_name, 0, 1, 0,
+       doc: /* Return last name of BUFFER, as a string.
+BUFFER defaults to the current buffer.
+
+The return value is nil if BUFFER is live and has never been renamed.
+If BUFFER is live and has been renamed at least once, it is the name it
+had before the last rename changed it.  For a dead buffer it is the name
+the buffer had before it was killed.  */)
+  (Lisp_Object buffer)
+{
+  return BVAR (decode_buffer (buffer), lastname);
+}
+
 DEFUN ("buffer-file-name", Fbuffer_file_name, Sbuffer_file_name, 0, 1, 0,
        doc: /* Return name of file BUFFER is visiting, or nil if none.
 No argument or nil as argument means use the current buffer.  */)
@@ -1647,6 +1665,7 @@ DEFUN ("rename-buffer", Frename_buffer, Srename_buffer, 1, 2,
 {
   register Lisp_Object tem, buf;
   Lisp_Object requestedname = newname;
+  Lisp_Object oldname = BVAR (current_buffer, name);
 
   CHECK_STRING (newname);
 
@@ -1661,14 +1680,14 @@ 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);
+	return oldname;
       if (!NILP (unique))
-	newname = Fgenerate_new_buffer_name (newname,
-	                                     BVAR (current_buffer, name));
+	newname = Fgenerate_new_buffer_name (newname, oldname);
       else
 	error ("Buffer name `%s' is in use", SDATA (newname));
     }
 
+  bset_lastname (current_buffer, oldname);
   bset_name (current_buffer, newname);
 
   /* Catch redisplay's attention.  Unless we do this, the mode lines for
@@ -2081,6 +2100,7 @@ DEFUN ("kill-buffer", Fkill_buffer, Skill_buffer, 0, 1, "bKill buffer: ",
      This gets rid of them for certain.  */
   reset_buffer_local_variables (b, 1);
 
+  bset_lastname (b, b->name_);
   bset_name (b, Qnil);
 
   block_input ();
@@ -4647,6 +4667,7 @@ init_buffer_once (void)
 
   /* 0 means not a lisp var, -1 means always local, else mask.  */
   memset (&buffer_local_flags, 0, sizeof buffer_local_flags);
+  bset_lastname (&buffer_local_flags, make_fixnum (-1));
   bset_filename (&buffer_local_flags, make_fixnum (-1));
   bset_directory (&buffer_local_flags, make_fixnum (-1));
   bset_backed_up (&buffer_local_flags, make_fixnum (-1));
@@ -6030,6 +6051,7 @@ Functions (implicitly) running this hook are `get-buffer-create',
   defsubr (&Smake_indirect_buffer);
   defsubr (&Sgenerate_new_buffer_name);
   defsubr (&Sbuffer_name);
+  defsubr (&Sbuffer_last_name);
   defsubr (&Sbuffer_file_name);
   defsubr (&Sbuffer_base_buffer);
   defsubr (&Sbuffer_local_value);
diff --git a/src/buffer.h b/src/buffer.h
index 80edfdcbc22..7e009397f4d 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -309,6 +309,12 @@ #define BVAR(buf, field) ((buf)->field ## _)
   /* The name of this buffer.  */
   Lisp_Object name_;
 
+  /* The last name of this buffer.  Initially nil, for a renamed live
+     buffer the name the buffer had before the last Frename_buffer
+     changed it, for a dead buffer the last name the buffer had before
+     it was killed.  */
+  Lisp_Object lastname_;
+
   /* The name of the file visited in this buffer, or nil.  */
   Lisp_Object filename_;