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
bug-gnu-emacs <at> gnu.org:bug#77253; Package emacs.
(Tue, 25 Mar 2025 15:12:02 GMT) Full text and rfc822 format available.Spencer Baugh <sbaugh <at> janestreet.com>: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.
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?
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.
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.
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.
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.
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.
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.
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.
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'.
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?
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?
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
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
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.
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.
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.
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
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.
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.
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
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.
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
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.
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
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.
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.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.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.