From fd5be298c67157822b35cd0231c65691c48dc29e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miha=20Rihtar=C5=A1i=C4=8D?= Date: Sat, 31 Jul 2021 13:44:21 +0200 Subject: [PATCH] Refactor minibuffer aborting * lisp/minibuffer.el (minibuffer-quit-recursive-edit): New optional argument to specify how many levels of recursion to quit. * src/minibuf.c (Fabort_minibuffers): Use minibuffer-quit-recursive-edit to quit multiple levels of minibuffer recursion. * src/eval.c (internal_catch): Remove special handling of 'exit tag. --- lisp/minibuffer.el | 20 ++++++++++++-------- src/eval.c | 22 ---------------------- src/lisp.h | 1 - src/minibuf.c | 9 +++++++-- 4 files changed, 19 insertions(+), 33 deletions(-) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 9668e7c732..b5c0054a3c 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2349,14 +2349,18 @@ minibuffer-restore-windows (add-hook 'minibuffer-exit-hook 'minibuffer-restore-windows) -(defun minibuffer-quit-recursive-edit () - "Quit the command that requested this recursive edit without error. -Like `abort-recursive-edit' without aborting keyboard macro -execution." - ;; See Info node `(elisp)Recursive Editing' for an explanation of - ;; throwing a function to `exit'. - (throw 'exit (lambda () - (signal 'minibuffer-quit nil)))) +(defun minibuffer-quit-recursive-edit (&optional levels) + "Quit the command that requested this recursive edit or minibuffer input. +Do so without terminating keyboard macro recording or execution. +LEVELS specifies the number of nested recursive edits to quit. +If nil, it defaults to 1." + (unless levels + (setq levels 1)) + (if (> levels 1) + ;; See Info node `(elisp)Recursive Editing' for an explanation + ;; of throwing a function to `exit'. + (throw 'exit (lambda () (minibuffer-quit-recursive-edit (1- levels)))) + (throw 'exit (lambda () (signal 'minibuffer-quit nil))))) (defun self-insert-and-exit () "Terminate minibuffer input." diff --git a/src/eval.c b/src/eval.c index 48104bd0f4..76fe671b6d 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1174,14 +1174,6 @@ #define clobbered_eassert(E) verify (sizeof (E) != 0) 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'. - 0 means there is no (throw 'exit t) in progress, or it wasn't from - a minibuffer which isn't the most nested; - N > 0 means the `throw' was done from the minibuffer at level N which - wasn't the most nested. */ -EMACS_INT minibuffer_quit_level = 0; - Lisp_Object internal_catch (Lisp_Object tag, Lisp_Object (*func) (Lisp_Object), Lisp_Object arg) @@ -1189,9 +1181,6 @@ internal_catch (Lisp_Object tag, /* This structure is made part of the chain `catchlist'. */ struct handler *c = push_handler (tag, CATCHER); - if (EQ (tag, Qexit)) - minibuffer_quit_level = 0; - /* Call FUNC. */ if (! sys_setjmp (c->jmp)) { @@ -1205,17 +1194,6 @@ internal_catch (Lisp_Object tag, Lisp_Object val = handlerlist->val; clobbered_eassert (handlerlist == c); handlerlist = handlerlist->next; - 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 (minibuf_level > minibuffer_quit_level - && !NILP (Fminibuffer_innermost_command_loop_p (Qnil))) - Fthrow (Qexit, Qt); - else - minibuffer_quit_level = 0; - } return val; } } diff --git a/src/lisp.h b/src/lisp.h index 7bfc69b647..4e6298a101 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4113,7 +4113,6 @@ intern_c_string (const char *str) } /* 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; diff --git a/src/minibuf.c b/src/minibuf.c index 0e7baf30dc..a4219d2a63 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -491,8 +491,13 @@ DEFUN ("abort-minibuffers", Fabort_minibuffers, Sabort_minibuffers, 0, 0, "", array[1] = make_fixnum (minibuf_level - minibuf_depth + 1); if (!NILP (Fyes_or_no_p (Fformat (2, array)))) { - minibuffer_quit_level = minibuf_depth; - Fthrow (Qexit, Qt); + /* Due to the above check, the current minibuffer is in the + most nested command loop, which means that we don't have + to abort any extra non-minibuffer recursive edits. Thus, + the number of recursive edits we have to abort equals the + number of minibuffers we have to abort. */ + CALLN (Ffuncall, intern ("minibuffer-quit-recursive-edit"), + array[1]); } } else -- 2.33.0