From 49e06183f5972817d93dad6acf5351c204e61cc5 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Fri, 10 Jun 2022 10:16:57 +0200 Subject: [PATCH] Allow REQUIRE-MATCH to be a function * doc/lispref/minibuf.texi (Minibuffer Completion): Document it. * lisp/minibuffer.el (completion--complete-and-exit): Allow REQUIRE-MATCH to be a function. (read-file-name): Mention it. * src/minibuf.c (Fcompleting_read): Mention it. --- doc/lispref/minibuf.texi | 5 +++ lisp/minibuffer.el | 93 +++++++++++++++++++++------------------- src/minibuf.c | 2 + 3 files changed, 57 insertions(+), 43 deletions(-) diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi index be81b5b3fbb..86e601f8c0f 100644 --- a/doc/lispref/minibuf.texi +++ b/doc/lispref/minibuf.texi @@ -1121,6 +1121,11 @@ completion command (i.e., one of the commands in @code{minibuffer-confirm-exit-commands}) and the resulting input is not an element of @var{collection}. @xref{Completion Commands}. +@item +If a function, the function is called with the input as the only +argument. The function should return a non-@code{nil} value of the +input is acceptable. + @item Any other value of @var{require-match} behaves like @code{t}, except that the exit commands won't exit if it performs completion. diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index cdbde2d3405..332e3fcce97 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -1726,52 +1726,57 @@ If `minibuffer-completion-confirm' is `confirm-after-completion', "Exit from `require-match' minibuffer. COMPLETION-FUNCTION is called if the current buffer's content does not appear to be a match." - (cond - ;; Allow user to specify null string + (cond + ;; Allow user to specify null string ((= beg end) (funcall exit-function)) - ((test-completion (buffer-substring beg end) - minibuffer-completion-table - minibuffer-completion-predicate) - ;; FIXME: completion-ignore-case has various slightly - ;; incompatible meanings. E.g. it can reflect whether the user - ;; wants completion to pay attention to case, or whether the - ;; string will be used in a context where case is significant. - ;; E.g. usually try-completion should obey the first, whereas - ;; test-completion should obey the second. - (when completion-ignore-case - ;; Fixup case of the field, if necessary. - (let* ((string (buffer-substring beg end)) - (compl (try-completion - string - minibuffer-completion-table - minibuffer-completion-predicate))) - (when (and (stringp compl) (not (equal string compl)) - ;; If it weren't for this piece of paranoia, I'd replace - ;; the whole thing with a call to do-completion. - ;; This is important, e.g. when the current minibuffer's - ;; content is a directory which only contains a single - ;; file, so `try-completion' actually completes to - ;; that file. - (= (length string) (length compl))) - (completion--replace beg end compl)))) - (funcall exit-function)) - - ((memq minibuffer-completion-confirm '(confirm confirm-after-completion)) - ;; The user is permitted to exit with an input that's rejected - ;; by test-completion, after confirming her choice. - (if (or (eq last-command this-command) - ;; For `confirm-after-completion' we only ask for confirmation - ;; if trying to exit immediately after typing TAB (this - ;; catches most minibuffer typos). - (and (eq minibuffer-completion-confirm 'confirm-after-completion) - (not (memq last-command minibuffer-confirm-exit-commands)))) + ;; The CONFIRM argument is a predicate. + ((and (functionp minibuffer-completion-confirm) + (funcall minibuffer-completion-confirm + (buffer-substring beg end))) + (funcall exit-function)) + ;; See if we have a completion from the table. + ((test-completion (buffer-substring beg end) + minibuffer-completion-table + minibuffer-completion-predicate) + ;; FIXME: completion-ignore-case has various slightly + ;; incompatible meanings. E.g. it can reflect whether the user + ;; wants completion to pay attention to case, or whether the + ;; string will be used in a context where case is significant. + ;; E.g. usually try-completion should obey the first, whereas + ;; test-completion should obey the second. + (when completion-ignore-case + ;; Fixup case of the field, if necessary. + (let* ((string (buffer-substring beg end)) + (compl (try-completion + string + minibuffer-completion-table + minibuffer-completion-predicate))) + (when (and (stringp compl) (not (equal string compl)) + ;; If it weren't for this piece of paranoia, I'd replace + ;; the whole thing with a call to do-completion. + ;; This is important, e.g. when the current minibuffer's + ;; content is a directory which only contains a single + ;; file, so `try-completion' actually completes to + ;; that file. + (= (length string) (length compl))) + (completion--replace beg end compl)))) + (funcall exit-function)) + ;; The user is permitted to exit with an input that's rejected + ;; by test-completion, after confirming her choice. + ((memq minibuffer-completion-confirm '(confirm confirm-after-completion)) + (if (or (eq last-command this-command) + ;; For `confirm-after-completion' we only ask for confirmation + ;; if trying to exit immediately after typing TAB (this + ;; catches most minibuffer typos). + (and (eq minibuffer-completion-confirm 'confirm-after-completion) + (not (memq last-command minibuffer-confirm-exit-commands)))) (funcall exit-function) - (minibuffer-message "Confirm") - nil)) + (minibuffer-message "Confirm") + nil)) - (t - ;; Call do-completion, but ignore errors. - (funcall completion-function)))) + (t + ;; Call do-completion, but ignore errors. + (funcall completion-function)))) (defun completion--try-word-completion (string table predicate point md) (let ((comp (completion-try-completion string table predicate point md))) @@ -3156,6 +3161,8 @@ Fourth arg MUSTMATCH can take the following values: input, but she needs to confirm her choice if she called `minibuffer-complete' right before `minibuffer-complete-and-exit' and the input is not an existing file. +- a function, which will be called with the input as the parameter. + If it returns a non-nil value, we exit with that value. - anything else behaves like t except that typing RET does not exit if it does non-null completion. diff --git a/src/minibuf.c b/src/minibuf.c index 79985b8d2bb..3e984d163d1 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -2009,6 +2009,8 @@ REQUIRE-MATCH can take the following values: input, but she needs to confirm her choice if she called `minibuffer-complete' right before `minibuffer-complete-and-exit' and the input is not an element of COLLECTION. +- a function, which will be called with the input as the parameter. + If it returns a non-nil value, we exit with that value. - anything else behaves like t except that typing RET does not exit if it does non-null completion. -- 2.39.2