GNU bug report logs - #77253
30.1.50; Support RET choosing the selected completion without rebinding arrow keys

Previous Next

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

Full log


View this message in rfc822 format

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: bug#77253: 30.1.50; Support RET choosing the selected completion without rebinding arrow keys, [PATCH] Make RET in minibuffer choose selected completion
Date: Mon, 21 Jul 2025 12:26:32 -0400
[Message part 1 (text/plain, inline)]
Spencer Baugh <sbaugh <at> janestreet.com> writes:

> 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)

Oops sorry, that was the emacs-30 version, attached is the proper
version for installing on trunk.

[0001-Make-RET-in-minibuffer-choose-selected-completion.patch (text/x-patch, inline)]
From 1b969351e067982e6735574bc505ca52e31a8f11 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 6f9e6c67541..12f66f57747 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -3226,6 +3226,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
@@ -3235,6 +3241,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
@@ -3246,7 +3253,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
@@ -3343,18 +3350,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)
@@ -5286,10 +5309,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


This bug report was last modified 23 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.