Package: emacs;
Reported by: Spencer Baugh <sbaugh <at> janestreet.com>
Date: Tue, 25 Mar 2025 15:12:02 UTC
Severity: normal
Found in version 30.1.50
Message #41 received at 77253 <at> debbugs.gnu.org (full text, mbox):
From: Spencer Baugh <sbaugh <at> janestreet.com> To: Juri Linkov <juri <at> linkov.net> Cc: sbaugh <at> catern.com, 77253 <at> debbugs.gnu.org Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected completion without rebinding arrow keys Date: Mon, 21 Jul 2025 12:24:19 -0400
[Message part 1 (text/plain, inline)]
Juri Linkov <juri <at> linkov.net> writes: >>>>>>> Not sure if it's possible for RET to accept the selected candidate >>>>>>> by default since users might prefer to accept text in the minibuffer. >>>>>> >>>>>> If there's a selected candidate, though, then users have already decided >>>>>> to use M-<up>/M-<down> to interact with completions. (Or they've >>>>>> switched to the completions buffer and selected one) >>>>>> >>>>>> If they decide they don't want the candidate they selected, and want to >>>>>> continue with text in the minibuffer, completion-auto-deselect will >>>>>> automatically deselect the candidate if they type anything. >>>>>> >>>>>> I think these two facts combined make it possible for RET to accept the >>>>>> selected candidate by default. >>>>> >>>>> Makes sense. So we need to try how well it performs. >>>> >>>> How about this? >>> >>> Thanks, will try to use for a while. >> >> Any feedback on the patch? > > Everything looks good. Could you send the final version of the patch? Yes, attached. (Note that this doesn't do the change I mentioned earlier of replacing (get-buffer-window "*Completions*" 0) everywhere with minibuffer--completions-visible, which probably should be done in a separate patch, I can send that if you're up to install it now)
[0001-Make-RET-in-minibuffer-choose-selected-completion.patch (text/x-patch, inline)]
From df5c9ffe4669bd8417bb5ae3d631723e21e70d68 Mon Sep 17 00:00:00 2001 From: Spencer Baugh <sbaugh <at> janestreet.com> Date: Mon, 21 Jul 2025 12:22:19 -0400 Subject: [PATCH] Make RET in minibuffer choose selected completion Previously, one could select a completion via M-<up>/M-<down>, but then RET would not actually select the chosen completion. With the addition of completion-auto-deselect, this is not actually necessary: we can reasonably assume that when a completion is selected, the user wants to use that, since their last action must have been to select it. So, just choose the selected completion on RET. * lisp/minibuffer.el (minibuffer--completions-visible) (minibuffer-choose-completion-if-selected): Add. (minibuffer-choose-completion-or-exit): Use the more reliable minibuffer-choose-completion-if-selected instead of a condition-case. (minibuffer-local-must-match-map): Bind RET to minibuffer-choose-completion-or-exit instead of minibuffer-complete-and-exit. (bug#77253) (minibuffer-choose-completion-just-exit): Add. (minibuffer-local-completion-map): Bind RET to minibuffer-choose-completion-just-exit instead of exit-minibuffer. (minibuffer-visible-completions--filter): Use minibuffer--completions-visible. --- lisp/minibuffer.el | 47 +++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 64e3ad53b42..7a7f6aae44b 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -3232,6 +3232,12 @@ completion-help-at-point (define-key map "\n" 'exit-minibuffer) (define-key map "\r" 'exit-minibuffer)) +(defun minibuffer-choose-completion-just-exit (&optional no-exit) + "Choose the selected completion from the minibuffer or call `exit-minibuffer'." + (interactive "P") + (or (minibuffer-choose-completion-if-selected no-exit) + (exit-minibuffer))) + (defvar-keymap minibuffer-local-completion-map :doc "Local keymap for minibuffer input with completion." :parent minibuffer-local-map @@ -3241,6 +3247,7 @@ minibuffer-local-completion-map ;; another binding for it. ;; "M-TAB" #'minibuffer-force-complete "SPC" #'minibuffer-complete-word + "RET" #'minibuffer-choose-completion-just-exit "?" #'minibuffer-completion-help "<prior>" #'switch-to-completions "M-v" #'switch-to-completions @@ -3252,7 +3259,7 @@ minibuffer-local-completion-map (defvar-keymap minibuffer-local-must-match-map :doc "Local keymap for minibuffer input with completion, for exact match." :parent minibuffer-local-completion-map - "RET" #'minibuffer-complete-and-exit + "RET" #'minibuffer-choose-completion-or-exit "C-j" #'minibuffer-complete-and-exit) (defvar-keymap minibuffer-local-filename-completion-map @@ -3349,18 +3356,34 @@ minibuffer-visible-completions (defvar minibuffer-visible-completions--always-bind nil "If non-nil, force the `minibuffer-visible-completions' bindings on.") +(defun minibuffer--completions-visible () + "Return the window where the *Completions* buffer for this minibuffer is visible." + (when-let ((window (get-buffer-window "*Completions*" 0))) + (when (eq (buffer-local-value 'completion-reference-buffer + (window-buffer window)) + (window-buffer (active-minibuffer-window))) + window))) + +(defun minibuffer-choose-completion-if-selected (&optional no-exit no-quit) + "Like `minibuffer-choose-completion', but do nothing if no candidate is selected. + +Return non-nil if a completion was chosen." + (when-let* ((window (minibuffer--completions-visible))) + (with-selected-window window + ;; Detect selection as if `choose-completion-deselect-if-after' is non-nil. + (when (get-text-property (point) 'completion--string) + (choose-completion nil no-exit no-quit) + t)))) + (defun minibuffer-visible-completions--filter (cmd) "Return CMD if `minibuffer-visible-completions' bindings should be active." (if minibuffer-visible-completions--always-bind cmd - (when-let ((window (get-buffer-window "*Completions*" 0))) - (when (and (eq (buffer-local-value 'completion-reference-buffer - (window-buffer window)) - (window-buffer (active-minibuffer-window))) - (if (eq cmd #'minibuffer-choose-completion-or-exit) - (with-current-buffer (window-buffer window) - (get-text-property (point) 'completion--string)) - t)) + (when-let ((window (minibuffer--completions-visible))) + (when (if (eq cmd #'minibuffer-choose-completion-or-exit) + (with-current-buffer (window-buffer window) + (get-text-property (point) 'completion--string)) + t) cmd)))) (defun minibuffer-visible-completions--bind (binding) @@ -5211,10 +5234,8 @@ minibuffer-choose-completion-or-exit in the completions window, then exit the minibuffer using its present contents." (interactive "P") - (condition-case nil - (let ((choose-completion-deselect-if-after t)) - (minibuffer-choose-completion no-exit no-quit)) - (error (minibuffer-complete-and-exit)))) + (or (minibuffer-choose-completion-if-selected no-exit no-quit) + (minibuffer-complete-and-exit))) (defun minibuffer-complete-history () "Complete as far as possible using the minibuffer history. -- 2.39.3
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.