From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: miha--- via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#49700: 27.2; [PATCH] Refactor minibuffer aborting Date: Fri, 17 Sep 2021 23:47:35 +0200 Message-ID: <87pmt6ho20.fsf@miha-pc> References: <87pmvaar0a.fsf@miha-pc> <87im0qrmxe.fsf@miha-pc> <87eeb6b3av.fsf@miha-pc> Reply-To: Mime-Version: 1.0 Content-Type: multipart/signed; boundary="==-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="37637"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Eli Zaretskii , 49700@debbugs.gnu.org To: Alan Mackenzie Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Fri Sep 17 23:45:19 2021 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mRLfb-0009Yf-8x for geb-bug-gnu-emacs@m.gmane-mx.org; Fri, 17 Sep 2021 23:45:19 +0200 Original-Received: from localhost ([::1]:48952 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mRLfZ-0001gO-Qg for geb-bug-gnu-emacs@m.gmane-mx.org; Fri, 17 Sep 2021 17:45:17 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:46890) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mRLfK-0001gE-HO for bug-gnu-emacs@gnu.org; Fri, 17 Sep 2021 17:45:02 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:49870) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mRLfK-000544-AA for bug-gnu-emacs@gnu.org; Fri, 17 Sep 2021 17:45:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1mRLfK-0005ym-7f for bug-gnu-emacs@gnu.org; Fri, 17 Sep 2021 17:45:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Fri, 17 Sep 2021 21:45:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 49700 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 49700-submit@debbugs.gnu.org id=B49700.163191506822925 (code B ref 49700); Fri, 17 Sep 2021 21:45:02 +0000 Original-Received: (at 49700) by debbugs.gnu.org; 17 Sep 2021 21:44:28 +0000 Original-Received: from localhost ([127.0.0.1]:33183 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mRLel-0005xg-G6 for submit@debbugs.gnu.org; Fri, 17 Sep 2021 17:44:28 -0400 Original-Received: from kamnitnik.top ([209.250.245.214]:57770) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mRLeg-0005xV-Lb for 49700@debbugs.gnu.org; Fri, 17 Sep 2021 17:44:26 -0400 Original-Received: from localhost (unknown [IPv6:2a00:ee2:e04:9300:e18:5d33:4bd1:d3a4]) by kamnitnik.top (Postfix) with ESMTPSA id 35A489C5E5; Fri, 17 Sep 2021 21:44:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kamnitnik.top; s=mail; t=1631915061; bh=yklCj4q6ZrKn+bX+aN18Qdvp2f6SqFY7gTtZpTbFwr8=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=ju1D1EtS3rI8/PvE9Pzj6OY1paGsZrnO4LAQzr+fqoAnyJRmZQKishoi9cTypiBIM 02vgAhuJM+6L/F6Yn9njuXwsmtZR9tD3SBRgdRCyk+n6St02IHgS1l6lUC+aIHXcPy I5xn38mOo08rOpERWmwFUkjL0XH6UM4MIkbZuKUyKbC1OjVoBJF5a9JAREjv0mFxpS mwdAVQtXgch672EqdNnky4AOkq1BuRqmZ3rhOGlqf7vWdLxwAtYOaHogr7Yih616c5 CwH2KzvbuXu/5yuLOq98tXjC3oJ/HJV97FOyc+UDfmNyp4sxn3nMHJiY0zB7AOaum+ UA0UFA/g3chjg== In-Reply-To: <87eeb6b3av.fsf@miha-pc> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:214588 Archived-At: --==-=-= Content-Type: multipart/mixed; boundary="=-=-=" --=-=-= Content-Type: text/plain miha--- via "Bug reports for GNU Emacs, the Swiss army knife of text editors" writes: > True, my code would indeed be incorrect if the number of minibuffer > levels to be aborted weren't to match the number of recursive edits. > However, in such cases, my code isn't reached because an error is > signaled that the current minibuffer isn't in the innermost command > loop. > > Sorry for not clarifying this earlier. Would it would be enough to > include the following comment in the code?: > > /* 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. > */ > > [...] > Perhaps the following adjustment to the doc string could be considered > (to be applied on top of the latest patch). It copies the beginning of > abort-recursive-edit's doc string and removes the link to it. > > [...] I realized that my proposals are kind of scattered over multiple e-mails in this thread. So I'm sending them again, attached in this mail as complete patches that apply to current master. The first patch refactors abort-minibuffers (and improves minibuffer-quit-recursive-edit's doc string as requested). The second patch improves documentation of recursive editing. Best regards. --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=0001-Refactor-minibuffer-aborting.patch Content-Transfer-Encoding: quoted-printable From=20fd5be298c67157822b35cd0231c65691c48dc29e Mon Sep 17 00:00:00 2001 From: =3D?UTF-8?q?Miha=3D20Rihtar=3DC5=3DA1i=3DC4=3D8D?=3D 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. =2D-- 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 =2D-- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2349,14 +2349,18 @@ minibuffer-restore-windows =20 (add-hook 'minibuffer-exit-hook 'minibuffer-restore-windows) =20 =2D(defun minibuffer-quit-recursive-edit () =2D "Quit the command that requested this recursive edit without error. =2DLike `abort-recursive-edit' without aborting keyboard macro =2Dexecution." =2D ;; See Info node `(elisp)Recursive Editing' for an explanation of =2D ;; throwing a function to `exit'. =2D (throw 'exit (lambda () =2D (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))))) =20 (defun self-insert-and-exit () "Terminate minibuffer input." diff --git a/src/eval.c b/src/eval.c index 48104bd0f4..76fe671b6d 100644 =2D-- a/src/eval.c +++ b/src/eval.c @@ -1174,14 +1174,6 @@ #define clobbered_eassert(E) verify (sizeof (E) !=3D= 0) FUNC should return a Lisp_Object. This is how catches are done from within C code. */ =20 =2D/* MINIBUFFER_QUIT_LEVEL is to handle quitting from nested minibuffers by =2D throwing t to tag `exit'. =2D 0 means there is no (throw 'exit t) in progress, or it wasn't from =2D a minibuffer which isn't the most nested; =2D N > 0 means the `throw' was done from the minibuffer at level N which =2D wasn't the most nested. */ =2DEMACS_INT minibuffer_quit_level =3D 0; =2D 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 =3D push_handler (tag, CATCHER); =20 =2D if (EQ (tag, Qexit)) =2D minibuffer_quit_level =3D 0; =2D /* Call FUNC. */ if (! sys_setjmp (c->jmp)) { @@ -1205,17 +1194,6 @@ internal_catch (Lisp_Object tag, Lisp_Object val =3D handlerlist->val; clobbered_eassert (handlerlist =3D=3D c); handlerlist =3D handlerlist->next; =2D if (EQ (tag, Qexit) && EQ (val, Qt) && minibuffer_quit_level > 0) =2D /* If we've thrown t to tag `exit' from within a minibuffer, we =2D exit all minibuffers more deeply nested than the current =2D one. */ =2D { =2D if (minibuf_level > minibuffer_quit_level =2D && !NILP (Fminibuffer_innermost_command_loop_p (Qnil))) =2D Fthrow (Qexit, Qt); =2D else =2D minibuffer_quit_level =3D 0; =2D } return val; } } diff --git a/src/lisp.h b/src/lisp.h index 7bfc69b647..4e6298a101 100644 =2D-- a/src/lisp.h +++ b/src/lisp.h @@ -4113,7 +4113,6 @@ intern_c_string (const char *str) } =20 /* Defined in eval.c. */ =2Dextern 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 =2D-- a/src/minibuf.c +++ b/src/minibuf.c @@ -491,8 +491,13 @@ DEFUN ("abort-minibuffers", Fabort_minibuffers, Sabort= _minibuffers, 0, 0, "", array[1] =3D make_fixnum (minibuf_level - minibuf_depth + 1); if (!NILP (Fyes_or_no_p (Fformat (2, array)))) { =2D minibuffer_quit_level =3D minibuf_depth; =2D 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 =2D-=20 2.33.0 --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=0001-Improve-documentation-of-exiting-recursive-editing.patch Content-Transfer-Encoding: quoted-printable From=20387baa2b42e8220b0aac36f6f23ec3547ad0811e Mon Sep 17 00:00:00 2001 From: =3D?UTF-8?q?Miha=3D20Rihtar=3DC5=3DA1i=3DC4=3D8D?=3D Date: Sun, 1 Aug 2021 02:41:37 +0200 Subject: [PATCH] Improve documentation of exiting recursive editing * doc/lispref/commands.texi (Recursive Editing): Mention what happens when throwing a string or any other value to 'exit. * src/keyboard.c (Frecursive_edit): Document throwing a function to 'exit. =2D-- doc/lispref/commands.texi | 22 ++++++++++++---------- src/keyboard.c | 18 ++++++++++++++---- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index ddd74d1245..3425880fec 100644 =2D-- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -3585,17 +3585,19 @@ Recursive Editing @cindex exit recursive editing @cindex aborting To invoke a recursive editing level, call the function =2D@code{recursive-edit}. This function contains the command loop; it also =2Dcontains a call to @code{catch} with tag @code{exit}, which makes it =2Dpossible to exit the recursive editing level by throwing to @code{exit} =2D(@pxref{Catch and Throw}). If you throw a @code{nil} value, then =2D@code{recursive-edit} returns normally to the function that called it. =2DThe command @kbd{C-M-c} (@code{exit-recursive-edit}) does this. =2DThrowing a @code{t} value causes @code{recursive-edit} to quit, so that =2Dcontrol returns to the command loop one level up. This is called =2D@dfn{aborting}, and is done by @kbd{C-]} (@code{abort-recursive-edit}). =2DYou can also throw a function value. In that case, +@code{recursive-edit}. This function contains the command loop; it +also contains a call to @code{catch} with tag @code{exit}, which makes +it possible to exit the recursive editing level by throwing to +@code{exit} (@pxref{Catch and Throw}). Throwing a @code{t} value +causes @code{recursive-edit} to quit, so that control returns to the +command loop one level up. This is called @dfn{aborting}, and is done +by @kbd{C-]} (@code{abort-recursive-edit}). Similarly, you can throw +a string value to make @code{recursive-edit} signal an error, printing +this string as the message. If you throw a function, @code{recursive-edit} will call it without arguments before returning. +Throwing any other value, will make @code{recursive-edit} return +normally to the function that called it. The command @kbd{C-M-c} +(@code{exit-recursive-edit}) does this. =20 Most applications should not use recursive editing, except as part of using the minibuffer. Usually it is more convenient for the user if you diff --git a/src/keyboard.c b/src/keyboard.c index 63bf29a948..2d97429ade 100644 =2D-- a/src/keyboard.c +++ b/src/keyboard.c @@ -753,10 +753,20 @@ DEFUN ("recursive-edit", Frecursive_edit, Srecursive_= edit, 0, 0, "", doc: /* Invoke the editor command loop recursively. To get out of the recursive edit, a command can throw to `exit' -- for instance (throw \\=3D'exit nil). =2DIf you throw a value other than t, `recursive-edit' returns normally =2Dto the function that called it. Throwing a t value causes =2D`recursive-edit' to quit, so that control returns to the command loop =2Done level up. + +The following values can be thrown to 'exit: + +- t causes `recursive-edit' to quit, so that control returns to the + command loop one level up. + +- A string causes `recursive-edit' to signal an error, printing this + string as the message. + +- A function causes `recursive-edit' to call this function without + arguments before returning normally. + +- Any other value causes `recursive-edit' to return normally to the + function that called it. =20 This function is called by the editor initialization to begin editing. */) (void) =2D-=20 2.33.0 --=-=-=-- --==-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQJHBAEBCAAxFiEEmxVnesoT5rQXvVXnswkaGpIVmT8FAmFFDPcTHG1paGFAa2Ft bml0bmlrLnRvcAAKCRCzCRoakhWZP0zxEAC/f7Jaa4qLRqHMTVr1+yV59GPM1mBg asm0H/1DgPGRofqMX3fsR+m5PrJcF1PkAyx2gAuD1QA6E6T0XFKcz/o8nFKd/mwo MUAcpIkJbS5IBmdjzP8vhlHVCaPj23C15j7MLWJjCJwcNKZZeTQtNIdtuZuBFqnB iRZ8s8VugEkn1dxbLd+gcpR8+JAcEt04cCGEtzS86m/K/HL/j/2glp94fZb80Xen pZkHyN519kXY+q9mhFIUb4fp682PbReWybchjgtZGlbaKsljQw17MCva9f8tUnD3 gSbTOKWrwgNjuk5Mwr+uG5P9vfoaQ76bNKcNgbuw+FI/VXqVcu/lJQkIxwPAYnAe BF75E7PT8Btlj5rQlEAF8Z16BbFIGYOqHGHz4RDNJwEI0ocDrRrM0oMHi71yCa6I 4pu+iGRbYpOuRdpJhHgg44MQlWXMYu/Ttf82wLxPFSuoC+uG45iEwpmGmaTFa5MB 8lag61nTSt09FEE3oXLQNj685IEktpzZavRej0VAyzqaFWdvJlV7EUDjvwNKtJMg EoFez0XCmYFP2iGfThHcgX3qoXNffajp9NaWHEQ14r6w/WMeQCShpYpaKi+zBbvS M0qgRyTGLMS6bLCHC61/pLkVMhCEOoMyUkZm1DnWCRXtoyn0Yc0XqmvHrgoh3tIC 2z9pnZTTtTpH3A== =Wrzb -----END PGP SIGNATURE----- --==-=-=--