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#48603: 27.2; [PATCH] Quit minibuffers without aborting kmacros Date: Tue, 25 May 2021 23:34:11 +0200 Message-ID: <86r1hu4hws.fsf@miha-pc> References: <86eedx7c0u.fsf@miha-pc> <877djmegh8.fsf@gnus.org> 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="36202"; mail-complaints-to="usenet@ciao.gmane.io" Cc: 48603@debbugs.gnu.org To: Lars Ingebrigtsen Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue May 25 23:29:12 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 1llebv-0009AC-VD for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 25 May 2021 23:29:12 +0200 Original-Received: from localhost ([::1]:47314 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1llebu-0007Gw-W5 for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 25 May 2021 17:29:11 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:35614) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1llebn-0007Fm-Jb for bug-gnu-emacs@gnu.org; Tue, 25 May 2021 17:29:03 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:35650) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1llebm-0000m9-0i for bug-gnu-emacs@gnu.org; Tue, 25 May 2021 17:29:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1llebl-0003Et-Tw for bug-gnu-emacs@gnu.org; Tue, 25 May 2021 17:29:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 25 May 2021 21:29:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 48603 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 48603-submit@debbugs.gnu.org id=B48603.162197813612440 (code B ref 48603); Tue, 25 May 2021 21:29:01 +0000 Original-Received: (at 48603) by debbugs.gnu.org; 25 May 2021 21:28:56 +0000 Original-Received: from localhost ([127.0.0.1]:47196 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1llebf-0003EZ-AJ for submit@debbugs.gnu.org; Tue, 25 May 2021 17:28:56 -0400 Original-Received: from kamnitnik.top ([209.250.245.214]:34882 helo=mail.kamnitnik.top) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1llebb-0003EO-NH for 48603@debbugs.gnu.org; Tue, 25 May 2021 17:28:54 -0400 Original-Received: from localhost (unknown [IPv6:2a00:ee2:e04:9300:b7eb:7ae7:cc56:e0da]) by mail.kamnitnik.top (Postfix) with ESMTPSA id 73ED3BBB83; Tue, 25 May 2021 21:28:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kamnitnik.top; s=mail; t=1621978129; bh=Gm+FNaS7eE3DR6NdgoeVxFu8YvgxgItdnMYiPIZFR/o=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=eXWaph0VD4Bw4wFlQetUd+cfE0zxi6wc/T+tRYO6qxTTio26BioZ9o9Y4IOW986oM y/mWo4zh/a3hRJASOavqldTjLTcJyK3cFnQFZ8V12YCl8ZdUhOd2TZOCRAmQbJlY8B nRNLPV4zLpwowpX099efo3MwXBMjnxvsA17skty0h1n59h38en0O3RZm++DyTXOLV6 VYAkGBpGf3hl+RZoSaLYb4RTYmKx0iU37noX/h9f/pFN/wpn1EOHgm9QEvfxUIhdo3 epb93Za+I81DVBMkJKUe5ZKs4vv6ItT5hbUJ/kF1bGB6HLW1TRrNmyEGRs215iGe3o 73U3wPhk708SA== In-Reply-To: <877djmegh8.fsf@gnus.org> 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:207267 Archived-At: --==-=-= Content-Type: multipart/mixed; boundary="=-=-=" --=-=-= Content-Type: text/plain Lars Ingebrigtsen writes: > miha@kamnitnik.top writes: > >> Rationale: a user wants to copy a command from command history without >> executing it. Or user wants to complete a file name in C-x C-f and copy >> it without finding the file. I believe this should be possible in >> keyboard macros. > > `C-g' is part of how one normally operates `M-x' (etc.) in some > circumstances, so it might make sense to have a special quit symbol for > that; yes. > > Does anybody else have an opinion here? One alternative to a new quit error symbol would be to introduce a new variable `kmacro-dont-end-on-error'. One would then set it to non-nil before signaling a quit (or any error) and command loop would set it back to nil after handling the error without aborting kmacro definition. What do you think? >> * src/data.c (syms_of_data): New error symbol `lite-quit' > > But it should be called something more descriptive, like > `minibuffer-quit'. Good idea, attaching a revised patch (which also adds two NEWS entries.) --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=0001-Quit-minibuffers-without-aborting-kmacros.patch Content-Transfer-Encoding: quoted-printable From=20289f4d6cae45c6846d9ef4c245b1635056a2f288 Mon Sep 17 00:00:00 2001 From: =3D?UTF-8?q?Miha=3D20Rihtar=3DC5=3DA1i=3DC4=3D8D?=3D Date: Sun, 23 May 2021 16:08:43 +0200 Subject: [PATCH] Quit minibuffers without aborting kmacros * src/data.c (syms_of_data): New error symbol `minibuffer-quit' * src/keyboard.c (recursive_edit_1): Implement throwing of function values to `exit`. In that case, the function will be called without arguments before returning from the command loop. (cmd_error): (Fcommand_error_default_function): Do not abort keyboard macro execution if minibuffer-quit is signaled. (command_loop_2): New argument HANDLERS. * src/macros.c (Fexecute_kbd_macro): Use command_loop_2 instead of command_loop_1. * doc/lispref/commands.texi (Quitting): Document `minibuffer-quit' (Recursive Editing): Document throwing of function values to `exit'. * doc/lispref/errors.texi (Standard Errors): Document `minibuffer-quit' * lisp/minibuffer.el (minibuffer-quit-recursive-edit): New function. * src/minibuf.c (Fabort_minibuffers): Use it. * lisp/simple.el (minibuffer-error-function): Do not abort keyboard macro execution if is minibuffer-quit is signaled. =2D-- doc/lispref/commands.texi | 14 +++++++++--- doc/lispref/errors.texi | 9 ++++++-- etc/NEWS | 9 ++++++++ lisp/minibuffer.el | 9 ++++++++ lisp/simple.el | 6 ++++-- src/data.c | 2 ++ src/keyboard.c | 45 ++++++++++++++++++++++++++++----------- src/lisp.h | 2 +- src/macros.c | 2 +- src/minibuf.c | 2 +- 10 files changed, 78 insertions(+), 22 deletions(-) diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 8199ece110..164e1ad630 100644 =2D-- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -3378,6 +3378,12 @@ Quitting in @ref{Errors}.) @end deffn =20 + To quit without aborting keyboard macro definition or execution, you +can signal the @code{minibuffer-quit} condition. This has almost the +same effect as the @code{quit} condition except that the error handling +in the command loop handles it without breaking keyboard macro +definition or execution. + You can specify a character other than @kbd{C-g} to use for quitting. See the function @code{set-input-mode} in @ref{Input Modes}. =20 @@ -3562,12 +3568,14 @@ Recursive Editing @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} =2D(@pxref{Catch and Throw}). If you throw a value other than @code{t}, =2Dthen @code{recursive-edit} returns normally to the function that called =2Dit. The command @kbd{C-M-c} (@code{exit-recursive-edit}) does this. +(@pxref{Catch and Throw}). If you throw a @code{nil} value, then +@code{recursive-edit} returns normally to the function that called it. +The command @kbd{C-M-c} (@code{exit-recursive-edit}) does this. 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}). +You can also throw a function value. In that case, +@code{recursive-edit} will call it without arguments before returning. =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/doc/lispref/errors.texi b/doc/lispref/errors.texi index fb393b951f..f848218e26 100644 =2D-- a/doc/lispref/errors.texi +++ b/doc/lispref/errors.texi @@ -20,8 +20,9 @@ Standard Errors we do not say here that a certain error symbol has additional error conditions, that means it has none. =20 =2D As a special exception, the error symbol @code{quit} does not have the =2Dcondition @code{error}, because quitting is not considered an error. + As a special exception, the error symbols @code{quit} and +@code{minibuffer-quit} don't have the condition @code{error}, because +quitting is not considered an error. =20 Most of these error symbols are defined in C (mainly @file{data.c}), but some are defined in Lisp. For example, the file @file{userlock.el} @@ -40,6 +41,10 @@ Standard Errors @item quit The message is @samp{Quit}. @xref{Quitting}. =20 +@item minibuffer-quit +The message is @samp{Quit}. This is a subcategory of @code{quit}. +@xref{Quitting}. + @item args-out-of-range The message is @samp{Args out of range}. This happens when trying to access an element beyond the range of a sequence, buffer, or other diff --git a/etc/NEWS b/etc/NEWS index ea74dfe217..1bfd87dcb7 100644 =2D-- a/etc/NEWS +++ b/etc/NEWS @@ -2705,6 +2705,15 @@ the Emacs Lisp reference manual for background. * Lisp Changes in Emacs 28.1 =20 ++++ +** A function can now be thrown to the 'exit' label in addition to t or ni= l. +The command loop will call it with zero arguments before returning. + ++++ +** New error symbol 'minibuffer-quit'. +Signaling it has almost the same effect as 'quit' except that it +doesn't cause keyboard macro termination. + --- ** Emacs now attempts to test for high-rate subprocess output more fairly. When several subprocesses produce output simultaneously at high rate, diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index ec21b7b93b..400dff058c 100644 =2D-- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2318,6 +2318,15 @@ exit-minibuffer (setq deactivate-mark nil) (throw 'exit nil)) =20 +(defun minibuffer-quit-recursive-edit () + "Quit the command that requested this recursive edit wihtout error. +Like `abort-recursive-edit' wihtout 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 self-insert-and-exit () "Terminate minibuffer input." (interactive) diff --git a/lisp/simple.el b/lisp/simple.el index 8849919360..4546bbde2a 100644 =2D-- a/lisp/simple.el +++ b/lisp/simple.el @@ -2855,8 +2855,10 @@ minibuffer-error-function The same as `command-error-default-function' but display error messages at the end of the minibuffer using `minibuffer-message' to not obscure the minibuffer contents." =2D (discard-input) =2D (ding) + (if (memq 'minibuffer-quit (get (car data) 'error-conditions)) + (ding t) + (discard-input) + (ding)) (let ((string (error-message-string data))) ;; If we know from where the error was signaled, show it in ;; *Messages*. diff --git a/src/data.c b/src/data.c index d547f5da5e..903d171d8b 100644 =2D-- a/src/data.c +++ b/src/data.c @@ -3899,6 +3899,7 @@ syms_of_data (void) DEFSYM (Qerror, "error"); DEFSYM (Quser_error, "user-error"); DEFSYM (Qquit, "quit"); + DEFSYM (Qminibuffer_quit, "minibuffer-quit"); DEFSYM (Qwrong_length_argument, "wrong-length-argument"); DEFSYM (Qwrong_type_argument, "wrong-type-argument"); DEFSYM (Qargs_out_of_range, "args-out-of-range"); @@ -3971,6 +3972,7 @@ #define PUT_ERROR(sym, tail, msg) \ Fput (sym, Qerror_message, build_pure_c_string (msg)) =20 PUT_ERROR (Qquit, Qnil, "Quit"); + PUT_ERROR (Qminibuffer_quit, pure_cons (Qquit, Qnil), "Quit"); =20 PUT_ERROR (Quser_error, error_tail, ""); PUT_ERROR (Qwrong_length_argument, error_tail, "Wrong length argument"); diff --git a/src/keyboard.c b/src/keyboard.c index 47b5e59024..0ac6d24b0a 100644 =2D-- a/src/keyboard.c +++ b/src/keyboard.c @@ -725,6 +725,9 @@ recursive_edit_1 (void) if (STRINGP (val)) xsignal1 (Qerror, val); =20 + if (FUNCTIONP (val)) + call0 (val); + return unbind_to (count, Qnil); } =20 @@ -921,6 +924,7 @@ restore_kboard_configuration (int was_locked) cmd_error (Lisp_Object data) { Lisp_Object old_level, old_length; + Lisp_Object conditions; char macroerror[sizeof "After..kbd macro iterations: " + INT_STRLEN_BOUND (EMACS_INT)]; =20 @@ -940,10 +944,15 @@ cmd_error (Lisp_Object data) else *macroerror =3D 0; =20 + conditions =3D Fget (XCAR (data), Qerror_conditions); + if (NILP (Fmemq (Qminibuffer_quit, conditions))) + { + Vexecuting_kbd_macro =3D Qnil; + executing_kbd_macro =3D Qnil; + } + Vstandard_output =3D Qt; Vstandard_input =3D Qt; =2D Vexecuting_kbd_macro =3D Qnil; =2D executing_kbd_macro =3D Qnil; kset_prefix_arg (current_kboard, Qnil); kset_last_prefix_arg (current_kboard, Qnil); cancel_echoing (); @@ -998,6 +1007,7 @@ DEFUN ("command-error-default-function", Fcommand_erro= r_default_function, (Lisp_Object data, Lisp_Object context, Lisp_Object signal) { struct frame *sf =3D SELECTED_FRAME (); + Lisp_Object conditions; =20 CHECK_STRING (context); =20 @@ -1024,17 +1034,27 @@ DEFUN ("command-error-default-function", Fcommand_e= rror_default_function, } else { + conditions =3D Fget (XCAR (data), Qerror_conditions); + clear_message (1, 0); =2D Fdiscard_input (); message_log_maybe_newline (); =2D bitch_at_user (); + + if (!NILP (Fmemq (Qminibuffer_quit, conditions))) + { + Fding (Qt); + } + else + { + Fdiscard_input (); + bitch_at_user (); + } =20 print_error_message (data, Qt, SSDATA (context), signal); } return Qnil; } =20 =2Dstatic Lisp_Object command_loop_2 (Lisp_Object); +static Lisp_Object command_loop_1 (void); static Lisp_Object top_level_1 (Lisp_Object); =20 /* Entry to editor-command-loop. @@ -1062,7 +1082,7 @@ command_loop (void) if (command_loop_level > 0 || minibuf_level > 0) { Lisp_Object val; =2D val =3D internal_catch (Qexit, command_loop_2, Qnil); + val =3D internal_catch (Qexit, command_loop_2, Qerror); executing_kbd_macro =3D Qnil; return val; } @@ -1070,7 +1090,7 @@ command_loop (void) while (1) { internal_catch (Qtop_level, top_level_1, Qnil); =2D internal_catch (Qtop_level, command_loop_2, Qnil); + internal_catch (Qtop_level, command_loop_2, Qerror); executing_kbd_macro =3D Qnil; =20 /* End of file in -batch run causes exit here. */ @@ -1083,15 +1103,16 @@ command_loop (void) editing loop, and reenter the editing loop. When there is an error, cmd_error runs and returns a non-nil value to us. A value of nil means that command_loop_1 itself =2D returned due to end of file (or end of kbd macro). */ + returned due to end of file (or end of kbd macro). HANDLERS is a + list of condition names, passed to internal_condition_case. */ =20 =2Dstatic Lisp_Object =2Dcommand_loop_2 (Lisp_Object ignore) +Lisp_Object +command_loop_2 (Lisp_Object handlers) { register Lisp_Object val; =20 do =2D val =3D internal_condition_case (command_loop_1, Qerror, cmd_error); + val =3D internal_condition_case (command_loop_1, handlers, cmd_error); while (!NILP (val)); =20 return Qnil; @@ -1234,7 +1255,7 @@ some_mouse_moved (void) bool, bool, bool, bool); static void adjust_point_for_property (ptrdiff_t, bool); =20 =2DLisp_Object +static Lisp_Object command_loop_1 (void) { modiff_count prev_modiff =3D 0; diff --git a/src/lisp.h b/src/lisp.h index 91b7a89d0f..a30d7b861d 100644 =2D-- a/src/lisp.h +++ b/src/lisp.h @@ -4417,7 +4417,7 @@ fast_string_match_ignore_case (Lisp_Object regexp, Li= sp_Object string) extern bool detect_input_pending_run_timers (bool); extern void safe_run_hooks (Lisp_Object); extern void cmd_error_internal (Lisp_Object, const char *); =2Dextern Lisp_Object command_loop_1 (void); +extern Lisp_Object command_loop_2 (Lisp_Object); extern Lisp_Object read_menu_command (void); extern Lisp_Object recursive_edit_1 (void); extern void record_auto_save (void); diff --git a/src/macros.c b/src/macros.c index 60d0766a75..0752a5bb6f 100644 =2D-- a/src/macros.c +++ b/src/macros.c @@ -324,7 +324,7 @@ DEFUN ("execute-kbd-macro", Fexecute_kbd_macro, Sexecut= e_kbd_macro, 1, 3, 0, break; } =20 =2D command_loop_1 (); + command_loop_2 (list1 (Qminibuffer_quit)); =20 executing_kbd_macro_iterations =3D ++success_count; =20 diff --git a/src/minibuf.c b/src/minibuf.c index cffb7fe787..9f4970320e 100644 =2D-- a/src/minibuf.c +++ b/src/minibuf.c @@ -496,7 +496,7 @@ DEFUN ("abort-minibuffers", Fabort_minibuffers, Sabort_= minibuffers, 0, 0, "", } } else =2D Fthrow (Qexit, Qt); + CALLN (Ffuncall, intern ("minibuffer-quit-recursive-edit")); return Qnil; } =20 =2D-=20 2.31.1 --=-=-=-- --==-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQJHBAEBCAAxFiEEmxVnesoT5rQXvVXnswkaGpIVmT8FAmCtbVMTHG1paGFAa2Ft bml0bmlrLnRvcAAKCRCzCRoakhWZP0QoEACz5ZagRhP39S7Wh2pkz/md7AgWNRvq +Zpzvt+KWZpp+NKfOc9qmORI9gIxiYfGVji71tm5H9idv43mH6a0sFDAC3neHLyc FUkBhJ9ul9i3eniMrym0U7sUohrScLWOLOt22O2grZtEsmhYFZ66aBchfPCrPmq8 cw9L9Stqfh83IuyMZ/4V0GDQdJAgcV3GqM3pGrnimsMrbfbY0WHNW4wp6LXLVXfY 6SUdnGf5H0MV1SiDSpnUk96iB8/KgR22WcnuNZiHAhejX+lZi7Ox72URgpnu286M 3ckjbSVskJmy/ftYO7T+zobGtNDfySi4lLeb0cNm25YwbmSP1s/UJWE35MWRkz1b NsKZNxzT4wQaqgSOfnS7a5q5jqbPnaTcFiKAvW8XbJMfVO4FzI0mkD6UXaaMN8g6 tydbgAlRrGT1HJ7fNjELKxCA0ttzYcu2U2C/YiPM7CJfZmtKMlhyaUjh4QBhI3wI MvSSimmGYrXiTt5JenG2H2C8gvE/kBnSbK10WXIiyg+eL6acDQToE5PzxpvaJBK6 +fEbvM49QBUs/edriGQVMP7RPtbjUpo5K2fk1ypr7AZV+GzrPhebVZT+J8KZOcY3 aoSI7fPRZBVdvEVNYMpAzRBlVWPW0/D2pvwIsxGTy+ffZMDEnrVpl2ELSQe18yYT LnEjnv11iiCPlA== =7aDF -----END PGP SIGNATURE----- --==-=-=--