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

Fixed in version 31.0.50

Done: Juri Linkov <juri <at> linkov.net>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 77253 in the body.
You can then email your comments to 77253 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Tue, 25 Mar 2025 15:12:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Spencer Baugh <sbaugh <at> janestreet.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Tue, 25 Mar 2025 15:12:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Spencer Baugh <sbaugh <at> janestreet.com>
To: bug-gnu-emacs <at> gnu.org
Cc: juri <at> linkov.net
Subject: 30.1.50; Support RET choosing the selected completion without
 rebinding arrow keys
Date: Tue, 25 Mar 2025 11:10:57 -0400
Right now, minibuffer-visible-completions does two things, only when
*Completions* is visible:

A. If there's a selected completion candidate, RET exits the minibuffer
with it.

B. The arrow keys move point in the *Completions* buffer instead of the
minibuffer, to select completion candidates.

These are really two separate things.

A is a nice behavior for novice users, but B is difficult for novice
users (who like to use the arrow keys for moving point) to deal with.

We should make them separately configurable, or at least allow enabling
the RET behavior without the arrow keys behavior.

And with the addition of completion-auto-deselect, the RET behavior is
actually a plausible default behavior: it only takes effect if the user
has manually selected a completion candidate with M-<up>/M-<down>, and
the selected candidate is automatically deselected if the user types
more.  So it won't affect anyone who isn't explicitly making use of
M-<up>/M-<down>.

So I suggest we should add a new defcustom to change the RET behavior in
the presence of a selected completion candidate, and default it to t.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Tue, 25 Mar 2025 17:23:02 GMT) Full text and rfc822 format available.

Message #8 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: bug-gnu-emacs <at> gnu.org
Subject: Re: 30.1.50; Support RET choosing the selected completion without
 rebinding arrow keys
Date: Tue, 25 Mar 2025 19:19:38 +0200
> Right now, minibuffer-visible-completions does two things, only when
> *Completions* is visible:
>
> A. If there's a selected completion candidate, RET exits the minibuffer
> with it.
>
> B. The arrow keys move point in the *Completions* buffer instead of the
> minibuffer, to select completion candidates.
>
> These are really two separate things.
>
> A is a nice behavior for novice users, but B is difficult for novice
> users (who like to use the arrow keys for moving point) to deal with.

Not sure why this would be difficult for novice users, but maybe adding
a new value to the existing defcustom minibuffer-visible-completions
would be sufficient?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Tue, 25 Mar 2025 17:26:02 GMT) Full text and rfc822 format available.

Message #11 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: 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Tue, 25 Mar 2025 13:25:09 -0400
Juri Linkov <juri <at> linkov.net> writes:
>> Right now, minibuffer-visible-completions does two things, only when
>> *Completions* is visible:
>>
>> A. If there's a selected completion candidate, RET exits the minibuffer
>> with it.
>>
>> B. The arrow keys move point in the *Completions* buffer instead of the
>> minibuffer, to select completion candidates.
>>
>> These are really two separate things.
>>
>> A is a nice behavior for novice users, but B is difficult for novice
>> users (who like to use the arrow keys for moving point) to deal with.
>
> Not sure why this would be difficult for novice users,

Well, because they like using the arrow keys. :)

> but maybe adding a new value to the existing defcustom
> minibuffer-visible-completions would be sufficient?

That would work, but I guess I also propose that we should change the
implementation a bit.  The use of a menu-item :filter binding is clever,
but I think it would be nicer to have a normal binding for RET which
just checks if *Completions* is shown/a completion candidate is
selected.  For one thing, then C-h k RET will behave more expectedly.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Wed, 26 Mar 2025 07:54:01 GMT) Full text and rfc822 format available.

Message #14 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Wed, 26 Mar 2025 09:52:05 +0200
>>> Right now, minibuffer-visible-completions does two things, only when
>>> *Completions* is visible:
>>>
>>> A. If there's a selected completion candidate, RET exits the minibuffer
>>> with it.
>>>
>>> B. The arrow keys move point in the *Completions* buffer instead of the
>>> minibuffer, to select completion candidates.
>>>
>>> These are really two separate things.
>>>
>>> A is a nice behavior for novice users, but B is difficult for novice
>>> users (who like to use the arrow keys for moving point) to deal with.
>>
>> Not sure why this would be difficult for novice users,
>
> Well, because they like using the arrow keys. :)

But they like using the arrow keys to select a completion candidate too.
This is how they use arrow keys e.g. in a web browser in the address bar.
At least up/down arrows navigate completions, while left/right arrows
indeed move the cursor in the address bar.

So we need separate values for up/down and left/right arrows?

>> but maybe adding a new value to the existing defcustom
>> minibuffer-visible-completions would be sufficient?
>
> That would work, but I guess I also propose that we should change the
> implementation a bit.  The use of a menu-item :filter binding is clever,
> but I think it would be nicer to have a normal binding for RET which
> just checks if *Completions* is shown/a completion candidate is
> selected.  For one thing, then C-h k RET will behave more expectedly.

Removing the :filter binding would be fine, if it won't cause other problems.
At least it would be nice to try to see how this works with :filter.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Wed, 26 Mar 2025 14:07:02 GMT) Full text and rfc822 format available.

Message #17 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: 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Wed, 26 Mar 2025 10:06:20 -0400
Juri Linkov <juri <at> linkov.net> writes:

>>>> Right now, minibuffer-visible-completions does two things, only when
>>>> *Completions* is visible:
>>>>
>>>> A. If there's a selected completion candidate, RET exits the minibuffer
>>>> with it.
>>>>
>>>> B. The arrow keys move point in the *Completions* buffer instead of the
>>>> minibuffer, to select completion candidates.
>>>>
>>>> These are really two separate things.
>>>>
>>>> A is a nice behavior for novice users, but B is difficult for novice
>>>> users (who like to use the arrow keys for moving point) to deal with.
>>>
>>> Not sure why this would be difficult for novice users,
>>
>> Well, because they like using the arrow keys. :)
>
> But they like using the arrow keys to select a completion candidate too.
> This is how they use arrow keys e.g. in a web browser in the address bar.
> At least up/down arrows navigate completions, while left/right arrows
> indeed move the cursor in the address bar.

That is true.

> So we need separate values for up/down and left/right arrows?

That would probably be good, yes.

But, here's another factor: The *Completions* buffer by default contains
a help message explaining to users that they can use M-<up> and M-<down>
to select completions.  There's no such message explaining to users that
they can use C-b/C-f/C-n/C-p to move point.  So:

- If the arrow keys move point, users can still figure out how to select
  completions by reading the help text.

- If the arrow keys select completions, users who don't know
  C-b/C-f/C-n/C-p are basically helpless.  (This is sadly common at my
  site, because most of our users use evil-mode and don't know
  C-b/C-f/C-n/C-p)

Also, rebinding the arrow keys by default to select completions is
probably an unacceptable behavior change.  But it's very possible to
rebind RET to accept completions by default.  So even if we disregard
the "novice user" argument, I still think we should investigate binding
RET without rebinding the arrow keys.

>>> but maybe adding a new value to the existing defcustom
>>> minibuffer-visible-completions would be sufficient?
>>
>> That would work, but I guess I also propose that we should change the
>> implementation a bit.  The use of a menu-item :filter binding is clever,
>> but I think it would be nicer to have a normal binding for RET which
>> just checks if *Completions* is shown/a completion candidate is
>> selected.  For one thing, then C-h k RET will behave more expectedly.
>
> Removing the :filter binding would be fine, if it won't cause other problems.
> At least it would be nice to try to see how this works with :filter.

I'm curious: Why do you prefer the :filter approach?  Does it avoid some
problems that happened in the past?  It makes sense for the arrow keys,
but if we are rebinding RET by default, :filter seems like an unusual
thing to use.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Thu, 27 Mar 2025 18:01:02 GMT) Full text and rfc822 format available.

Message #20 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Thu, 27 Mar 2025 19:50:13 +0200
> But, here's another factor: The *Completions* buffer by default contains
> a help message explaining to users that they can use M-<up> and M-<down>
> to select completions.  There's no such message explaining to users that
> they can use C-b/C-f/C-n/C-p to move point.  So:
>
> - If the arrow keys move point, users can still figure out how to select
>   completions by reading the help text.
>
> - If the arrow keys select completions, users who don't know
>   C-b/C-f/C-n/C-p are basically helpless.  (This is sadly common at my
>   site, because most of our users use evil-mode and don't know
>   C-b/C-f/C-n/C-p)

When users need to move point with arrow keys, then they have
to close the completions window.  This is the purpose of
'minibuffer-visible-completions': to eliminate ambiguity
whether arrows/RET apply to the visible completions window,
or to the text in the minibuffer.

> Also, rebinding the arrow keys by default to select completions is
> probably an unacceptable behavior change.  But it's very possible to
> rebind RET to accept completions by default.  So even if we disregard
> the "novice user" argument, I still think we should investigate binding
> RET without rebinding the arrow keys.

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.

> I'm curious: Why do you prefer the :filter approach?  Does it avoid some
> problems that happened in the past?  It makes sense for the arrow keys,
> but if we are rebinding RET by default, :filter seems like an unusual
> thing to use.

:filter makes it easier to add conditional keybindings that share
the same condition.  I doubt if it would be possible to rebind RET
by default.  But need to try to see how it works.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Thu, 27 Mar 2025 20:43:02 GMT) Full text and rfc822 format available.

Message #23 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: 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Thu, 27 Mar 2025 16:42:29 -0400
Juri Linkov <juri <at> linkov.net> writes:
>> But, here's another factor: The *Completions* buffer by default contains
>> a help message explaining to users that they can use M-<up> and M-<down>
>> to select completions.  There's no such message explaining to users that
>> they can use C-b/C-f/C-n/C-p to move point.  So:
>>
>> - If the arrow keys move point, users can still figure out how to select
>>   completions by reading the help text.
>>
>> - If the arrow keys select completions, users who don't know
>>   C-b/C-f/C-n/C-p are basically helpless.  (This is sadly common at my
>>   site, because most of our users use evil-mode and don't know
>>   C-b/C-f/C-n/C-p)
>
> When users need to move point with arrow keys, then they have
> to close the completions window.  This is the purpose of
> 'minibuffer-visible-completions': to eliminate ambiguity
> whether arrows/RET apply to the visible completions window,
> or to the text in the minibuffer.

Yes, and I'm definitely a fan of minibuffer-visible-completions, but
just to name a few problems:

- It's not necessarily obvious that closing the completions window will
  make the arrow keys operate in the minibuffer.  Actually, maybe we
  should update the completion help text to say that?  That might help a
  lot.

- The new completion-eager-display makes *Completions* pop up
  immediately; when this happens, it can be surprising that the arrow
  keys don't work in the minibuffer from the very start of the
  minibuffer session.

But again, I like minibuffer-visible-completions a lot, I'm just
wondering about other points in the design space.

>> Also, rebinding the arrow keys by default to select completions is
>> probably an unacceptable behavior change.  But it's very possible to
>> rebind RET to accept completions by default.  So even if we disregard
>> the "novice user" argument, I still think we should investigate binding
>> RET without rebinding the arrow keys.
>
> 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.

>> I'm curious: Why do you prefer the :filter approach?  Does it avoid some
>> problems that happened in the past?  It makes sense for the arrow keys,
>> but if we are rebinding RET by default, :filter seems like an unusual
>> thing to use.
>
> :filter makes it easier to add conditional keybindings that share
> the same condition.  I doubt if it would be possible to rebind RET
> by default.  But need to try to see how it works.

Makes sense.  I'll try.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Fri, 28 Mar 2025 07:33:02 GMT) Full text and rfc822 format available.

Message #26 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Fri, 28 Mar 2025 09:20:43 +0200
> - It's not necessarily obvious that closing the completions window will
>   make the arrow keys operate in the minibuffer.  Actually, maybe we
>   should update the completion help text to say that?  That might help a
>   lot.

Maybe it's possible to squeeze this help text just into one additional line?
Something like:

  Type 'C-g' to close this window and restore arrows to move point.

> - The new completion-eager-display makes *Completions* pop up
>   immediately; when this happens, it can be surprising that the arrow
>   keys don't work in the minibuffer from the very start of the
>   minibuffer session.

Then another possible value for 'minibuffer-visible-completions'
would be to not rebind left/right arrows when the completions window
contains only one column (like on the browser's address bar).

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




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Thu, 03 Apr 2025 17:53:02 GMT) Full text and rfc822 format available.

Message #29 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: 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Thu, 03 Apr 2025 13:52:44 -0400
Juri Linkov <juri <at> linkov.net> writes:

>> - It's not necessarily obvious that closing the completions window will
>>   make the arrow keys operate in the minibuffer.  Actually, maybe we
>>   should update the completion help text to say that?  That might help a
>>   lot.
>
> Maybe it's possible to squeeze this help text just into one additional line?
> Something like:
>
>   Type 'C-g' to close this window and restore arrows to move point.

Maybe we don't even need an additional line?  How about:

Click or type RET on a completion to select it, or C-g to close this window.
Type <right>, <left>, <down>, <up> to move point between completions.

>> - The new completion-eager-display makes *Completions* pop up
>>   immediately; when this happens, it can be surprising that the arrow
>>   keys don't work in the minibuffer from the very start of the
>>   minibuffer session.
>
> Then another possible value for 'minibuffer-visible-completions'
> would be to not rebind left/right arrows when the completions window
> contains only one column (like on the browser's address bar).

True.  Though I guess that could maybe be the default behavior when
completions-format=one-column.

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

(BTW, after writing minibuffer--completions-visible, I'm wondering if
most of the code which calls (get-buffer-window "*Completions*" 0) is
actually buggy, because it's not checking completion-reference-buffer.
Should we replace ~all the calls to (get-buffer-window "*Completions*"
0) with (minibuffer--completions-visible) which does check that?)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 404fa143194..c026e41a818 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -3209,6 +3209,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)
+      (minibuffer-exit)))
+
 (defvar-keymap minibuffer-local-completion-map
   :doc "Local keymap for minibuffer input with completion."
   :parent minibuffer-local-map
@@ -3218,6 +3224,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
@@ -3229,7 +3236,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
@@ -3326,18 +3333,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 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)
@@ -5109,10 +5132,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.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Thu, 03 Apr 2025 18:29:02 GMT) Full text and rfc822 format available.

Message #32 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Thu, 03 Apr 2025 21:19:16 +0300
>>> - It's not necessarily obvious that closing the completions window will
>>>   make the arrow keys operate in the minibuffer.  Actually, maybe we
>>>   should update the completion help text to say that?  That might help a
>>>   lot.
>>
>> Maybe it's possible to squeeze this help text just into one additional line?
>> Something like:
>>
>>   Type 'C-g' to close this window and restore arrows to move point.
>
> Maybe we don't even need an additional line?  How about:
>
> Click or type RET on a completion to select it, or C-g to close this window.
> Type <right>, <left>, <down>, <up> to move point between completions.

Looks good.

>>> - The new completion-eager-display makes *Completions* pop up
>>>   immediately; when this happens, it can be surprising that the arrow
>>>   keys don't work in the minibuffer from the very start of the
>>>   minibuffer session.
>>
>> Then another possible value for 'minibuffer-visible-completions'
>> would be to not rebind left/right arrows when the completions window
>> contains only one column (like on the browser's address bar).
>
> True.  Though I guess that could maybe be the default behavior when
> completions-format=one-column.

Agreed.

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

> (BTW, after writing minibuffer--completions-visible, I'm wondering if
> most of the code which calls (get-buffer-window "*Completions*" 0) is
> actually buggy, because it's not checking completion-reference-buffer.
> Should we replace ~all the calls to (get-buffer-window "*Completions*"
> 0) with (minibuffer--completions-visible) which does check that?)

Looks right, for example for the case of recursive minibuffers.

> +      (minibuffer-exit)))

Typo: 'exit-minibuffer'.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Thu, 17 Jul 2025 20:35:02 GMT) Full text and rfc822 format available.

Message #35 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: sbaugh <at> catern.com
To: Juri Linkov <juri <at> linkov.net>
Cc: Spencer Baugh <sbaugh <at> janestreet.com>, 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected completion
 without rebinding arrow keys
Date: Thu, 17 Jul 2025 20:34:24 +0000 (UTC)
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?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Fri, 18 Jul 2025 06:52:01 GMT) Full text and rfc822 format available.

Message #38 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: sbaugh <at> catern.com
Cc: Spencer Baugh <sbaugh <at> janestreet.com>, 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Fri, 18 Jul 2025 09:38:33 +0300
>>>>>> 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?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Mon, 21 Jul 2025 16:25:02 GMT) Full text and rfc822 format available.

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


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Mon, 21 Jul 2025 16:27:01 GMT) Full text and rfc822 format available.

Message #44 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, [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


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Tue, 22 Jul 2025 12:12:02 GMT) Full text and rfc822 format available.

Message #47 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: sbaugh <at> catern.com, 77253 <at> debbugs.gnu.org, juri <at> linkov.net
Subject: Re: bug#77253: 30.1.50;
 Support RET choosing the selected completion without rebinding arrow
 keys, [PATCH] Make RET in minibuffer choose selected completion
Date: Tue, 22 Jul 2025 15:11:01 +0300
> Cc: sbaugh <at> catern.com, 77253 <at> debbugs.gnu.org
> Date: Mon, 21 Jul 2025 12:26:32 -0400
> From:  Spencer Baugh via "Bug reports for GNU Emacs,
>  the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
> 
> @@ -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)

Can we please not to change commands bound to keys?  That will make
the changes much more backward-compatible.

In any case, this warrants a NEWS entry.

Thanks.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Thu, 24 Jul 2025 17:17:02 GMT) Full text and rfc822 format available.

Message #50 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: Spencer Baugh <sbaugh <at> janestreet.com>, 77253 <at> debbugs.gnu.org,
 sbaugh <at> catern.com
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys, [PATCH] Make RET in minibuffer
 choose selected completion
Date: Thu, 24 Jul 2025 20:10:41 +0300
>> @@ -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)
>
> Can we please not to change commands bound to keys?  That will make
> the changes much more backward-compatible.

First we discussed adding a new option like 'minibuffer-visible-completions'
that affects only RET, not arrow keys.  But now we arrived at a patch that
rebinds the default keybindings.  So I'm not sure how this would affect
the current default behavior.  IIUC, previously after selecting a candidate
with M-down the user needed to type M-RET, and after applying the patch
just RET will be sufficient?  But it was already possible to use RET
with 'minibuffer-completion-auto-choose' equal to t when M-down inserts
the completion candidate to the minibuffer.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Wed, 20 Aug 2025 18:41:01 GMT) Full text and rfc822 format available.

Message #53 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, Eli Zaretskii <eliz <at> gnu.org>, 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys, [PATCH] Make RET in minibuffer
 choose selected completion
Date: Wed, 20 Aug 2025 14:40:44 -0400
Juri Linkov <juri <at> linkov.net> writes:

>>> @@ -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)
>>
>> Can we please not to change commands bound to keys?  That will make
>> the changes much more backward-compatible.
>
> First we discussed adding a new option like 'minibuffer-visible-completions'
> that affects only RET, not arrow keys.  But now we arrived at a patch that
> rebinds the default keybindings.  So I'm not sure how this would affect
> the current default behavior.  IIUC, previously after selecting a candidate
> with M-down the user needed to type M-RET, and after applying the patch
> just RET will be sufficient?

Yes.

BTW, the patch can work either by changing commands bound to keys or by
changing the commands themselves.  I can produce either version, after
some discussion.

> But it was already possible to use RET with
> 'minibuffer-completion-auto-choose' equal to t when M-down inserts the
> completion candidate to the minibuffer.

Ah, right, I forgot that that is on by default.  Hmm...

IMO, this patch supersedes that default.  We would be able to turn
minibuffer-completion-auto-choose off by default:

- With this patch, the user would still be able to type RET in the
minibuffer to choose a completion selected via M-<up>, so that part
wouldn't change.

- Now additionally they will be able to more easily change their mind
about selecting a completion: if they start using M-<up> a few times,
and then decide they want to do more completion, their minibuffer will
be unchanged so they can just resume typing and hitting TAB as normal.
This matches completion-in-region-mode better, since that has never had
minibuffer-completion-auto-choose active.

- If they do want to insert the selected completion into the minibuffer
to edit it, as always they can do that with C-u M-<RET>, which also
works in completion-in-region-mode.

What do you think?  I do think that this patch to make RET work by
default is somewhat pointless if we can't combine it with turning
minibuffer-completion-auto-choose off by default, so I'm hopefully we
can do it.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Wed, 20 Aug 2025 18:42:02 GMT) Full text and rfc822 format available.

Message #56 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: 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Wed, 20 Aug 2025 14:41:43 -0400
[Message part 1 (text/plain, inline)]
Juri Linkov <juri <at> linkov.net> writes:
>> (BTW, after writing minibuffer--completions-visible, I'm wondering if
>> most of the code which calls (get-buffer-window "*Completions*" 0) is
>> actually buggy, because it's not checking completion-reference-buffer.
>> Should we replace ~all the calls to (get-buffer-window "*Completions*"
>> 0) with (minibuffer--completions-visible) which does check that?)
>
> Looks right, for example for the case of recursive minibuffers.

Done in the attached patch.  If it looks good I suggest we land this
first, since it's a nice bugfix anyway.

[0001-Add-minibuffer-completions-visible-and-use-it.patch (text/x-patch, inline)]
From 59e63cf9970f3484047f9e3e3ef3517df5737255 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh <at> janestreet.com>
Date: Wed, 20 Aug 2025 14:27:59 -0400
Subject: [PATCH] Add minibuffer--completions-visible and use it

At various places, instead of just checking that there's any
window displaying a buffer named *Completions*, we should
additionally check that that *Completions* buffer is actually
for the current completion session.
minibuffer--completions-visible does that.

* lisp/comint.el (comint-complete-input-ring)
(comint-dynamic-list-completions): Call
minibuffer--completions-visible.
* lisp/minibuffer.el (minibuffer--completions-visible):
Add. (bug#77253)
(completion--do-completion, completions--post-command-update)
(completions--after-change, minibuffer-hide-completions)
(minibuffer-visible-completions)
(minibuffer-visible-completions--always-bind)
(minibuffer-visible-completions--filter)
(with-minibuffer-completions-window, minibuffer-complete-history)
(minibuffer-complete-defaults): Call
minibuffer--completions-visible.
* lisp/pcomplete.el (pcomplete-show-completions): Call
minibuffer--completions-visible.
* lisp/simple.el (switch-to-completions): Call
minibuffer--completions-visible.
* test/lisp/minibuffer-tests.el (completion-auto-help-test)
(completion-auto-select-test): Call
minibuffer--completions-visible.
---
 lisp/comint.el                |  4 ++--
 lisp/minibuffer.el            | 39 +++++++++++++++++++++--------------
 lisp/pcomplete.el             |  2 +-
 lisp/simple.el                |  4 ++--
 test/lisp/minibuffer-tests.el | 14 ++++++-------
 5 files changed, 35 insertions(+), 28 deletions(-)

diff --git a/lisp/comint.el b/lisp/comint.el
index b9c910eff43..bbb9820c16a 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -1197,7 +1197,7 @@ comint-complete-input-ring
              (ring-elements comint-input-ring)
            (user-error "No history available")))
         (completion-in-region-mode-predicate
-         (lambda () (get-buffer-window "*Completions*" 0))))
+         (lambda () (minibuffer--completions-visible))))
     (completion-in-region
      (comint-line-beginning-position) (point-max)
      (completion-table-with-metadata
@@ -3521,7 +3521,7 @@ comint-dynamic-list-completions
 specifying a common substring for adding the faces
 `completions-first-difference' and `completions-common-part' to
 the completions."
-  (let ((window (get-buffer-window "*Completions*" 0)))
+  (let ((window (minibuffer--completions-visible)))
     (setq completions (sort completions #'string-lessp))
     (if (and (eq last-command this-command)
 	     window (window-live-p window) (window-buffer window)
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index f453b2fee95..1769b98ac6f 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1628,7 +1628,7 @@ completion--do-completion
              ((or completed only-changed-boundaries)
               (cond
                ((pcase completion-auto-help
-                  ('visible (get-buffer-window "*Completions*" 0))
+                  ('visible (minibuffer--completions-visible))
                   ('always t))
                 (minibuffer-completion-help beg end))
                (t (minibuffer-hide-completions)
@@ -2689,13 +2689,13 @@ completions--background-update
 (defun completions--post-command-update ()
   "Update displayed *Completions* buffer after command, once."
   (remove-hook 'post-command-hook #'completions--post-command-update)
-  (when (and completion-eager-update (get-buffer-window "*Completions*" 0))
+  (when (and completion-eager-update (minibuffer--completions-visible))
     (completions--background-update)))
 
 (defun completions--after-change (_start _end _old-len)
   "Update displayed *Completions* buffer after change in buffer contents."
   (when (or completion-auto-deselect completion-eager-update)
-    (when-let* ((window (get-buffer-window "*Completions*" 0)))
+    (when-let* ((window (minibuffer--completions-visible)))
       (when completion-auto-deselect
         (with-selected-window window
           (completions--deselect)))
@@ -2897,7 +2897,7 @@ minibuffer-hide-completions
   ;; FIXME: We could/should use minibuffer-scroll-window here, but it
   ;; can also point to the minibuffer-parent-window, so it's a bit tricky.
   (interactive)
-  (when-let* ((win (get-buffer-window "*Completions*" 0)))
+  (when-let* ((win (minibuffer--completions-visible)))
     (with-selected-window win
       ;; Move point off any completions, so we don't move point there
       ;; again the next time `minibuffer-completion-help' is called.
@@ -3344,18 +3344,25 @@ 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 current *Completions* buffer is visible, if any."
+  (when-let* ((window (get-buffer-window "*Completions*" 0)))
+    (when (eq (buffer-local-value 'completion-reference-buffer
+                                  (window-buffer window))
+              ;; If there's no active minibuffer, we call `window-buffer' on nil, assuming
+              ;; that completion is happening in the selected window.
+              (window-buffer (active-minibuffer-window)))
+      window)))
+
 (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)
@@ -5116,10 +5123,10 @@ with-minibuffer-completions-window
 When used in a minibuffer window, select the window with completions,
 and execute the forms."
   (declare (indent 0) (debug t))
-  `(let ((window (or (get-buffer-window "*Completions*" 0)
+  `(let ((window (or (minibuffer--completions-visible)
                      ;; Make sure we have a completions window.
                      (progn (minibuffer-completion-help)
-                            (get-buffer-window "*Completions*" 0)))))
+                            (minibuffer--completions-visible)))))
      (when window
        (with-selected-window window
          (completion--lazy-insert-strings)
@@ -5214,7 +5221,7 @@ minibuffer-complete-history
             (user-error "No history available"))))
     ;; FIXME: Can we make it work for CRM?
     (let ((completion-in-region-mode-predicate
-           (lambda () (get-buffer-window "*Completions*" 0))))
+           (lambda () (minibuffer--completions-visible))))
       (completion-in-region
        (minibuffer--completion-prompt-end) (point-max)
        (completion-table-with-metadata
@@ -5232,7 +5239,7 @@ minibuffer-complete-defaults
           minibuffer-default (funcall minibuffer-default-add-function)))
   (let ((completions (ensure-list minibuffer-default))
         (completion-in-region-mode-predicate
-         (lambda () (get-buffer-window "*Completions*" 0))))
+         (lambda () (minibuffer--completions-visible))))
     (completion-in-region
      (minibuffer--completion-prompt-end) (point-max)
      (completion-table-with-metadata
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index 43d149d5c90..c3b7f9d52d3 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -1150,7 +1150,7 @@ pcomplete-show-completions
              ((or (eq event 'tab)
                   ;; Needed on a terminal
                   (eq event 9))
-              (let ((win (or (get-buffer-window "*Completions*" 0)
+              (let ((win (or (minibuffer--completions-visible)
                              (display-buffer "*Completions*"
                                              'not-this-window))))
                 (with-selected-window win
diff --git a/lisp/simple.el b/lisp/simple.el
index f7f059793ca..b0f6621b37e 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10598,10 +10598,10 @@ completion-setup-function
 (defun switch-to-completions ()
   "Select the completion list window."
   (interactive)
-  (when-let* ((window (or (get-buffer-window "*Completions*" 0)
+  (when-let* ((window (or (minibuffer--completions-visible)
 		          ;; Make sure we have a completions window.
                           (progn (minibuffer-completion-help)
-                                 (get-buffer-window "*Completions*" 0)))))
+                                 (minibuffer--completions-visible)))))
     (select-window window)
     (completion--lazy-insert-strings)
     (when (bobp)
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index 35cc67b770b..523f2cbf24e 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -458,21 +458,21 @@ completion-auto-help-test
             '("a" "ab" "ac")
           (execute-kbd-macro (kbd "a TAB TAB"))
           (should (equal (car messages) "Complete, but not unique"))
-          (should-not (get-buffer-window "*Completions*" 0))
+          (should-not (minibuffer--completions-visible))
           (execute-kbd-macro (kbd "b TAB"))
           (should (equal (car messages) "Sole completion"))))
       (let ((completion-auto-help t))
         (completing-read-with-minibuffer-setup
             '("a" "ab" "ac")
           (execute-kbd-macro (kbd "a TAB TAB"))
-          (should (get-buffer-window "*Completions*" 0))
+          (should (minibuffer--completions-visible))
           (execute-kbd-macro (kbd "b TAB"))
           (should (equal (car messages) "Sole completion"))))
       (let ((completion-auto-help 'visible))
         (completing-read-with-minibuffer-setup
          '("a" "ab" "ac" "achoo")
          (execute-kbd-macro (kbd "a TAB TAB"))
-         (should (get-buffer-window "*Completions*" 0))
+         (should (minibuffer--completions-visible))
          (execute-kbd-macro (kbd "ch TAB"))
          (should (equal (car messages) "Sole completion")))))))
 
@@ -481,19 +481,19 @@ completion-auto-select-test
     (completing-read-with-minibuffer-setup
         '("aa" "ab" "ac")
       (execute-kbd-macro (kbd "a TAB"))
-      (should (and (get-buffer-window "*Completions*" 0)
+      (should (and (minibuffer--completions-visible)
                    (eq (current-buffer) (get-buffer "*Completions*"))))
       (execute-kbd-macro (kbd "TAB TAB TAB"))
-      (should (and (get-buffer-window "*Completions*" 0)
+      (should (and (minibuffer--completions-visible)
                    (eq (current-buffer) (get-buffer " *Minibuf-1*"))))
       (execute-kbd-macro (kbd "S-TAB"))
-      (should (and (get-buffer-window "*Completions*" 0)
+      (should (and (minibuffer--completions-visible)
                    (eq (current-buffer) (get-buffer "*Completions*"))))))
   (let ((completion-auto-select 'second-tab))
     (completing-read-with-minibuffer-setup
         '("aa" "ab" "ac")
       (execute-kbd-macro (kbd "a TAB"))
-      (should (and (get-buffer-window "*Completions*" 0)
+      (should (and (minibuffer--completions-visible)
                    (not (eq (current-buffer) (get-buffer "*Completions*")))))
       (execute-kbd-macro (kbd "TAB TAB"))
       (should (eq (current-buffer) (get-buffer "*Completions*"))))))
-- 
2.43.7


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Thu, 21 Aug 2025 06:55:02 GMT) Full text and rfc822 format available.

Message #59 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: sbaugh <at> catern.com, Eli Zaretskii <eliz <at> gnu.org>, 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys, [PATCH] Make RET in minibuffer
 choose selected completion
Date: Thu, 21 Aug 2025 09:51:22 +0300
>>>> @@ -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)
>>>
>>> Can we please not to change commands bound to keys?  That will make
>>> the changes much more backward-compatible.
>>
>> First we discussed adding a new option like 'minibuffer-visible-completions'
>> that affects only RET, not arrow keys.  But now we arrived at a patch that
>> rebinds the default keybindings.  So I'm not sure how this would affect
>> the current default behavior.  IIUC, previously after selecting a candidate
>> with M-down the user needed to type M-RET, and after applying the patch
>> just RET will be sufficient?
>
> Yes.
>
> BTW, the patch can work either by changing commands bound to keys or by
> changing the commands themselves.  I can produce either version, after
> some discussion.

It looks like changing the commands themselves is more preferable
than changing traditional keybindings.

>> But it was already possible to use RET with
>> 'minibuffer-completion-auto-choose' equal to t when M-down inserts the
>> completion candidate to the minibuffer.
>
> Ah, right, I forgot that that is on by default.  Hmm...
>
> IMO, this patch supersedes that default.  We would be able to turn
> minibuffer-completion-auto-choose off by default:
>
> - With this patch, the user would still be able to type RET in the
> minibuffer to choose a completion selected via M-<up>, so that part
> wouldn't change.
>
> - Now additionally they will be able to more easily change their mind
> about selecting a completion: if they start using M-<up> a few times,
> and then decide they want to do more completion, their minibuffer will
> be unchanged so they can just resume typing and hitting TAB as normal.
> This matches completion-in-region-mode better, since that has never had
> minibuffer-completion-auto-choose active.
>
> - If they do want to insert the selected completion into the minibuffer
> to edit it, as always they can do that with C-u M-<RET>, which also
> works in completion-in-region-mode.
>
> What do you think?  I do think that this patch to make RET work by
> default is somewhat pointless if we can't combine it with turning
> minibuffer-completion-auto-choose off by default, so I'm hopefully we
> can do it.

The default value t of minibuffer-completion-auto-choose
was intended to emulate the behavior of completion in web browsers
where navigating with up/down arrows inserts the completion candidates
into the editing area that corresponds to the minibuffer.

However, this doesn't prevent from disabling minibuffer-completion-auto-choose
by default, provided there is an easy way to insert the completion
candidate into the minibuffer.

For example, in icomplete-mode 'C-M-i' (icomplete-force-complete)
inserts the current completion candidate into the minibuffer.

Since 'C-u RET' does the same for the completion buffer, it seems
we can disable minibuffer-completion-auto-choose by default.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Thu, 21 Aug 2025 16:40:01 GMT) Full text and rfc822 format available.

Message #62 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Thu, 21 Aug 2025 19:38:32 +0300
>>> (BTW, after writing minibuffer--completions-visible, I'm wondering if
>>> most of the code which calls (get-buffer-window "*Completions*" 0) is
>>> actually buggy, because it's not checking completion-reference-buffer.
>>> Should we replace ~all the calls to (get-buffer-window "*Completions*"
>>> 0) with (minibuffer--completions-visible) which does check that?)
>>
>> Looks right, for example for the case of recursive minibuffers.
>
> Done in the attached patch.  If it looks good I suggest we land this
> first, since it's a nice bugfix anyway.

Sorry, the patch doesn't apply cleanly on current master.
BTW, while updating the patch, please also
fit the docstring and comments into 72 columns.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Thu, 21 Aug 2025 16:49:02 GMT) Full text and rfc822 format available.

Message #65 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: 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Thu, 21 Aug 2025 12:48:31 -0400
[Message part 1 (text/plain, inline)]
Juri Linkov <juri <at> linkov.net> writes:

>>>> (BTW, after writing minibuffer--completions-visible, I'm wondering if
>>>> most of the code which calls (get-buffer-window "*Completions*" 0) is
>>>> actually buggy, because it's not checking completion-reference-buffer.
>>>> Should we replace ~all the calls to (get-buffer-window "*Completions*"
>>>> 0) with (minibuffer--completions-visible) which does check that?)
>>>
>>> Looks right, for example for the case of recursive minibuffers.
>>
>> Done in the attached patch.  If it looks good I suggest we land this
>> first, since it's a nice bugfix anyway.
>
> Sorry, the patch doesn't apply cleanly on current master.
> BTW, while updating the patch, please also
> fit the docstring and comments into 72 columns.

Updated and filled that long comment, sorry.

(The docstring is still over 72 columns, but it's under 80 characters in
the first line, so I think it's still within the usual style)

[0001-Add-minibuffer-completions-visible-and-use-it.patch (text/x-patch, inline)]
From 379e427cb6b3828b47fbf4f1cb6b1a1d1ac88827 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh <at> janestreet.com>
Date: Wed, 20 Aug 2025 14:27:59 -0400
Subject: [PATCH] Add minibuffer--completions-visible and use it

At various places, instead of just checking that there's any
window displaying a buffer named *Completions*, we should
additionally check that that *Completions* buffer is actually
for the current completion session.
minibuffer--completions-visible does that.

* lisp/comint.el (comint-complete-input-ring)
(comint-dynamic-list-completions): Call
minibuffer--completions-visible.
* lisp/minibuffer.el (minibuffer--completions-visible):
Add. (bug#77253)
(completion--do-completion, completions--post-command-update)
(completions--after-change, minibuffer-hide-completions)
(minibuffer-visible-completions)
(minibuffer-visible-completions--always-bind)
(minibuffer-visible-completions--filter)
(with-minibuffer-completions-window, minibuffer-complete-history)
(minibuffer-complete-defaults): Call
minibuffer--completions-visible.
* lisp/pcomplete.el (pcomplete-show-completions): Call
minibuffer--completions-visible.
* lisp/simple.el (switch-to-completions): Call
minibuffer--completions-visible.
* test/lisp/minibuffer-tests.el (completion-auto-help-test)
(completion-auto-select-test): Call
minibuffer--completions-visible.
---
 lisp/comint.el                |  4 ++--
 lisp/minibuffer.el            | 40 +++++++++++++++++++++--------------
 lisp/pcomplete.el             |  2 +-
 lisp/simple.el                |  4 ++--
 test/lisp/minibuffer-tests.el | 14 ++++++------
 5 files changed, 36 insertions(+), 28 deletions(-)

diff --git a/lisp/comint.el b/lisp/comint.el
index b9c910eff43..bbb9820c16a 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -1197,7 +1197,7 @@ comint-complete-input-ring
              (ring-elements comint-input-ring)
            (user-error "No history available")))
         (completion-in-region-mode-predicate
-         (lambda () (get-buffer-window "*Completions*" 0))))
+         (lambda () (minibuffer--completions-visible))))
     (completion-in-region
      (comint-line-beginning-position) (point-max)
      (completion-table-with-metadata
@@ -3521,7 +3521,7 @@ comint-dynamic-list-completions
 specifying a common substring for adding the faces
 `completions-first-difference' and `completions-common-part' to
 the completions."
-  (let ((window (get-buffer-window "*Completions*" 0)))
+  (let ((window (minibuffer--completions-visible)))
     (setq completions (sort completions #'string-lessp))
     (if (and (eq last-command this-command)
 	     window (window-live-p window) (window-buffer window)
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index f453b2fee95..37af93c3ae8 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1628,7 +1628,7 @@ completion--do-completion
              ((or completed only-changed-boundaries)
               (cond
                ((pcase completion-auto-help
-                  ('visible (get-buffer-window "*Completions*" 0))
+                  ('visible (minibuffer--completions-visible))
                   ('always t))
                 (minibuffer-completion-help beg end))
                (t (minibuffer-hide-completions)
@@ -2689,13 +2689,13 @@ completions--background-update
 (defun completions--post-command-update ()
   "Update displayed *Completions* buffer after command, once."
   (remove-hook 'post-command-hook #'completions--post-command-update)
-  (when (and completion-eager-update (get-buffer-window "*Completions*" 0))
+  (when (and completion-eager-update (minibuffer--completions-visible))
     (completions--background-update)))
 
 (defun completions--after-change (_start _end _old-len)
   "Update displayed *Completions* buffer after change in buffer contents."
   (when (or completion-auto-deselect completion-eager-update)
-    (when-let* ((window (get-buffer-window "*Completions*" 0)))
+    (when-let* ((window (minibuffer--completions-visible)))
       (when completion-auto-deselect
         (with-selected-window window
           (completions--deselect)))
@@ -2897,7 +2897,7 @@ minibuffer-hide-completions
   ;; FIXME: We could/should use minibuffer-scroll-window here, but it
   ;; can also point to the minibuffer-parent-window, so it's a bit tricky.
   (interactive)
-  (when-let* ((win (get-buffer-window "*Completions*" 0)))
+  (when-let* ((win (minibuffer--completions-visible)))
     (with-selected-window win
       ;; Move point off any completions, so we don't move point there
       ;; again the next time `minibuffer-completion-help' is called.
@@ -3344,18 +3344,26 @@ 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 current *Completions* buffer is visible, if any."
+  (when-let* ((window (get-buffer-window "*Completions*" 0)))
+    (when (eq (buffer-local-value 'completion-reference-buffer
+                                  (window-buffer window))
+              ;; If there's no active minibuffer, we call
+              ;; `window-buffer' on nil, assuming that completion is
+              ;; happening in the selected window.
+              (window-buffer (active-minibuffer-window)))
+      window)))
+
 (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)
@@ -5116,10 +5124,10 @@ with-minibuffer-completions-window
 When used in a minibuffer window, select the window with completions,
 and execute the forms."
   (declare (indent 0) (debug t))
-  `(let ((window (or (get-buffer-window "*Completions*" 0)
+  `(let ((window (or (minibuffer--completions-visible)
                      ;; Make sure we have a completions window.
                      (progn (minibuffer-completion-help)
-                            (get-buffer-window "*Completions*" 0)))))
+                            (minibuffer--completions-visible)))))
      (when window
        (with-selected-window window
          (completion--lazy-insert-strings)
@@ -5214,7 +5222,7 @@ minibuffer-complete-history
             (user-error "No history available"))))
     ;; FIXME: Can we make it work for CRM?
     (let ((completion-in-region-mode-predicate
-           (lambda () (get-buffer-window "*Completions*" 0))))
+           (lambda () (minibuffer--completions-visible))))
       (completion-in-region
        (minibuffer--completion-prompt-end) (point-max)
        (completion-table-with-metadata
@@ -5232,7 +5240,7 @@ minibuffer-complete-defaults
           minibuffer-default (funcall minibuffer-default-add-function)))
   (let ((completions (ensure-list minibuffer-default))
         (completion-in-region-mode-predicate
-         (lambda () (get-buffer-window "*Completions*" 0))))
+         (lambda () (minibuffer--completions-visible))))
     (completion-in-region
      (minibuffer--completion-prompt-end) (point-max)
      (completion-table-with-metadata
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index 43d149d5c90..c3b7f9d52d3 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -1150,7 +1150,7 @@ pcomplete-show-completions
              ((or (eq event 'tab)
                   ;; Needed on a terminal
                   (eq event 9))
-              (let ((win (or (get-buffer-window "*Completions*" 0)
+              (let ((win (or (minibuffer--completions-visible)
                              (display-buffer "*Completions*"
                                              'not-this-window))))
                 (with-selected-window win
diff --git a/lisp/simple.el b/lisp/simple.el
index f7f059793ca..b0f6621b37e 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10598,10 +10598,10 @@ completion-setup-function
 (defun switch-to-completions ()
   "Select the completion list window."
   (interactive)
-  (when-let* ((window (or (get-buffer-window "*Completions*" 0)
+  (when-let* ((window (or (minibuffer--completions-visible)
 		          ;; Make sure we have a completions window.
                           (progn (minibuffer-completion-help)
-                                 (get-buffer-window "*Completions*" 0)))))
+                                 (minibuffer--completions-visible)))))
     (select-window window)
     (completion--lazy-insert-strings)
     (when (bobp)
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index 35cc67b770b..523f2cbf24e 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -458,21 +458,21 @@ completion-auto-help-test
             '("a" "ab" "ac")
           (execute-kbd-macro (kbd "a TAB TAB"))
           (should (equal (car messages) "Complete, but not unique"))
-          (should-not (get-buffer-window "*Completions*" 0))
+          (should-not (minibuffer--completions-visible))
           (execute-kbd-macro (kbd "b TAB"))
           (should (equal (car messages) "Sole completion"))))
       (let ((completion-auto-help t))
         (completing-read-with-minibuffer-setup
             '("a" "ab" "ac")
           (execute-kbd-macro (kbd "a TAB TAB"))
-          (should (get-buffer-window "*Completions*" 0))
+          (should (minibuffer--completions-visible))
           (execute-kbd-macro (kbd "b TAB"))
           (should (equal (car messages) "Sole completion"))))
       (let ((completion-auto-help 'visible))
         (completing-read-with-minibuffer-setup
          '("a" "ab" "ac" "achoo")
          (execute-kbd-macro (kbd "a TAB TAB"))
-         (should (get-buffer-window "*Completions*" 0))
+         (should (minibuffer--completions-visible))
          (execute-kbd-macro (kbd "ch TAB"))
          (should (equal (car messages) "Sole completion")))))))
 
@@ -481,19 +481,19 @@ completion-auto-select-test
     (completing-read-with-minibuffer-setup
         '("aa" "ab" "ac")
       (execute-kbd-macro (kbd "a TAB"))
-      (should (and (get-buffer-window "*Completions*" 0)
+      (should (and (minibuffer--completions-visible)
                    (eq (current-buffer) (get-buffer "*Completions*"))))
       (execute-kbd-macro (kbd "TAB TAB TAB"))
-      (should (and (get-buffer-window "*Completions*" 0)
+      (should (and (minibuffer--completions-visible)
                    (eq (current-buffer) (get-buffer " *Minibuf-1*"))))
       (execute-kbd-macro (kbd "S-TAB"))
-      (should (and (get-buffer-window "*Completions*" 0)
+      (should (and (minibuffer--completions-visible)
                    (eq (current-buffer) (get-buffer "*Completions*"))))))
   (let ((completion-auto-select 'second-tab))
     (completing-read-with-minibuffer-setup
         '("aa" "ab" "ac")
       (execute-kbd-macro (kbd "a TAB"))
-      (should (and (get-buffer-window "*Completions*" 0)
+      (should (and (minibuffer--completions-visible)
                    (not (eq (current-buffer) (get-buffer "*Completions*")))))
       (execute-kbd-macro (kbd "TAB TAB"))
       (should (eq (current-buffer) (get-buffer "*Completions*"))))))
-- 
2.43.7


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Thu, 21 Aug 2025 17:13:02 GMT) Full text and rfc822 format available.

Message #68 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys
Date: Thu, 21 Aug 2025 20:11:08 +0300
>>>>> (BTW, after writing minibuffer--completions-visible, I'm wondering if
>>>>> most of the code which calls (get-buffer-window "*Completions*" 0) is
>>>>> actually buggy, because it's not checking completion-reference-buffer.
>>>>> Should we replace ~all the calls to (get-buffer-window "*Completions*"
>>>>> 0) with (minibuffer--completions-visible) which does check that?)
>>>>
>>>> Looks right, for example for the case of recursive minibuffers.
>>>
>>> Done in the attached patch.  If it looks good I suggest we land this
>>> first, since it's a nice bugfix anyway.
>>
>> Sorry, the patch doesn't apply cleanly on current master.
>> BTW, while updating the patch, please also
>> fit the docstring and comments into 72 columns.
>
> Updated and filled that long comment, sorry.

Now pushed.  Thanks for submitting a separate patch
for this bugfix.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Thu, 21 Aug 2025 18:46:02 GMT) Full text and rfc822 format available.

Message #71 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, Eli Zaretskii <eliz <at> gnu.org>, 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys, [PATCH] Make RET in minibuffer
 choose selected completion
Date: Thu, 21 Aug 2025 14:45:05 -0400
[Message part 1 (text/plain, inline)]
Juri Linkov <juri <at> linkov.net> writes:

>>>>> @@ -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)
>>>>
>>>> Can we please not to change commands bound to keys?  That will make
>>>> the changes much more backward-compatible.
>>>
>>> First we discussed adding a new option like 'minibuffer-visible-completions'
>>> that affects only RET, not arrow keys.  But now we arrived at a patch that
>>> rebinds the default keybindings.  So I'm not sure how this would affect
>>> the current default behavior.  IIUC, previously after selecting a candidate
>>> with M-down the user needed to type M-RET, and after applying the patch
>>> just RET will be sufficient?
>>
>> Yes.
>>
>> BTW, the patch can work either by changing commands bound to keys or by
>> changing the commands themselves.  I can produce either version, after
>> some discussion.
>
> It looks like changing the commands themselves is more preferable
> than changing traditional keybindings.

For minibuffers with require-match completion, this can be done by
changing the existing command bound to RET:
minibuffer-complete-and-exit.

For minibuffers with nil require-match completion, RET is bound to
exit-minibuffer, and changing exit-minibuffer to have this logic is
risky, I think.  I can handle that case by adding a new
minibuffer-completion-exit which wraps exit-minibuffer and bind RET to
it.

Done in the attached patch.

>>> But it was already possible to use RET with
>>> 'minibuffer-completion-auto-choose' equal to t when M-down inserts the
>>> completion candidate to the minibuffer.
>>
>> Ah, right, I forgot that that is on by default.  Hmm...
>>
>> IMO, this patch supersedes that default.  We would be able to turn
>> minibuffer-completion-auto-choose off by default:
>>
>> - With this patch, the user would still be able to type RET in the
>> minibuffer to choose a completion selected via M-<up>, so that part
>> wouldn't change.
>>
>> - Now additionally they will be able to more easily change their mind
>> about selecting a completion: if they start using M-<up> a few times,
>> and then decide they want to do more completion, their minibuffer will
>> be unchanged so they can just resume typing and hitting TAB as normal.
>> This matches completion-in-region-mode better, since that has never had
>> minibuffer-completion-auto-choose active.
>>
>> - If they do want to insert the selected completion into the minibuffer
>> to edit it, as always they can do that with C-u M-<RET>, which also
>> works in completion-in-region-mode.
>>
>> What do you think?  I do think that this patch to make RET work by
>> default is somewhat pointless if we can't combine it with turning
>> minibuffer-completion-auto-choose off by default, so I'm hopefully we
>> can do it.
>
> The default value t of minibuffer-completion-auto-choose
> was intended to emulate the behavior of completion in web browsers
> where navigating with up/down arrows inserts the completion candidates
> into the editing area that corresponds to the minibuffer.
>
> However, this doesn't prevent from disabling minibuffer-completion-auto-choose
> by default, provided there is an easy way to insert the completion
> candidate into the minibuffer.
>
> For example, in icomplete-mode 'C-M-i' (icomplete-force-complete)
> inserts the current completion candidate into the minibuffer.
>
> Since 'C-u RET' does the same for the completion buffer, it seems
> we can disable minibuffer-completion-auto-choose by default.

How about this patch?

It doesn't add support for C-u RET inserting the completion, you have to
use C-u M-RET as you already can today.  Do you think that's fine?  It
seems a bit safer.

Also no NEWS entry still, will add one once we settle on a patch.

It occurs to me now that we could maybe also make RET choose the
selected completion by default in completion-in-region-mode, though that
would require a :filter keymap entry like minibuffer-visible-completions
has.  completion-auto-deselect makes this viable, by the same reasoning
I mentioned earlier in the bug.  So maybe that's also interesting to do?

[0001-Make-RET-in-minibuffer-choose-selected-completion.patch (text/x-patch, inline)]
From 9b1988e3836952e9d954325d8004aa89f1d7f282 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh <at> janestreet.com>
Date: Thu, 21 Aug 2025 14:33:23 -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.  This lets us default
minibuffer-completion-auto-choose to nil.

For minibuffers with require-match completion, this can be done
by changing the existing command bound to RET.  For minibuffers
with nil require-match completion, RET was previously bound to
exit-minibuffer, and changing exit-minibuffer to have this logic
is risky.  We handle that case by adding a new
minibuffer-completion-exit which wraps exit-minibuffer and bind
RET to it.

* lisp/minibuffer.el (minibuffer-insert-completion-if-selected):
Add.
(minibuffer-complete-and-exit): Call
minibuffer-insert-completion-if-selected. (bug#77253)
(minibuffer-completion-exit): Add, just calling
minibuffer-insert-completion-if-selected before exit-minibuffer.
(minibuffer-local-completion-map): Bind RET to
minibuffer-completion-exit, overriding exit-minibuffer.
(minibuffer-completion-auto-choose): Default to nil.
---
 lisp/minibuffer.el | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 37af93c3ae8..c786c1b0948 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2009,6 +2009,7 @@ minibuffer-complete-and-exit
  `minibuffer-confirm-exit-commands', and accept the input
  otherwise."
   (interactive)
+  (minibuffer-insert-completion-if-selected)
   (completion-complete-and-exit (minibuffer--completion-prompt-end) (point-max)
                                 #'exit-minibuffer))
 
@@ -3227,6 +3228,12 @@ completion-help-at-point
   (define-key map "\n" 'exit-minibuffer)
   (define-key map "\r" 'exit-minibuffer))
 
+(defun minibuffer-completion-exit ()
+  "Call `exit-minibuffer', inserting the selected completion first if any."
+  (interactive)
+  (minibuffer-insert-completion-if-selected)
+  (exit-minibuffer))
+
 (defvar-keymap minibuffer-local-completion-map
   :doc "Local keymap for minibuffer input with completion."
   :parent minibuffer-local-map
@@ -3236,6 +3243,7 @@ minibuffer-local-completion-map
   ;; another binding for it.
   ;; "M-TAB"  #'minibuffer-force-complete
   "SPC"       #'minibuffer-complete-word
+  "RET"       #'minibuffer-completion-exit
   "?"         #'minibuffer-completion-help
   "<prior>"   #'switch-to-completions
   "M-v"       #'switch-to-completions
@@ -3355,6 +3363,17 @@ minibuffer--completions-visible
               (window-buffer (active-minibuffer-window)))
       window)))
 
+(defun minibuffer-insert-completion-if-selected ()
+  "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 t t)
+        t))))
+
 (defun minibuffer-visible-completions--filter (cmd)
   "Return CMD if `minibuffer-visible-completions' bindings should be active."
   (if minibuffer-visible-completions--always-bind
@@ -5133,13 +5152,13 @@ with-minibuffer-completions-window
          (completion--lazy-insert-strings)
          ,@body))))
 
-(defcustom minibuffer-completion-auto-choose t
+(defcustom minibuffer-completion-auto-choose nil
   "Non-nil means to automatically insert completions to the minibuffer.
 When non-nil, then `minibuffer-next-completion' and
 `minibuffer-previous-completion' will insert the completion
 selected by these commands to the minibuffer."
   :type 'boolean
-  :version "29.1")
+  :version "31.1")
 
 (defun minibuffer-next-completion (&optional n vertical)
   "Move to the next item in its completions window from the minibuffer.
-- 
2.43.7


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Fri, 22 Aug 2025 06:53:02 GMT) Full text and rfc822 format available.

Message #74 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: sbaugh <at> catern.com, Eli Zaretskii <eliz <at> gnu.org>, 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys, [PATCH] Make RET in minibuffer
 choose selected completion
Date: Fri, 22 Aug 2025 09:48:12 +0300
> How about this patch?

Thanks, I tested your patch, and the new behavior of RET is more intuitive.

Does this make M-RET mostly obsolete?  Or at least supersedes it?
Then we could replace M-RET with RET in the completion help text:

  Click or type M-RET on a completion to select it.

> It doesn't add support for C-u RET inserting the completion, you have to
> use C-u M-RET as you already can today.  Do you think that's fine?  It
> seems a bit safer.

It's possible to add a prefix argument to the commands bound to RET.
Or maybe the existing 'C-u M-RET' would be sufficient?
Unless we decide to make M-RET obsolete.

> Also no NEWS entry still, will add one once we settle on a patch.

It would be interesting to see how would you describe this change
in NEWS for users.

> It occurs to me now that we could maybe also make RET choose the
> selected completion by default in completion-in-region-mode, though that
> would require a :filter keymap entry like minibuffer-visible-completions
> has.  completion-auto-deselect makes this viable, by the same reasoning
> I mentioned earlier in the bug.  So maybe that's also interesting to do?

Definitely, this would be needed for consistency with the minibuffer behavior.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Fri, 22 Aug 2025 19:08:02 GMT) Full text and rfc822 format available.

Message #77 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, Eli Zaretskii <eliz <at> gnu.org>, 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys, [PATCH] Make RET in minibuffer
 choose selected completion
Date: Fri, 22 Aug 2025 15:07:29 -0400
[Message part 1 (text/plain, inline)]
Juri Linkov <juri <at> linkov.net> writes:

>> How about this patch?
>
> Thanks, I tested your patch, and the new behavior of RET is more intuitive.
>
> Does this make M-RET mostly obsolete?  Or at least supersedes it?

It does, though of course we should keep the binding around for
compatibility - it doesn't hurt to have it, and also it's sometimes a
bit convenient to hold M- down while hitting <down> <down> <down> RET.

> Then we could replace M-RET with RET in the completion help text:
>
>   Click or type M-RET on a completion to select it.

True.  Did this partially in the attached patch.  Now in-buffer
completion says RET in the completion help text.  (And the code to
render the completion help text is also a bit simpler)

minibuffer completion still says M-RET, because it's a bit trickier,
since it has some different commands bound to RET... doesn't seem too
bad, anyway, M-RET still works and we can fix it up more later if we
think of a good way.

>> It doesn't add support for C-u RET inserting the completion, you have to
>> use C-u M-RET as you already can today.  Do you think that's fine?  It
>> seems a bit safer.
>
> It's possible to add a prefix argument to the commands bound to RET.
> Or maybe the existing 'C-u M-RET' would be sufficient?
> Unless we decide to make M-RET obsolete.

Added support for this to my new/changed commands.

>> Also no NEWS entry still, will add one once we settle on a patch.
>
> It would be interesting to see how would you describe this change
> in NEWS for users.

Done.

>> It occurs to me now that we could maybe also make RET choose the
>> selected completion by default in completion-in-region-mode, though that
>> would require a :filter keymap entry like minibuffer-visible-completions
>> has.  completion-auto-deselect makes this viable, by the same reasoning
>> I mentioned earlier in the bug.  So maybe that's also interesting to do?
>
> Definitely, this would be needed for consistency with the minibuffer behavior.

Agreed, done.

In fact, now that the RET binding is provided also for in-buffer
completion, I think the RET binding provided by
minibuffer-visible-completions can be dropped.  So I did that in the
latest version of the patch.

Also included some new tests.

[0001-Make-RET-choose-the-selected-completion.patch (text/x-patch, inline)]
From 2270c2181abe5cd83b9e33763b7af9a9d975caaf Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh <at> janestreet.com>
Date: Thu, 21 Aug 2025 14:33:23 -0400
Subject: [PATCH] Make RET choose the 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.  This lets us default
minibuffer-completion-auto-choose to nil.

For minibuffers with require-match completion, this can be done
by changing the existing command bound to RET.  For minibuffers
with nil require-match completion, RET was previously bound to
exit-minibuffer, and changing exit-minibuffer to have this logic
is risky.  We handle that case by adding a new
minibuffer-completion-exit which wraps exit-minibuffer and bind
RET to it.

* lisp/minibuffer.el (minibuffer-insert-completion-if-selected)
(minibuffer-completion-exit, completion--selected-candidate):
Add.
(minibuffer-complete-and-exit): Call
minibuffer-choose-completion. (bug#77253)
(minibuffer-local-completion-map): Bind RET to
minibuffer-completion-exit, overriding exit-minibuffer.
(completion-in-region-mode-map): Bind RET to
minibuffer-choose-completion when there's a selected candidate.
(minibuffer-completion-auto-choose): Default to nil.
(minibuffer-visible-completions--filter)
(minibuffer-visible-completions-map): Delete RET binding, no
longer necessary.
* lisp/simple.el (completion-setup-function): Update completion
help text to show more correct bindings.
* test/lisp/minibuffer-tests.el (completions-header-format-test)
(minibuffer-next-completion): Set
minibuffer-completion-auto-choose=t explicitly.
(with-minibuffer-setup, minibuffer-completion-RET-prefix)
(completion-in-region-next-completion): Add new tests.
* etc/NEWS: Announce.
---
 etc/NEWS                      |  8 ++++++
 lisp/minibuffer.el            | 50 +++++++++++++++++++++++++--------
 lisp/simple.el                | 32 +++++++++------------
 test/lisp/minibuffer-tests.el | 53 ++++++++++++++++++++++++++++++++++-
 4 files changed, 112 insertions(+), 31 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 27244565d19..058f0e896eb 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -183,6 +183,14 @@ different completion categories by customizing
 be updated as you type, or nil to suppress this always.  Note that for
 large or inefficient completion tables this can slow down typing.
 
+---
+*** RET chooses the completion selected with M-<up>/M-<down>
+If a completion candidate is selected with M-<up> or M-<down>, hitting
+RET will exit completion with that as the result.  This works both in
+minibuffer completion and in-buffer completion.  This supersedes
+'minibuffer-completion-auto-choose', which previously provided similar
+behavior; that variable is now nil by default.
+
 +++
 *** New user option 'completion-pcm-leading-wildcard'.
 This option configures how the partial-completion style does completion.
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 37bfbdc0765..8a617b7168f 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1994,12 +1994,17 @@ minibuffer--require-match
 (defvar minibuffer--original-buffer nil
   "Buffer that was current when `completing-read' was called.")
 
-(defun minibuffer-complete-and-exit ()
+(defun minibuffer-complete-and-exit (&optional no-exit)
   "Exit if the minibuffer contains a valid completion.
 Otherwise, try to complete the minibuffer contents.  If
 completion leads to a valid completion, a repetition of this
 command will exit.
 
+If a completion candidate is selected in the *Completions* buffer, it
+will be inserted in the minibuffer first.  If NO-EXIT is non-nil, don't
+actually exit the minibuffer, just insert the selected completion if
+any.
+
 If `minibuffer-completion-confirm' is `confirm', do not try to
  complete; instead, ask for confirmation and accept any input if
  confirmed.
@@ -2008,9 +2013,12 @@ minibuffer-complete-and-exit
  preceding minibuffer command was a member of
  `minibuffer-confirm-exit-commands', and accept the input
  otherwise."
-  (interactive)
-  (completion-complete-and-exit (minibuffer--completion-prompt-end) (point-max)
-                                #'exit-minibuffer))
+  (interactive "P")
+  (when (completion--selected-candidate)
+    (minibuffer-choose-completion t t))
+  (unless no-exit
+    (completion-complete-and-exit (minibuffer--completion-prompt-end) (point-max)
+                                  #'exit-minibuffer)))
 
 (defun completion-complete-and-exit (beg end exit-function)
   (completion--complete-and-exit
@@ -3021,6 +3029,11 @@ completion-in-region-mode-map
   ;; completion-at-point called directly.
   "M-?" #'completion-help-at-point
   "TAB" #'completion-at-point
+  ;; If a completion is selected, RET will choose it.
+  "RET" `(menu-item "" minibuffer-choose-completion :filter
+                    ,(lambda (cmd)
+                       (when (completion--selected-candidate)
+                         cmd)))
   "M-<up>"   #'minibuffer-previous-completion
   "M-<down>" #'minibuffer-next-completion
   "M-RET"    #'minibuffer-choose-completion)
@@ -3227,6 +3240,17 @@ completion-help-at-point
   (define-key map "\n" 'exit-minibuffer)
   (define-key map "\r" 'exit-minibuffer))
 
+(defun minibuffer-completion-exit (&optional no-exit)
+  "Call `exit-minibuffer', inserting the selected completion first if any.
+
+If NO-EXIT is non-nil, don't `exit-minibuffer', just insert the selected
+completion."
+  (interactive "P")
+  (when (completion--selected-candidate)
+    (minibuffer-choose-completion t t))
+  (unless no-exit
+    (exit-minibuffer)))
+
 (defvar-keymap minibuffer-local-completion-map
   :doc "Local keymap for minibuffer input with completion."
   :parent minibuffer-local-map
@@ -3236,6 +3260,7 @@ minibuffer-local-completion-map
   ;; another binding for it.
   ;; "M-TAB"  #'minibuffer-force-complete
   "SPC"       #'minibuffer-complete-word
+  "RET"       #'minibuffer-completion-exit
   "?"         #'minibuffer-completion-help
   "<prior>"   #'switch-to-completions
   "M-v"       #'switch-to-completions
@@ -3355,16 +3380,18 @@ minibuffer--completions-visible
               (window-buffer (active-minibuffer-window)))
       window)))
 
+(defun completion--selected-candidate ()
+  "Return the selected completion candidate if any."
+  (when-let* ((window (minibuffer--completions-visible)))
+    (with-current-buffer (window-buffer window)
+      (get-text-property (point) 'completion--string))))
+
 (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 (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))))
+      cmd)))
 
 (defun minibuffer-visible-completions--bind (binding)
   "Use BINDING when completions are visible.
@@ -3380,7 +3407,6 @@ minibuffer-visible-completions-map
   "<right>" (minibuffer-visible-completions--bind #'minibuffer-next-completion)
   "<up>"    (minibuffer-visible-completions--bind #'minibuffer-previous-line-completion)
   "<down>"  (minibuffer-visible-completions--bind #'minibuffer-next-line-completion)
-  "RET"     (minibuffer-visible-completions--bind #'minibuffer-choose-completion-or-exit)
   "C-g"     (minibuffer-visible-completions--bind #'minibuffer-hide-completions))
 
 ;;; Completion tables.
@@ -5147,13 +5173,13 @@ with-minibuffer-completions-window
          (completion--lazy-insert-strings)
          ,@body))))
 
-(defcustom minibuffer-completion-auto-choose t
+(defcustom minibuffer-completion-auto-choose nil
   "Non-nil means to automatically insert completions to the minibuffer.
 When non-nil, then `minibuffer-next-completion' and
 `minibuffer-previous-completion' will insert the completion
 selected by these commands to the minibuffer."
   :type 'boolean
-  :version "29.1")
+  :version "31.1")
 
 (defun minibuffer-next-completion (&optional n vertical)
   "Move to the next item in its completions window from the minibuffer.
diff --git a/lisp/simple.el b/lisp/simple.el
index b0f6621b37e..2a13d59e5cd 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10570,28 +10570,24 @@ completion-setup-function
       ;; Maybe insert help string.
       (when completion-show-help
 	(goto-char (point-min))
-        (if minibuffer-visible-completions
-            (let ((helps
-                   (with-current-buffer (window-buffer (active-minibuffer-window))
-                     (let ((minibuffer-visible-completions--always-bind t))
-                       (list
-                        (substitute-command-keys
-	                 (if (display-mouse-p)
-	                     "Click or type \\[minibuffer-choose-completion-or-exit] on a completion to select it.\n"
-                           "Type \\[minibuffer-choose-completion-or-exit] on a completion to select it.\n"))
+        (let ((helps
+               (with-current-buffer (window-buffer (active-minibuffer-window))
+                 (let ((minibuffer-visible-completions--always-bind t))
+                   (list
+                    (substitute-command-keys
+	             (if (display-mouse-p)
+	                 "Click or type \\[minibuffer-choose-completion] on a completion to select it.\n"
+                       "Type \\[minibuffer-choose-completion] on a completion to select it.\n"))
+                    (if minibuffer-visible-completions
                         (substitute-command-keys
 		         "Type \\[minibuffer-next-completion], \\[minibuffer-previous-completion], \
 \\[minibuffer-next-line-completion], \\[minibuffer-previous-line-completion] \
-to move point between completions.\n\n"))))))
-              (dolist (help helps)
-                (insert help)))
-          (insert (substitute-command-keys
-	           (if (display-mouse-p)
-	               "Click or type \\[minibuffer-choose-completion] on a completion to select it.\n"
-                     "Type \\[minibuffer-choose-completion] on a completion to select it.\n")))
-          (insert (substitute-command-keys
-		   "Type \\[minibuffer-next-completion] or \\[minibuffer-previous-completion] \
+to move point between completions.\n\n")
+                      (substitute-command-keys
+		       "Type \\[minibuffer-next-completion] or \\[minibuffer-previous-completion] \
 to move point between completions.\n\n")))))))
+          (dolist (help helps)
+            (insert help)))))))
 
 (add-hook 'completion-setup-hook #'completion-setup-function)
 
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index e5868351619..7a6480f0392 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -441,6 +441,17 @@ completion-flex-test-3
            15)))
 
 
+(defmacro with-minibuffer-setup (completing-read &rest body)
+  (declare (indent 1) (debug (collection body)))
+  `(catch 'result
+     (minibuffer-with-setup-hook
+         (lambda ()
+           (let ((redisplay-skip-initial-frame nil)
+                 (executing-kbd-macro nil)) ; Don't skip redisplay
+             (throw 'result (progn . ,body))))
+       (let ((executing-kbd-macro t)) ; Force the real minibuffer
+         ,completing-read))))
+
 (defmacro completing-read-with-minibuffer-setup (collection &rest body)
   (declare (indent 1) (debug (collection body)))
   `(catch 'result
@@ -577,6 +588,7 @@ completion-next-line-multline-test
 
 (ert-deftest completions-header-format-test ()
   (let ((completion-show-help nil)
+        (minibuffer-completion-auto-choose t)
         (completions-header-format nil))
     (completing-read-with-minibuffer-setup
         '("aa" "ab" "ac")
@@ -726,11 +738,50 @@ completion-cycle
       (should (equal (minibuffer-contents) "ccc")))))
 
 (ert-deftest minibuffer-next-completion ()
-  (let ((default-directory (ert-resource-directory)))
+  (let ((default-directory (ert-resource-directory))
+        (minibuffer-completion-auto-choose t))
     (completing-read-with-minibuffer-setup #'read-file-name-internal
       (insert "d/")
       (execute-kbd-macro (kbd "M-<down> M-<down> M-<down>"))
       (should (equal "data/minibuffer-test-cttq$$tion" (minibuffer-contents))))))
 
+(ert-deftest minibuffer-completion-RET-prefix ()
+  ;; REQUIRE-MATCH=nil
+  (with-minibuffer-setup
+      (completing-read ":" '("aaa" "bbb" "ccc") nil nil)
+    (execute-kbd-macro (kbd "M-<down> M-<down> C-u RET"))
+    (should (equal "bbb" (minibuffer-contents))))
+  ;; REQUIRE-MATCH=t
+  (with-minibuffer-setup
+   (completing-read ":" '("aaa" "bbb" "ccc") nil t)
+   (execute-kbd-macro (kbd "M-<down> M-<down> C-u RET"))
+   (should (equal "bbb" (minibuffer-contents)))))
+
+(defun test/completion-at-point ()
+  (list (point-min) (point) '("test:a" "test:b")))
+
+(ert-deftest completion-in-region-next-completion ()
+  (with-current-buffer (get-buffer-create "*test*")
+    ;; Put this buffer in the selected window so
+    ;; `minibuffer--completions-visible' works.
+    (pop-to-buffer (current-buffer))
+    (setq-local completion-at-point-functions (list #'test/completion-at-point))
+    (insert "test:")
+    (completion-help-at-point)
+    (should (minibuffer--completions-visible))
+    ;; C-u RET and RET have basically the same behavior for
+    ;; completion-in-region-mode, since they both dismiss *Completions*
+    ;; while leaving completion-in-region-mode still active.
+    (execute-kbd-macro (kbd "M-<down>"))
+    (should (equal (completion--selected-candidate) "test:a"))
+    (execute-kbd-macro (kbd "C-u RET"))
+    (should (equal (buffer-string) "test:a"))
+    (delete-char -1)
+    (completion-help-at-point)
+    (execute-kbd-macro (kbd "M-<down> M-<down>"))
+    (should (equal (completion--selected-candidate) "test:b"))
+    (execute-kbd-macro (kbd "RET"))
+    (should (equal (buffer-string) "test:b"))))
+
 (provide 'minibuffer-tests)
 ;;; minibuffer-tests.el ends here
-- 
2.43.7


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77253; Package emacs. (Wed, 27 Aug 2025 18:26:02 GMT) Full text and rfc822 format available.

Message #80 received at 77253 <at> debbugs.gnu.org (full text, mbox):

From: Juri Linkov <juri <at> linkov.net>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: sbaugh <at> catern.com, Eli Zaretskii <eliz <at> gnu.org>, 77253 <at> debbugs.gnu.org
Subject: Re: bug#77253: 30.1.50; Support RET choosing the selected
 completion without rebinding arrow keys, [PATCH] Make RET in minibuffer
 choose selected completion
Date: Wed, 27 Aug 2025 21:23:38 +0300
close 77253 31.0.50
thanks

> In fact, now that the RET binding is provided also for in-buffer
> completion, I think the RET binding provided by
> minibuffer-visible-completions can be dropped.  So I did that in the
> latest version of the patch.
>
> Also included some new tests.

Thanks, I tested everything and RET works consistently,
so now pushed and closed.




bug marked as fixed in version 31.0.50, send any further explanations to 77253 <at> debbugs.gnu.org and Spencer Baugh <sbaugh <at> janestreet.com> Request was from Juri Linkov <juri <at> linkov.net> to control <at> debbugs.gnu.org. (Wed, 27 Aug 2025 18:26:03 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Thu, 25 Sep 2025 11:24:25 GMT) Full text and rfc822 format available.

This bug report was last modified 42 days ago.

Previous Next


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