From 9291e7316f98ab0858b323f72047ffd5a23d9ac9 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sun, 14 Feb 2021 13:29:35 +0100 Subject: [PATCH] Add new 'declare' forms for command completion predicates * doc/lispref/functions.texi (Declare Form): Document the new `completion' and `modes' declarations. * lisp/simple.el (completion-with-modes-p): New helper functions. * lisp/emacs-lisp/byte-run.el (byte-run--set-completion) (byte-run--set-modes): (defun-declarations-alist): New declarations for `completion' and `modes'. --- doc/lispref/functions.texi | 10 ++++++++++ etc/NEWS | 9 +++++++++ lisp/emacs-lisp/byte-run.el | 15 ++++++++++++++- lisp/simple.el | 5 +++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi index 414035f684b..1e3da8e3a5d 100644 --- a/doc/lispref/functions.texi +++ b/doc/lispref/functions.texi @@ -2309,6 +2309,16 @@ form @code{(lambda (@var{arg}) @var{body})} in which case that function will additionally have access to the macro (or function)'s arguments and it will be passed to @code{gv-define-setter}. +@item (completion @var{completion-predicate}) +Declare @var{completion-predicate} as a function to determine whether +to include the symbol in the list of functions when asking for +completions in @kbd{M-x}. @var{completion-predicate} is called with +two parameters: The first parameter is the symbol, and the second is +the current buffer. + +@item (modes @var{modes}) +Specify that this command is meant to be applicable for @var{modes} +only. @end table @end defmac diff --git a/etc/NEWS b/etc/NEWS index d8f0bc60726..3b6467bf45c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2266,6 +2266,15 @@ back in Emacs 23.1. The affected functions are: 'make-obsolete', * Lisp Changes in Emacs 28.1 ++++ +** New forms to declare how completion should happen has been added. +'(declare (completion PREDICATE))' can be used as a general predicate +to say whether the command should be present when completing with +'M-x TAB'. '(declare (modes MODE...))' can be used as a short-hand +way of saying that the command should be present when completing from +buffers in major modes derived from MODE..., or, if it's a minor mode, +whether that minor mode is enabled in the current buffer. + +++ ** The 'interactive' syntax has been extended to allow listing applicable modes. Forms like '(interactive "p" dired-mode)' can be used to annotate the diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el index 88f362d24f0..30fcbf2b9cc 100644 --- a/lisp/emacs-lisp/byte-run.el +++ b/lisp/emacs-lisp/byte-run.el @@ -143,6 +143,17 @@ The return value of this function is not used." (list 'function-put (list 'quote f) ''lisp-indent-function (list 'quote val)))) +(defalias 'byte-run--set-completion + #'(lambda (f _args val) + (list 'function-put (list 'quote f) + ''completion-predicate val))) + +(defalias 'byte-run--set-modes + #'(lambda (f _args val) + (list 'function-put (list 'quote f) + ''completion-predicate `(lambda (_ b) + (completion-with-modes-p ,val b))))) + ;; Add any new entries to info node `(elisp)Declare Form'. (defvar defun-declarations-alist (list @@ -159,7 +170,9 @@ This may shift errors from run-time to compile-time.") If `error-free', drop calls even if `byte-compile-delete-errors' is nil.") (list 'compiler-macro #'byte-run--set-compiler-macro) (list 'doc-string #'byte-run--set-doc-string) - (list 'indent #'byte-run--set-indent)) + (list 'indent #'byte-run--set-indent) + (list 'completion #'byte-run--set-completion) + (list 'modes #'byte-run--set-modes)) "List associating function properties to their macro expansion. Each element of the list takes the form (PROP FUN) where FUN is a function. For each (PROP . VALUES) in a function's declaration, diff --git a/lisp/simple.el b/lisp/simple.el index 0c5bcb66724..9057355a7ab 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1950,6 +1950,11 @@ to get different commands to edit and resubmit." (complete-with-action action obarray string pred))) #'commandp t nil 'extended-command-history))) +(defun completion-with-modes-p (modes buffer) + (apply #'provided-mode-derived-p + (buffer-local-value 'major-mode buffer) + modes)) + (defun read-extended-command--affixation (command-names) (with-selected-window (or (minibuffer-selected-window) (selected-window)) (mapcar