From 13b9268374669c368343ce4279041f2021b264f6 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Mon, 14 Feb 2022 11:20:41 +0100 Subject: [PATCH] Add a mechanism for querying before executing a command * doc/emacs/custom.texi (Disabling): Document it. * doc/lispref/commands.texi (Disabling Commands): Document the low-level stuff. * lisp/simple.el (command-execute): Respect the `(query ...)' value for `disabled'. (command-execute--query): New function. (command-query): New function. --- doc/emacs/custom.texi | 16 ++++++++++++++++ doc/lispref/commands.texi | 9 +++++++++ etc/NEWS | 5 +++++ lisp/simple.el | 28 ++++++++++++++++++++++++---- 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index c4f112d6683..a3c9c7c206a 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -2234,6 +2234,22 @@ is included in the message displayed when the command is used: "It's better to use `kill-region' instead.\n") @end example +@findex command-query + As a less heavy-handed alternative to disabling commands, you may +want to be queried before executing a command. For instance, to be +queried before executing the @kbd{M->} (@code{end-of-buffer}) +command, you could put something like the following in your init file: + +@example +(command-query + 'end-of-buffer + "Do you really want to go to the end of the buffer?") +@end example + +By default, you'll be queried with a @kbd{y}/@kbd{n} question, but if +you give a non-@code{nil} value to the third, optional argument, +you'll be queried with @kbd{yes}/@kbd{no} instead. + @findex disable-command @findex enable-command You can make a command disabled either by editing the initialization diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 01aa1e1fa4b..a1628eabaa2 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -3945,6 +3945,15 @@ what happens when a disabled command is invoked interactively. Disabling a command has no effect on calling it as a function from Lisp programs. +@findex command-query + The value of the @code{disabled} property can also be a list where +the first element is the symbol @code{query}. In that case, the user +will be queried whether to execute the command. The second element in +the list should be @code{nil} or non-@code{nil} to say whether to use +@code{y-or-n-p} or @code{yes-or-no-p}, respectively, and the third +element is the question to use. The @code{command-query} convenience +function should be used to enable querying for a command. + @deffn Command enable-command command Allow @var{command} (a symbol) to be executed without special confirmation from now on, and alter the user's init file (@pxref{Init diff --git a/etc/NEWS b/etc/NEWS index 0f956f18a20..cd8cec32d5d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -152,6 +152,11 @@ An autoload definition appears just as a '(defun . NAME)' and the * Changes in Emacs 29.1 ++++ +** New function 'command-query'. +Commands that are marked with this function will prompt the user +before executing. + --- ** 'count-lines' will now report buffer totals if given a prefix. diff --git a/lisp/simple.el b/lisp/simple.el index 695871db505..accc119e2b3 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2381,12 +2381,17 @@ don't clear it." (setq current-prefix-arg prefix-arg) (setq prefix-arg nil) (when current-prefix-arg - (prefix-command-update)))))) + (prefix-command-update))))) + query) (if (and (symbolp cmd) (get cmd 'disabled) - disabled-command-function) - ;; FIXME: Weird calling convention! - (run-hooks 'disabled-command-function) + (or (and (setq query (and (consp (get cmd 'disabled)) + (eq (car (get cmd 'disabled)) 'query))) + (not (command-execute--query cmd))) + (and (not query) disabled-command-function))) + (when (not query) + ;; FIXME: Weird calling convention! + (run-hooks 'disabled-command-function)) (let ((final cmd)) (while (progn @@ -2410,6 +2415,21 @@ don't clear it." (put cmd 'command-execute-obsolete-warned t) (message "%s" (macroexp--obsolete-warning cmd (get cmd 'byte-obsolete-info) "command")))))))))) + +(defun command-execute--query (command) + "Query the user whether to run COMMAND." + (let ((query (get command 'disabled))) + (funcall (if (nth 1 query) #'yes-or-no-p #'y-or-n-p) + (nth 2 query)))) + +;;;###autoload +(defun command-query (command query &optional verbose) + "Make executing COMMAND issue QUERY to the user. +This will, by default, use `y-or-n-p', but if VERBOSE, +`yes-or-no-p' is used instead." + (put command 'disabled + (list 'query (not (not verbose)) query))) + (defvar minibuffer-history nil "Default minibuffer history list. -- 2.39.5