From 57ac0d5c0408bb835eb78f7497a425d8390a7460 Mon Sep 17 00:00:00 2001 From: Gregory Heytings Date: Thu, 22 Apr 2021 15:12:56 +0000 Subject: [PATCH] Make it possible to disable a completion backend in recursive minibuffers --- lisp/minibuffer.el | 1 + lisp/subr.el | 17 +++++++++++++ src/fns.c | 6 ++--- src/minibuf.c | 59 +++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 74 insertions(+), 9 deletions(-) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 7da3c39e6b..1796b97990 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -3885,6 +3885,7 @@ completing-read-default (1+ (cdr initial-input))))) (let* ((minibuffer-completion-table collection) + (minibuffer-local-completion t) (minibuffer-completion-predicate predicate) ;; FIXME: Remove/rename this var, see the next one. (minibuffer-completion-confirm (unless (eq require-match t) diff --git a/lisp/subr.el b/lisp/subr.el index c2be26a15f..2414f60940 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -2791,6 +2791,23 @@ read-passwd ;; And of course, don't keep the sensitive data around. (erase-buffer)))))))) +(defmacro read-from-minibuffer (&rest body) + "Read a string from the minibuffer with `internal-read-from-minibuffer'. +See `internal-read-from-minibuffer' for a description of the arguments. +This macro exists only in Emacs 28, for the transition period during which +the default value of `minibuffer-local-completion' is nil, and will be +removed in Emacs 29. Likewise, `internal-read-from-minibuffer' will be +removed in Emacs 29, please do not use it directly." + `(if minibuffer-local-completion + (let ((minibuffer-local-completion-table minibuffer-completion-table) + (minibuffer-local-completion-predicate minibuffer-completion-predicate) + (minibuffer-local-completion-confirm minibuffer-completion-confirm)) + (let ((minibuffer-completion-table nil) + (minibuffer-completion-predicate nil) + (minibuffer-completion-confirm nil)) + (internal-read-from-minibuffer ,@body))) + (internal-read-from-minibuffer ,@body))) + (defvar read-number-history nil "The default history for the `read-number' function.") diff --git a/src/fns.c b/src/fns.c index 1758148ff2..db6679a847 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2985,9 +2985,9 @@ DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0, while (1) { - ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil, - Qyes_or_no_p_history, Qnil, - Qnil)); + ans = Fdowncase (Finternal_read_from_minibuffer (prompt, Qnil, Qnil, Qnil, + Qyes_or_no_p_history, Qnil, + Qnil)); if (SCHARS (ans) == 3 && !strcmp (SSDATA (ans), "yes")) return unbind_to (count, Qt); if (SCHARS (ans) == 2 && !strcmp (SSDATA (ans), "no")) diff --git a/src/minibuf.c b/src/minibuf.c index 1a637c86ad..fd780bd5c1 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -865,6 +865,16 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, if (STRINGP (input_method) && !NILP (Ffboundp (Qactivate_input_method))) call1 (Qactivate_input_method, input_method); + if (! EQ (Vminibuffer_local_completion, Qnil)) { + Fmake_local_variable (Qminibuffer_completion_table); + Fset (Qminibuffer_completion_table, Vminibuffer_local_completion_table); + Fmake_local_variable (Qminibuffer_completion_predicate); + Fset (Qminibuffer_completion_predicate, Vminibuffer_local_completion_predicate); + Fmake_local_variable (Qminibuffer_completion_confirm); + Fset (Qminibuffer_completion_confirm, Vminibuffer_local_completion_confirm); + specbind (Qminibuffer_local_completion, Qnil); + } + run_hook (Qminibuffer_setup_hook); /* Don't allow the user to undo past this point. */ @@ -1231,9 +1241,16 @@ barf_if_interaction_inhibited (void) xsignal0 (Qinhibited_interaction); } -DEFUN ("read-from-minibuffer", Fread_from_minibuffer, - Sread_from_minibuffer, 1, 7, 0, +DEFUN ("internal-read-from-minibuffer", Finternal_read_from_minibuffer, + Sinternal_read_from_minibuffer, 1, 7, 0, doc: /* Read a string from the minibuffer, prompting with string PROMPT. + +Note: Do not use this function directly, use `read-from-minibuffer' instead, +whith the arguments described below. The `read-from-minibuffer' macro exists +only in Emacs 28 for the transition period during which the default value of +`minibuffer-local-completion' is nil, it will be removed in Emacs 29, and +`internal-read-from-minibuffer' will become `read-from-minibuffer' again. + The optional second arg INITIAL-CONTENTS is an obsolete alternative to DEFAULT-VALUE. It normally should be nil in new code, except when HIST is a cons. It is discussed in more detail below. @@ -1352,9 +1369,9 @@ DEFUN ("read-string", Fread_string, Sread_string, 1, 5, 0, FIXME: `minibuffer-completion-table' should be buffer-local instead. */ specbind (Qminibuffer_completion_table, Qnil); - val = Fread_from_minibuffer (prompt, initial_input, Qnil, - Qnil, history, default_value, - inherit_input_method); + val = Finternal_read_from_minibuffer (prompt, initial_input, Qnil, + Qnil, history, default_value, + inherit_input_method); if (STRINGP (val) && SCHARS (val) == 0 && ! NILP (default_value)) val = CONSP (default_value) ? XCAR (default_value) : default_value; return unbind_to (count, val); @@ -2282,6 +2299,9 @@ syms_of_minibuf (void) Fset (Qminibuffer_default, Qnil); DEFSYM (Qminibuffer_completion_table, "minibuffer-completion-table"); + DEFSYM (Qminibuffer_completion_predicate, "minibuffer-completion-predicate"); + DEFSYM (Qminibuffer_completion_confirm, "minibuffer-completion-confirm"); + DEFSYM (Qminibuffer_local_completion, "minibuffer-local-completion"); staticpro (&last_minibuf_string); @@ -2415,6 +2435,33 @@ syms_of_minibuf (void) completion commands listed in `minibuffer-confirm-exit-commands'. */); Vminibuffer_completion_confirm = Qnil; + DEFVAR_LISP ("minibuffer-local-completion", Vminibuffer_local_completion, + doc: /* Whether minibuffer completion elements should become buffer-local. +The default is nil for Emacs 28. Setting this variable in Emacs 29 will have no effect; +the value t will be assumed. +When t, `minibuffer-completion-table', `minibuffer-completion-predicate' and +`minibuffer-completion-confirm' become buffer-local upon entering the minibuffer, +and are nil in recursive invocations of the minibuffer, unless they have been let-bound +to a value. +When nil, their values is shared between the recursive invocations of the minibuffer, +unless they have been let-bound to another value. */); + Vminibuffer_local_completion = Qnil; + + DEFVAR_LISP ("minibuffer-local-completion-table", Vminibuffer_local_completion_table, + doc: /* The local completion table used in the minibuffer. +See `minibuffer-local-completion'. */); + Vminibuffer_local_completion_table = Qnil; + + DEFVAR_LISP ("minibuffer-local-completion-predicate", Vminibuffer_local_completion_predicate, + doc: /* The local completion predicate used in the minibuffer. +See `minibuffer-local-completion'. */); + Vminibuffer_local_completion_predicate = Qnil; + + DEFVAR_LISP ("minibuffer-local-completion-confirm", Vminibuffer_local_completion_confirm, + doc: /* The local completion confirm used in the minibuffer. +See `minibuffer-local-completion'. */); + Vminibuffer_local_completion_confirm = Qnil; + DEFVAR_LISP ("minibuffer-completing-file-name", Vminibuffer_completing_file_name, doc: /* Non-nil means completing file names. */); @@ -2487,7 +2534,7 @@ syms_of_minibuf (void) defsubr (&Sactive_minibuffer_window); defsubr (&Sset_minibuffer_window); - defsubr (&Sread_from_minibuffer); + defsubr (&Sinternal_read_from_minibuffer); defsubr (&Sread_string); defsubr (&Sread_command); defsubr (&Sread_variable); -- 2.30.2