emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Stop frames stealing eachothers' minibuffers!


From: Alan Mackenzie
Subject: Re: Stop frames stealing eachothers' minibuffers!
Date: Sun, 7 Feb 2021 20:26:58 +0000

Hello jakanakaevangeli.

Thank you indeed for all the testing you are doing.  It is saving me a
lot of hassle in the future.

On Sun, Feb 07, 2021 at 17:44:17 +0100, jakanakaevangeli wrote:

[ .... ]

> > Could I ask you please to try out the following patch, which should be
> > applied on top of yesterday's patch:

> I tried it and everything works as expected, if we use C-g. The only
> minor thing I noticed is with abort-recursive-edit (C-]). When executed
> from a normal buffer, it does what its doc-string suggests. But when
> executed from a non-innermost minibuffer, it exits multiple recursive
> edits, just like abort-minibuffers. (This isn't surprising since it
> calls Fthrow (Qexit, Qt) just like abort-minibuffers, only without
> asking yes_or_no_p first.)

This is not good.

> This might actually be intended behaviour, depending on how you
> interpret "this minibuffer input" from abort-recursive-edit's
> doc-string.

I spent some time boring into the doc string and the description in the
Elisp manual.  The only conclusion I could come to was that C-] is meant
to abort EXACTLY ONE level.

So I have tweaked the C sources once more and come up with the following
patch.  It should apply to the Emacs state after yesterday's patch.
Please remove the patch from earlier today before you try to apply the
new patch.  Thanks!



--- src/eval.c~ 2021-02-06 12:44:35.798096526 +0000
+++ src/eval.c  2021-02-07 20:07:13.793787769 +0000
@@ -1163,16 +1163,17 @@
    FUNC should return a Lisp_Object.
    This is how catches are done from within C code.  */
 
+/* MINIBUFFER_QUIT_LEVEL is to handle quitting from nested minibuffers by
+   throwing t to tag `exit'.
+   Value -1 means there is no (throw 'exit t) in progress;
+   0 means the `throw' wasn't done from an active minibuffer;
+   N > 0 means the `throw' was done from the minibuffer at level N.  */
+EMACS_INT minibuffer_quit_level = -1;
+
 Lisp_Object
 internal_catch (Lisp_Object tag,
                Lisp_Object (*func) (Lisp_Object), Lisp_Object arg)
 {
-  /* MINIBUFFER_QUIT_LEVEL is to handle quitting from nested minibuffers by
-     throwing t to tag `exit'.
-     Value -1 means there is no (throw 'exit t) in progress;
-     0 means the `throw' wasn't done from an active minibuffer;
-     N > 0 means the `throw' was done from the minibuffer at level N.  */
-  static EMACS_INT minibuffer_quit_level = -1;
   /* This structure is made part of the chain `catchlist'.  */
   struct handler *c = push_handler (tag, CATCHER);
 
@@ -1192,16 +1193,14 @@
       Lisp_Object val = handlerlist->val;
       clobbered_eassert (handlerlist == c);
       handlerlist = handlerlist->next;
-      if (EQ (tag, Qexit) && EQ (val, Qt))
+      if (EQ (tag, Qexit) && EQ (val, Qt) && minibuffer_quit_level > 0)
        /* If we've thrown t to tag `exit' from within a minibuffer, we
           exit all minibuffers more deeply nested than the current
           one.  */
        {
-          if (minibuffer_quit_level == -1)
-            minibuffer_quit_level = this_minibuffer_depth (Qnil);
-          if (minibuf_level > minibuffer_quit_level
-              || command_loop_level
-              > minibuf_c_loop_level (minibuffer_quit_level))
+          /* MINIBUFFER_QUIT_LEVEL == 0 -> not in minibuffer. */
+         if (minibuf_level > minibuffer_quit_level
+             && !NILP (Fminibuffer_innermost_command_loop_p (Qnil)))
             Fthrow (Qexit, Qt);
          else
            minibuffer_quit_level = -1;
--- src/minibuf.c~      2021-02-06 15:04:58.878632379 +0000
+++ src/minibuf.c       2021-02-07 20:06:34.249789948 +0000
@@ -437,12 +437,17 @@
 
   if (!minibuf_depth)
     error ("Not in a minibuffer");
+  if (NILP (Fminibuffer_innermost_command_loop_p (Qnil)))
+    error ("Not in most nested command loop");
   if (minibuf_depth < minibuf_level)
     {
       array[0] = fmt;
       array[1] = make_fixnum (minibuf_level - minibuf_depth + 1);
       if (!NILP (Fyes_or_no_p (Fformat (2, array))))
-       Fthrow (Qexit, Qt);
+       {
+         minibuffer_quit_level = minibuf_depth;
+         Fthrow (Qexit, Qt);
+       }
     }
   else
     Fthrow (Qexit, Qt);
--- src/lisp.h~ 2021-02-06 12:45:15.205094355 +0000
+++ src/lisp.h  2021-02-07 20:07:45.816786005 +0000
@@ -4090,6 +4090,7 @@
 }
 
 /* Defined in eval.c.  */
+extern EMACS_INT minibuffer_quit_level;
 extern Lisp_Object Vautoload_queue;
 extern Lisp_Object Vrun_hooks;
 extern Lisp_Object Vsignaling_function;


-- 
Alan Mackenzie (Nuremberg, Germany).



reply via email to

[Prev in Thread] Current Thread [Next in Thread]