unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Navigating completions from minibuffer
@ 2023-11-07  3:57 T.V Raman
  2023-11-07  4:55 ` T.V Raman
  0 siblings, 1 reply; 62+ messages in thread
From: T.V Raman @ 2023-11-07  3:57 UTC (permalink / raw)
  To: emacs-devel

This change:
f0c0ff6bf23 * New option to use arrows in the minibuffer to select completions (bug#59486)
works really well but appears to  introduce a separate problem:

Assume you have a command  e.g. foo but also foo-bar and foo-bas.

Earlier you could type M-x foo and press enter to invoke foo.

Now, with the new option enabled, typing
M-x foo
appears to require that you first press TAB before pressing RET.

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Navigating completions from minibuffer
  2023-11-07  3:57 Navigating completions from minibuffer T.V Raman
@ 2023-11-07  4:55 ` T.V Raman
  2023-11-07  7:20   ` Juri Linkov
  0 siblings, 1 reply; 62+ messages in thread
From: T.V Raman @ 2023-11-07  4:55 UTC (permalink / raw)
  To: raman; +Cc: emacs-devel


Following up to myself:

The problem is that now RET calls minibuffer-choose-completion,
whereas exit-minibuffer is what you want if what you have typed is a
valid completion already; Perhaps we need
minibuffer-choose-completion-or-exit-minibuffer ...


T.V Raman writes:
 > This change:
 > f0c0ff6bf23 * New option to use arrows in the minibuffer to select completions (bug#59486)
 > works really well but appears to  introduce a separate problem:
 > 
 > Assume you have a command  e.g. foo but also foo-bar and foo-bas.
 > 
 > Earlier you could type M-x foo and press enter to invoke foo.
 > 
 > Now, with the new option enabled, typing
 > M-x foo
 > appears to require that you first press TAB before pressing RET.
 > 
 > -- 

-- 

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-07  4:55 ` T.V Raman
@ 2023-11-07  7:20   ` Juri Linkov
  2023-11-07 17:53     ` T.V Raman
  0 siblings, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-11-07  7:20 UTC (permalink / raw)
  To: T.V Raman; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 800 bytes --]

>> This change:
>> f0c0ff6bf23 * New option to use arrows in the minibuffer to select completions (bug#59486)
>> works really well but appears to  introduce a separate problem:
>>
>> Assume you have a command  e.g. foo but also foo-bar and foo-bas.
>>
>> Earlier you could type M-x foo and press enter to invoke foo.
>>
>> Now, with the new option enabled, typing
>> M-x foo
>> appears to require that you first press TAB before pressing RET.
>
> The problem is that now RET calls minibuffer-choose-completion,
> whereas exit-minibuffer is what you want if what you have typed is a
> valid completion already; Perhaps we need
> minibuffer-choose-completion-or-exit-minibuffer ...

Agreed.  When a completion candidate is not selected
let's use the contents of the minibuffer.
Please try this patch:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: minibuffer-choose-completion-or-exit.patch --]
[-- Type: text/x-diff, Size: 1223 bytes --]

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 4e8590989b3..0410e3a0b8d 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -3005,7 +3005,7 @@ 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)
+  "RET"     (minibuffer-visible-completions-bind #'minibuffer-choose-completion-or-exit)
   "C-g"     (minibuffer-visible-completions-bind #'minibuffer-hide-completions))
 
 \f
@@ -4693,6 +4693,12 @@ minibuffer-choose-completion
     (let ((completion-use-base-affixes t))
       (choose-completion nil no-exit no-quit))))
 
+(defun minibuffer-choose-completion-or-exit (&optional no-exit no-quit)
+  (interactive "P")
+  (condition-case nil
+      (minibuffer-choose-completion no-exit no-quit)
+    (error (exit-minibuffer))))
+
 (defun minibuffer-complete-history ()
   "Complete the minibuffer history as far as possible.
 Like `minibuffer-complete' but completes on the history items

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-07  7:20   ` Juri Linkov
@ 2023-11-07 17:53     ` T.V Raman
  2023-11-07 19:36       ` T.V Raman
  0 siblings, 1 reply; 62+ messages in thread
From: T.V Raman @ 2023-11-07 17:53 UTC (permalink / raw)
  To: juri; +Cc: raman, emacs-devel

am very confused.
Installed patch, recompiled, and installed -- restarted emacs
everything worked as expected.

But now my emacs cant find the --or-exit  command we just bound; where
is it defined?
-- 

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-07 17:53     ` T.V Raman
@ 2023-11-07 19:36       ` T.V Raman
  2023-11-08  7:39         ` Juri Linkov
  0 siblings, 1 reply; 62+ messages in thread
From: T.V Raman @ 2023-11-07 19:36 UTC (permalink / raw)
  To: juri; +Cc: emacs-devel

everything works, now that I actually applied the complete patch:-)

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-07 19:36       ` T.V Raman
@ 2023-11-08  7:39         ` Juri Linkov
  2023-11-08 16:21           ` T.V Raman
  2023-11-10 13:12           ` Spencer Baugh
  0 siblings, 2 replies; 62+ messages in thread
From: Juri Linkov @ 2023-11-08  7:39 UTC (permalink / raw)
  To: T.V Raman; +Cc: emacs-devel

> everything works, now that I actually applied the complete patch:-)

Thanks for confirming and for suggesting this change, now pushed.

Probably we have to make RET more smart, so that when more editing
was performed in the minibuffer after the completions were displayed,
then to use the minibuffer contents with exit-minibuffer,
not an obsolete completion candidate that remains selected.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-08  7:39         ` Juri Linkov
@ 2023-11-08 16:21           ` T.V Raman
  2023-11-08 17:18             ` T.V Raman
  2023-11-10 13:12           ` Spencer Baugh
  1 sibling, 1 reply; 62+ messages in thread
From: T.V Raman @ 2023-11-08 16:21 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

Juri Linkov <juri@linkov.net> writes:


Agreed. And somewhat related and something that has been causing me
trouble:

Q: Why is completion-at-point *soo much* slower than
hippie-expand?

I tried to understand why by looking at the code for completion-at-point
but failed miserably.

Hope you could look at this since you're working on completion related
bits.


Also, how and when completions are displayed can now be controlled by
multiple custom knobs, but it's hard to map the combinatorial explosion
of the available possibilities to different user experiences without
trying all possible settings; a higher level overview with a couple of
recipes that describe common combinations would help.


>> everything works, now that I actually applied the complete patch:-)
>
> Thanks for confirming and for suggesting this change, now pushed.
>
> Probably we have to make RET more smart, so that when more editing
> was performed in the minibuffer after the completions were displayed,
> then to use the minibuffer contents with exit-minibuffer,
> not an obsolete completion candidate that remains selected.
>

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-08 16:21           ` T.V Raman
@ 2023-11-08 17:18             ` T.V Raman
  2023-11-08 22:11               ` Slow completion-at-point was " T.V Raman
  0 siblings, 1 reply; 62+ messages in thread
From: T.V Raman @ 2023-11-08 17:18 UTC (permalink / raw)
  To: emacs-devel; +Cc: juri, emacs-devel

Adding emacs-devel after verifying slowness:

1. completion-at-point appears to have gotten very slow -- from memory
   in the last week (emacs built against Git @HEAD)
   The slowness is not present in a build from October 4.

   

T.V Raman writes:
 > Juri Linkov <juri@linkov.net> writes:
 > 
 > 
 > Agreed. And somewhat related and something that has been causing me
 > trouble:
 > 
 > Q: Why is completion-at-point *soo much* slower than
 > hippie-expand?
 > 
 > I tried to understand why by looking at the code for completion-at-point
 > but failed miserably.
 > 
 > Hope you could look at this since you're working on completion related
 > bits.
 > 
 > 
 > Also, how and when completions are displayed can now be controlled by
 > multiple custom knobs, but it's hard to map the combinatorial explosion
 > of the available possibilities to different user experiences without
 > trying all possible settings; a higher level overview with a couple of
 > recipes that describe common combinations would help.
 > 
 > 
 > >> everything works, now that I actually applied the complete patch:-)
 > >
 > > Thanks for confirming and for suggesting this change, now pushed.
 > >
 > > Probably we have to make RET more smart, so that when more editing
 > > was performed in the minibuffer after the completions were displayed,
 > > then to use the minibuffer contents with exit-minibuffer,
 > > not an obsolete completion candidate that remains selected.
 > >
 > 
 > -- 

-- 

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Slow completion-at-point was Re: Navigating completions from minibuffer
  2023-11-08 17:18             ` T.V Raman
@ 2023-11-08 22:11               ` T.V Raman
  2023-11-09  7:22                 ` Slow completion-at-point Juri Linkov
                                   ` (2 more replies)
  0 siblings, 3 replies; 62+ messages in thread
From: T.V Raman @ 2023-11-08 22:11 UTC (permalink / raw)
  To: emacs-devel; +Cc: emacs-devel, juri


Here is some timing information for this issue:



I added the following around advice fragment to completion-at-point debug:

(let ((start (current-time)))
     ad-do-it
     (message "<%.4f %d gcs %.4f>"
              (float-time (time-subtract (current-time) start))
              gcs-done gc-elapsed))

Then I went to a shell buffer, and from my home directory (it contains
a subdir text) typed

cd te <tab>

Messages buffer shows the following:

~/
Making completion list...
Sole completion
<2.0219 14 gcs 1.2927>
--Raman 
T.V Raman writes:
 > Adding emacs-devel after verifying slowness:
 > 
 > 1. completion-at-point appears to have gotten very slow -- from memory
 >    in the last week (emacs built against Git @HEAD)
 >    The slowness is not present in a build from October 4.
 > 
 >    
 > 
 > T.V Raman writes:
 >  > Juri Linkov <juri@linkov.net> writes:
 >  > 
 >  > 
 >  > Agreed. And somewhat related and something that has been causing me
 >  > trouble:
 >  > 
 >  > Q: Why is completion-at-point *soo much* slower than
 >  > hippie-expand?
 >  > 
 >  > I tried to understand why by looking at the code for completion-at-point
 >  > but failed miserably.
 >  > 
 >  > Hope you could look at this since you're working on completion related
 >  > bits.
 >  > 
 >  > 
 >  > Also, how and when completions are displayed can now be controlled by
 >  > multiple custom knobs, but it's hard to map the combinatorial explosion
 >  > of the available possibilities to different user experiences without
 >  > trying all possible settings; a higher level overview with a couple of
 >  > recipes that describe common combinations would help.
 >  > 
 >  > 
 >  > >> everything works, now that I actually applied the complete patch:-)
 >  > >
 >  > > Thanks for confirming and for suggesting this change, now pushed.
 >  > >
 >  > > Probably we have to make RET more smart, so that when more editing
 >  > > was performed in the minibuffer after the completions were displayed,
 >  > > then to use the minibuffer contents with exit-minibuffer,
 >  > > not an obsolete completion candidate that remains selected.
 >  > >
 >  > 
 >  > -- 
 > 
 > -- 
 > 
 > -- 

-- 

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point
  2023-11-08 22:11               ` Slow completion-at-point was " T.V Raman
@ 2023-11-09  7:22                 ` Juri Linkov
  2023-11-09 12:10                   ` Dmitry Gutov
  2023-11-09 15:39                   ` T.V Raman
  2023-11-09 12:20                 ` Slow completion-at-point was Re: Navigating completions from minibuffer Dmitry Gutov
  2023-11-09 17:46                 ` T.V Raman
  2 siblings, 2 replies; 62+ messages in thread
From: Juri Linkov @ 2023-11-09  7:22 UTC (permalink / raw)
  To: T.V Raman; +Cc: emacs-devel

> Here is some timing information for this issue:
>
> I added the following around advice fragment to completion-at-point debug:
>
> (let ((start (current-time)))
>      ad-do-it
>      (message "<%.4f %d gcs %.4f>"
>               (float-time (time-subtract (current-time) start))
>               gcs-done gc-elapsed))
>
> Then I went to a shell buffer, and from my home directory (it contains
> a subdir text) typed
>
> cd te <tab>
>
> Messages buffer shows the following:
>
> ~/
> Making completion list...
> Sole completion
> <2.0219 14 gcs 1.2927>

Please try to get benchmark numbers after customizing the recently added
'completion-lazy-hilit'.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point
  2023-11-09  7:22                 ` Slow completion-at-point Juri Linkov
@ 2023-11-09 12:10                   ` Dmitry Gutov
  2023-11-09 16:20                     ` Juri Linkov
  2023-11-11  2:48                     ` T.V Raman
  2023-11-09 15:39                   ` T.V Raman
  1 sibling, 2 replies; 62+ messages in thread
From: Dmitry Gutov @ 2023-11-09 12:10 UTC (permalink / raw)
  To: Juri Linkov, T.V Raman; +Cc: emacs-devel

On 09/11/2023 09:22, Juri Linkov wrote:
>> Here is some timing information for this issue:
>>
>> I added the following around advice fragment to completion-at-point debug:
>>
>> (let ((start (current-time)))
>>       ad-do-it
>>       (message "<%.4f %d gcs %.4f>"
>>                (float-time (time-subtract (current-time) start))
>>                gcs-done gc-elapsed))
>>
>> Then I went to a shell buffer, and from my home directory (it contains
>> a subdir text) typed
>>
>> cd te <tab>
>>
>> Messages buffer shows the following:
>>
>> ~/
>> Making completion list...
>> Sole completion
>> <2.0219 14 gcs 1.2927>
> Please try to get benchmark numbers after customizing the recently added
> 'completion-lazy-hilit'.

completion-lazy-hilit is not a user option. It's a defvar, intended for 
completion frontends to opt into deferred highlighting performed by 
completions styles.

IOW, whenever each completion UI is updated (that uses completion styles 
-- that is, calls completion-all-completions), all its users will see 
the benefits.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point was Re: Navigating completions from minibuffer
  2023-11-08 22:11               ` Slow completion-at-point was " T.V Raman
  2023-11-09  7:22                 ` Slow completion-at-point Juri Linkov
@ 2023-11-09 12:20                 ` Dmitry Gutov
  2023-11-09 15:41                   ` T.V Raman
  2023-11-09 17:46                 ` T.V Raman
  2 siblings, 1 reply; 62+ messages in thread
From: Dmitry Gutov @ 2023-11-09 12:20 UTC (permalink / raw)
  To: T.V Raman, emacs-devel; +Cc: juri

On 09/11/2023 00:11, T.V Raman wrote:
> Here is some timing information for this issue:
> 
> 
> 
> I added the following around advice fragment to completion-at-point debug:
> 
> (let ((start (current-time)))
>       ad-do-it
>       (message "<%.4f %d gcs %.4f>"
>                (float-time (time-subtract (current-time) start))
>                gcs-done gc-elapsed))
> 
> Then I went to a shell buffer, and from my home directory (it contains
> a subdir text) typed
> 
> cd te <tab>
> 
> Messages buffer shows the following:
> 
> ~/
> Making completion list...
> Sole completion
> <2.0219 14 gcs 1.2927>

Is completion-at-point slow for you in shell buffers in particular, or 
everywhere else too? E.g. completion in 'C-h f'.

There was a change last week (dfffb91a70532ac002), but it was supposed 
to make completion faster. And in your tests, it did (at least for 
icomplete, which knows how to take advantage of the optimization).



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point
  2023-11-09  7:22                 ` Slow completion-at-point Juri Linkov
  2023-11-09 12:10                   ` Dmitry Gutov
@ 2023-11-09 15:39                   ` T.V Raman
  1 sibling, 0 replies; 62+ messages in thread
From: T.V Raman @ 2023-11-09 15:39 UTC (permalink / raw)
  To: juri; +Cc: raman, emacs-devel

 So I played around with some of the completion related custom
 settings and at some point the problem disappeared. Will try what you
 suggest if it comes back.



Juri Linkov writes:
 > > Here is some timing information for this issue:
 > >
 > > I added the following around advice fragment to completion-at-point debug:
 > >
 > > (let ((start (current-time)))
 > >      ad-do-it
 > >      (message "<%.4f %d gcs %.4f>"
 > >               (float-time (time-subtract (current-time) start))
 > >               gcs-done gc-elapsed))
 > >
 > > Then I went to a shell buffer, and from my home directory (it contains
 > > a subdir text) typed
 > >
 > > cd te <tab>
 > >
 > > Messages buffer shows the following:
 > >
 > > ~/
 > > Making completion list...
 > > Sole completion
 > > <2.0219 14 gcs 1.2927>
 > 
 > Please try to get benchmark numbers after customizing the recently added
 > 'completion-lazy-hilit'.

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point was Re: Navigating completions from minibuffer
  2023-11-09 12:20                 ` Slow completion-at-point was Re: Navigating completions from minibuffer Dmitry Gutov
@ 2023-11-09 15:41                   ` T.V Raman
  0 siblings, 0 replies; 62+ messages in thread
From: T.V Raman @ 2023-11-09 15:41 UTC (permalink / raw)
  To: dmitry; +Cc: raman, emacs-devel, juri

when the problem was present, it was slow everywhere, though shell is
where I noticed it first. See other reply -- the problem disappeared
last night as I was twiddling various completion related custom knobs;
sadly I dont know when exactly it disappeared.


Dmitry Gutov writes:
 > On 09/11/2023 00:11, T.V Raman wrote:
 > > Here is some timing information for this issue:
 > > 
 > > 
 > > 
 > > I added the following around advice fragment to completion-at-point debug:
 > > 
 > > (let ((start (current-time)))
 > >       ad-do-it
 > >       (message "<%.4f %d gcs %.4f>"
 > >                (float-time (time-subtract (current-time) start))
 > >                gcs-done gc-elapsed))
 > > 
 > > Then I went to a shell buffer, and from my home directory (it contains
 > > a subdir text) typed
 > > 
 > > cd te <tab>
 > > 
 > > Messages buffer shows the following:
 > > 
 > > ~/
 > > Making completion list...
 > > Sole completion
 > > <2.0219 14 gcs 1.2927>
 > 
 > Is completion-at-point slow for you in shell buffers in particular, or 
 > everywhere else too? E.g. completion in 'C-h f'.
 > 
 > There was a change last week (dfffb91a70532ac002), but it was supposed 
 > to make completion faster. And in your tests, it did (at least for 
 > icomplete, which knows how to take advantage of the optimization).

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point
  2023-11-09 12:10                   ` Dmitry Gutov
@ 2023-11-09 16:20                     ` Juri Linkov
  2023-11-09 18:32                       ` João Távora
  2023-11-11  2:48                     ` T.V Raman
  1 sibling, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-11-09 16:20 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: emacs-devel

> IOW, whenever each completion UI is updated (that uses completion styles --
> that is, calls completion-all-completions), all its users will see the
> benefits.

BTW, after the recent change many tests are broken at the first part
of test/lisp/minibuffer-tests.el since there is no text property
'completion-score' anymore.  I noticed this when adding more tests
at the second part of the same file that is unrelated to this change.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Slow completion-at-point was Re: Navigating completions from minibuffer
  2023-11-08 22:11               ` Slow completion-at-point was " T.V Raman
  2023-11-09  7:22                 ` Slow completion-at-point Juri Linkov
  2023-11-09 12:20                 ` Slow completion-at-point was Re: Navigating completions from minibuffer Dmitry Gutov
@ 2023-11-09 17:46                 ` T.V Raman
  2 siblings, 0 replies; 62+ messages in thread
From: T.V Raman @ 2023-11-09 17:46 UTC (permalink / raw)
  To: emacs-devel; +Cc: emacs-devel, juri


Found the culprit:

If custom option
Hide Completion Auto Help: Choice: Value Menu Always visible
is set as above, it gets janky; if you go back to the default it
performs normally.

Haven't tested all other possibilities.

T.V Raman writes:
 > 
 > Here is some timing information for this issue:
 > 
 > 
 > 
 > I added the following around advice fragment to completion-at-point debug:
 > 
 > (let ((start (current-time)))
 >      ad-do-it
 >      (message "<%.4f %d gcs %.4f>"
 >               (float-time (time-subtract (current-time) start))
 >               gcs-done gc-elapsed))
 > 
 > Then I went to a shell buffer, and from my home directory (it contains
 > a subdir text) typed
 > 
 > cd te <tab>
 > 
 > Messages buffer shows the following:
 > 
 > ~/
 > Making completion list...
 > Sole completion
 > <2.0219 14 gcs 1.2927>
 > --Raman 
 > T.V Raman writes:
 >  > Adding emacs-devel after verifying slowness:
 >  > 
 >  > 1. completion-at-point appears to have gotten very slow -- from memory
 >  >    in the last week (emacs built against Git @HEAD)
 >  >    The slowness is not present in a build from October 4.
 >  > 
 >  >    
 >  > 
 >  > T.V Raman writes:
 >  >  > Juri Linkov <juri@linkov.net> writes:
 >  >  > 
 >  >  > 
 >  >  > Agreed. And somewhat related and something that has been causing me
 >  >  > trouble:
 >  >  > 
 >  >  > Q: Why is completion-at-point *soo much* slower than
 >  >  > hippie-expand?
 >  >  > 
 >  >  > I tried to understand why by looking at the code for completion-at-point
 >  >  > but failed miserably.
 >  >  > 
 >  >  > Hope you could look at this since you're working on completion related
 >  >  > bits.
 >  >  > 
 >  >  > 
 >  >  > Also, how and when completions are displayed can now be controlled by
 >  >  > multiple custom knobs, but it's hard to map the combinatorial explosion
 >  >  > of the available possibilities to different user experiences without
 >  >  > trying all possible settings; a higher level overview with a couple of
 >  >  > recipes that describe common combinations would help.
 >  >  > 
 >  >  > 
 >  >  > >> everything works, now that I actually applied the complete patch:-)
 >  >  > >
 >  >  > > Thanks for confirming and for suggesting this change, now pushed.
 >  >  > >
 >  >  > > Probably we have to make RET more smart, so that when more editing
 >  >  > > was performed in the minibuffer after the completions were displayed,
 >  >  > > then to use the minibuffer contents with exit-minibuffer,
 >  >  > > not an obsolete completion candidate that remains selected.
 >  >  > >
 >  >  > 
 >  >  > -- 
 >  > 
 >  > -- 
 >  > 
 >  > -- 
 > 
 > -- 
 > 
 > -- 

-- 

-- 

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point
  2023-11-09 16:20                     ` Juri Linkov
@ 2023-11-09 18:32                       ` João Távora
  0 siblings, 0 replies; 62+ messages in thread
From: João Távora @ 2023-11-09 18:32 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Dmitry Gutov, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 743 bytes --]

On Thu, Nov 9, 2023, 16:22 Juri Linkov <juri@linkov.net> wrote:

> > IOW, whenever each completion UI is updated (that uses completion styles
> --
> > that is, calls completion-all-completions), all its users will see the
> > benefits.
>
> BTW, after the recent change many tests are broken at the first part
> of test/lisp/minibuffer-tests.el since there is no text property
> 'completion-score' anymore.  I noticed this when adding more tests
> at the second part of the same file that is unrelated to this change.


Thanks for noticing and sorry for the breakage. I think the tests need to
be updated to reflect what exactly the public expectations are regarding
these properties. I'll look into this ASAP.

João

>
>

[-- Attachment #2: Type: text/html, Size: 1285 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-08  7:39         ` Juri Linkov
  2023-11-08 16:21           ` T.V Raman
@ 2023-11-10 13:12           ` Spencer Baugh
  2023-11-11 18:58             ` Juri Linkov
  1 sibling, 1 reply; 62+ messages in thread
From: Spencer Baugh @ 2023-11-10 13:12 UTC (permalink / raw)
  To: emacs-devel

Juri Linkov <juri@linkov.net> writes:
>> everything works, now that I actually applied the complete patch:-)
>
> Thanks for confirming and for suggesting this change, now pushed.
>
> Probably we have to make RET more smart, so that when more editing
> was performed in the minibuffer after the completions were displayed,
> then to use the minibuffer contents with exit-minibuffer,
> not an obsolete completion candidate that remains selected.

Interesting solution!  So if the last relevant command was changing the
selected candidate, then RET submits the candidate; if the last relevant
command was editing the minibuffer, then RET submits the minibuffer
text.

What about the case where I type some text, switch between some
completion candidates in *Completions*, then decide I don't want any of
them and hit RET to submit the minibuffer text?  That's something that
works today.  Can we support that somehow?

I wrote a series of experimental changes where RET picks the selected
completion candidate, after discussing that sort of behavior in the
completions-auto-update thread, and used them for a while.  I ended up
concluding that it couldn't be done without running into bugs/loss of
funtionality like icomplete and ido have, and that therefore a separate
M-RET was the best way.  But what you propose here would solve some of
the issues, and maybe all of them.

BTW, I think the best approach I came up with in those experiments was
for TAB to insert the selected completion candidate.  Then TAB RET
effectively chooses the selected candidate.  I found that quite elegant
and powerful, but in the end it also was limiting in some cases.  But
maybe in combination with your idea of only inserting the selected
completion candidate if the minibuffer hasn't changed since selecting
it, it could work.




^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point
  2023-11-09 12:10                   ` Dmitry Gutov
  2023-11-09 16:20                     ` Juri Linkov
@ 2023-11-11  2:48                     ` T.V Raman
  2023-11-11 10:36                       ` Dmitry Gutov
  1 sibling, 1 reply; 62+ messages in thread
From: T.V Raman @ 2023-11-11  2:48 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Juri Linkov, emacs-devel

Dmitry Gutov <dmitry@gutov.dev> writes:


Not sure if you saw my message where I tracked down the culprit:
The slowness in completion-at-point is triggered if
Completion Auto Help: Choice: Value Menu Always visible.

is set as above, it gets janky; if you go back to the default it
performs normally.

> On 09/11/2023 09:22, Juri Linkov wrote:
>>> Here is some timing information for this issue:
>>>
>>> I added the following around advice fragment to completion-at-point debug:
>>>
>>> (let ((start (current-time)))
>>>       ad-do-it
>>>       (message "<%.4f %d gcs %.4f>"
>>>                (float-time (time-subtract (current-time) start))
>>>                gcs-done gc-elapsed))
>>>
>>> Then I went to a shell buffer, and from my home directory (it contains
>>> a subdir text) typed
>>>
>>> cd te <tab>
>>>
>>> Messages buffer shows the following:
>>>
>>> ~/
>>> Making completion list...
>>> Sole completion
>>> <2.0219 14 gcs 1.2927>
>> Please try to get benchmark numbers after customizing the recently added
>> 'completion-lazy-hilit'.
>
> completion-lazy-hilit is not a user option. It's a defvar, intended
> for completion frontends to opt into deferred highlighting performed
> by completions styles.
>
> IOW, whenever each completion UI is updated (that uses completion
> styles -- that is, calls completion-all-completions), all its users
> will see the benefits.
>

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point
  2023-11-11  2:48                     ` T.V Raman
@ 2023-11-11 10:36                       ` Dmitry Gutov
  2023-11-11 16:40                         ` T.V Raman
  0 siblings, 1 reply; 62+ messages in thread
From: Dmitry Gutov @ 2023-11-11 10:36 UTC (permalink / raw)
  To: T.V Raman; +Cc: Juri Linkov, emacs-devel

On 11/11/2023 04:48, T.V Raman wrote:
> Dmitry Gutov<dmitry@gutov.dev>  writes:
> 
> 
> Not sure if you saw my message where I tracked down the culprit:
> The slowness in completion-at-point is triggered if
> Completion Auto Help: Choice: Value Menu Always visible.
> 
> is set as above, it gets janky; if you go back to the default it
> performs normally.

This is not a new option: it's from 2008. It is somewhat natural for 
things to get slower if Emacs has to do more work - i.e. the completions 
buffer remains visible.

Did the effect of this option get worse over the last week, or did you 
just try setting it to 'always' very recently?

In any case, if you have a good repro for the problem, you can file a 
bug report now.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point
  2023-11-11 10:36                       ` Dmitry Gutov
@ 2023-11-11 16:40                         ` T.V Raman
  2023-11-11 19:00                           ` Juri Linkov
  0 siblings, 1 reply; 62+ messages in thread
From: T.V Raman @ 2023-11-11 16:40 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Juri Linkov, emacs-devel

Dmitry Gutov <dmitry@gutov.dev> writes:

I've always had it set to always, and the slowness only emerged this
week -- ie when I sent the message.

> On 11/11/2023 04:48, T.V Raman wrote:
>> Dmitry Gutov<dmitry@gutov.dev>  writes:
>> Not sure if you saw my message where I tracked down the culprit:
>> The slowness in completion-at-point is triggered if
>> Completion Auto Help: Choice: Value Menu Always visible.
>> is set as above, it gets janky; if you go back to the default it
>> performs normally.
>
> This is not a new option: it's from 2008. It is somewhat natural for
> things to get slower if Emacs has to do more work - i.e. the
> completions buffer remains visible.
>
> Did the effect of this option get worse over the last week, or did you
> just try setting it to 'always' very recently?
>
> In any case, if you have a good repro for the problem, you can file a
> bug report now.
>

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-10 13:12           ` Spencer Baugh
@ 2023-11-11 18:58             ` Juri Linkov
  2023-11-14  7:36               ` Juri Linkov
  0 siblings, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-11-11 18:58 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: emacs-devel

>> Probably we have to make RET more smart, so that when more editing
>> was performed in the minibuffer after the completions were displayed,
>> then to use the minibuffer contents with exit-minibuffer,
>> not an obsolete completion candidate that remains selected.
>
> Interesting solution!  So if the last relevant command was changing the
> selected candidate, then RET submits the candidate; if the last relevant
> command was editing the minibuffer, then RET submits the minibuffer
> text.
>
> What about the case where I type some text, switch between some
> completion candidates in *Completions*, then decide I don't want any of
> them and hit RET to submit the minibuffer text?  That's something that
> works today.  Can we support that somehow?

Currently the suggested way to avoid selecting a highlighted candidate
is to close the completions window with C-g, i.e. it adheres
to the principle “what you see is what you get” - when you see
a highlighted candidate then you will get it, otherwise you will get
the minibuffer contents.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point
  2023-11-11 16:40                         ` T.V Raman
@ 2023-11-11 19:00                           ` Juri Linkov
  2023-11-11 19:43                             ` T.V Raman
  0 siblings, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-11-11 19:00 UTC (permalink / raw)
  To: T.V Raman; +Cc: Dmitry Gutov, emacs-devel

> I've always had it set to always, and the slowness only emerged this
> week -- ie when I sent the message.

I guess the slowness might be caused by one of these two commit:
either the commit f0c0ff6bf23 or the commit dfffb91a705.
Could you please try to check out whether the state before these commits
caused the same slowness?



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point
  2023-11-11 19:00                           ` Juri Linkov
@ 2023-11-11 19:43                             ` T.V Raman
  2023-11-11 21:50                               ` Dmitry Gutov
  0 siblings, 1 reply; 62+ messages in thread
From: T.V Raman @ 2023-11-11 19:43 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Dmitry Gutov, emacs-devel

could you give me the exact SHA checksum to checkout?
-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Slow completion-at-point
  2023-11-11 19:43                             ` T.V Raman
@ 2023-11-11 21:50                               ` Dmitry Gutov
  0 siblings, 0 replies; 62+ messages in thread
From: Dmitry Gutov @ 2023-11-11 21:50 UTC (permalink / raw)
  To: T.V Raman, Juri Linkov; +Cc: emacs-devel

On 11/11/2023 21:43, T.V Raman wrote:
> could you give me the exact SHA checksum to checkout?

These shorter hashes are fine to use with 'git checkout'. But you might 
need to 'git fetch' first.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-11 18:58             ` Juri Linkov
@ 2023-11-14  7:36               ` Juri Linkov
  2023-11-15 21:40                 ` Spencer Baugh
  2023-11-15 22:03                 ` Spencer Baugh
  0 siblings, 2 replies; 62+ messages in thread
From: Juri Linkov @ 2023-11-14  7:36 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: emacs-devel

>>> Probably we have to make RET more smart, so that when more editing
>>> was performed in the minibuffer after the completions were displayed,
>>> then to use the minibuffer contents with exit-minibuffer,
>>> not an obsolete completion candidate that remains selected.
>>
>> Interesting solution!  So if the last relevant command was changing the
>> selected candidate, then RET submits the candidate; if the last relevant
>> command was editing the minibuffer, then RET submits the minibuffer
>> text.
>>
>> What about the case where I type some text, switch between some
>> completion candidates in *Completions*, then decide I don't want any of
>> them and hit RET to submit the minibuffer text?  That's something that
>> works today.  Can we support that somehow?
>
> Currently the suggested way to avoid selecting a highlighted candidate
> is to close the completions window with C-g, i.e. it adheres
> to the principle “what you see is what you get” - when you see
> a highlighted candidate then you will get it, otherwise you will get
> the minibuffer contents.

So there are at least 2 variants what to do when completing-read is used
as selection rather than completion:

1. On editing the minibuffer close the completions window as expired.

Shouldn't 'completion-auto-help' support this case?
Should it have a new value 'close'?
Or need to create a new option 'completion-auto-close'?

2. AFAIR, 'completion-auto-update' already closes the completions window
if none of completion candidates matches the contents of the minibuffer?

So editing the minibuffer never causes a situation where a highlighted
candidate doesn't match the minibuffer contents?

And typing some characters to narrow down the completions
always keeps the highlighted candidate selected?

Then there is no problem.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-14  7:36               ` Juri Linkov
@ 2023-11-15 21:40                 ` Spencer Baugh
  2023-11-16 17:15                   ` T.V Raman
  2023-11-15 22:03                 ` Spencer Baugh
  1 sibling, 1 reply; 62+ messages in thread
From: Spencer Baugh @ 2023-11-15 21:40 UTC (permalink / raw)
  To: emacs-devel

Juri Linkov <juri@linkov.net> writes:
>>>> Probably we have to make RET more smart, so that when more editing
>>>> was performed in the minibuffer after the completions were displayed,
>>>> then to use the minibuffer contents with exit-minibuffer,
>>>> not an obsolete completion candidate that remains selected.
>>>
>>> Interesting solution!  So if the last relevant command was changing the
>>> selected candidate, then RET submits the candidate; if the last relevant
>>> command was editing the minibuffer, then RET submits the minibuffer
>>> text.
>>>
>>> What about the case where I type some text, switch between some
>>> completion candidates in *Completions*, then decide I don't want any of
>>> them and hit RET to submit the minibuffer text?  That's something that
>>> works today.  Can we support that somehow?
>>
>> Currently the suggested way to avoid selecting a highlighted candidate
>> is to close the completions window with C-g, i.e. it adheres
>> to the principle “what you see is what you get” - when you see
>> a highlighted candidate then you will get it, otherwise you will get
>> the minibuffer contents.
>
> So there are at least 2 variants what to do when completing-read is used
> as selection rather than completion:
>
> 1. On editing the minibuffer close the completions window as expired.
>
> Shouldn't 'completion-auto-help' support this case?
> Should it have a new value 'close'?
> Or need to create a new option 'completion-auto-close'?

I think a new option would be better, the different options for
completion-auto-help all seem plausible to combine with that behavior.

It's a bit tricky since completion-auto-update=t effectively implies
completion-auto-close=t.

Oh, actually, perhaps completion-auto-close should be merged with
completion-auto-update.  Then completion-auto-update has three values:

- nil (today's behavior)
- close (close the completions window on editing the minibufer)
- t (auto-update the completions window on editing the minibuffer)

After all, both non-nil values would use basically the same
implementation.

> 2. AFAIR, 'completion-auto-update' already closes the completions window
> if none of completion candidates matches the contents of the minibuffer?
>
> So editing the minibuffer never causes a situation where a highlighted
> candidate doesn't match the minibuffer contents?
>
> And typing some characters to narrow down the completions
> always keeps the highlighted candidate selected?
>
> Then there is no problem.

Yes, that's correct.

Very interesting analysis!  This makes sense.




^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-14  7:36               ` Juri Linkov
  2023-11-15 21:40                 ` Spencer Baugh
@ 2023-11-15 22:03                 ` Spencer Baugh
  2023-11-16  7:16                   ` Juri Linkov
  1 sibling, 1 reply; 62+ messages in thread
From: Spencer Baugh @ 2023-11-15 22:03 UTC (permalink / raw)
  To: emacs-devel

Juri Linkov <juri@linkov.net> writes:
>>>> Probably we have to make RET more smart, so that when more editing
>>>> was performed in the minibuffer after the completions were displayed,
>>>> then to use the minibuffer contents with exit-minibuffer,
>>>> not an obsolete completion candidate that remains selected.
>>>
>>> Interesting solution!  So if the last relevant command was changing the
>>> selected candidate, then RET submits the candidate; if the last relevant
>>> command was editing the minibuffer, then RET submits the minibuffer
>>> text.
>>>
>>> What about the case where I type some text, switch between some
>>> completion candidates in *Completions*, then decide I don't want any of
>>> them and hit RET to submit the minibuffer text?  That's something that
>>> works today.  Can we support that somehow?
>>
>> Currently the suggested way to avoid selecting a highlighted candidate
>> is to close the completions window with C-g, i.e. it adheres
>> to the principle “what you see is what you get” - when you see
>> a highlighted candidate then you will get it, otherwise you will get
>> the minibuffer contents.
>
> So there are at least 2 variants what to do when completing-read is used
> as selection rather than completion:
>
> 1. On editing the minibuffer close the completions window as expired.

This would make it difficult to narrow the completions by typing in some
text from them, though.  I think I relatively often:

1. TAB
2. Look at *Completions*
3. Type in some text from one of them

Step 3 would harder if *Completions* disappeared on the first character
I typed.

Perhaps instead typing a character could deselect the currently selected
completion, rather than hide *Completions*?  But it seems nice to
maintain the selected completion as you type, as a visual guide, and
also my other patch maintains the selected completion between each TAB,
which is nice.

Maybe... we could somehow de-activate the selected completion, visually
de-emphasizing it in some way, but still showing its position in some
less-significant way?  An underline, perhaps?  And subsequent operations
which change the selected completion would reactivate it, making it the
selected completion again.  That might be a bit tricky to represent
visually in an intuitive way, but it might give us everything we want.

Maybe we could represent that visually by moving the selected completion
indicator (which in emacs -q is a green highlight) to *the minibuffer*
when the "selected" completion is not actually active.  Then the user
would quite quickly get the idea: RET submits whatever is highlighted in
green.




^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-15 22:03                 ` Spencer Baugh
@ 2023-11-16  7:16                   ` Juri Linkov
  2023-11-16 14:41                     ` Spencer Baugh
  0 siblings, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-11-16  7:16 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: emacs-devel

>> 1. On editing the minibuffer close the completions window as expired.
>
> This would make it difficult to narrow the completions by typing in some
> text from them, though.  I think I relatively often:
>
> 1. TAB
> 2. Look at *Completions*
> 3. Type in some text from one of them
>
> Step 3 would harder if *Completions* disappeared on the first character
> I typed.
>
> Perhaps instead typing a character could deselect the currently selected
> completion, rather than hide *Completions*?  But it seems nice to
> maintain the selected completion as you type, as a visual guide, and
> also my other patch maintains the selected completion between each TAB,
> which is nice.

In case of completion-auto-update=t the selected completion should be
maintained as you type indeed.  But when completion-auto-update=nil
instead of forcing the completions window to be closed it looks better
just to deselect the current completion.

> Maybe... we could somehow de-activate the selected completion, visually
> de-emphasizing it in some way, but still showing its position in some
> less-significant way?  An underline, perhaps?  And subsequent operations
> which change the selected completion would reactivate it, making it the
> selected completion again.  That might be a bit tricky to represent
> visually in an intuitive way, but it might give us everything we want.
>
> Maybe we could represent that visually by moving the selected completion
> indicator (which in emacs -q is a green highlight) to *the minibuffer*
> when the "selected" completion is not actually active.  Then the user
> would quite quickly get the idea: RET submits whatever is highlighted in
> green.

Usually the active editing area is not highlighted in any way.
So better would be to use highlighting only in the completions window.

For completions-highlight-face=t it's clear that deselection should
remove this face.  But what to do for completions-highlight-face=nil
is not clear.  Maybe just to move point to area with no candidates?



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-16  7:16                   ` Juri Linkov
@ 2023-11-16 14:41                     ` Spencer Baugh
  2023-11-16 17:28                       ` Juri Linkov
  0 siblings, 1 reply; 62+ messages in thread
From: Spencer Baugh @ 2023-11-16 14:41 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

Juri Linkov <juri@linkov.net> writes:
>>> 1. On editing the minibuffer close the completions window as expired.
>>
>> This would make it difficult to narrow the completions by typing in some
>> text from them, though.  I think I relatively often:
>>
>> 1. TAB
>> 2. Look at *Completions*
>> 3. Type in some text from one of them
>>
>> Step 3 would harder if *Completions* disappeared on the first character
>> I typed.
>>
>> Perhaps instead typing a character could deselect the currently selected
>> completion, rather than hide *Completions*?  But it seems nice to
>> maintain the selected completion as you type, as a visual guide, and
>> also my other patch maintains the selected completion between each TAB,
>> which is nice.
>
> In case of completion-auto-update=t the selected completion should be
> maintained as you type indeed.  But when completion-auto-update=nil
> instead of forcing the completions window to be closed it looks better
> just to deselect the current completion.

Yes, agreed on that point.  When completion-auto-update=nil, It is
better to deselect the current completion than close the completions
window.

>> Maybe... we could somehow de-activate the selected completion, visually
>> de-emphasizing it in some way, but still showing its position in some
>> less-significant way?  An underline, perhaps?  And subsequent operations
>> which change the selected completion would reactivate it, making it the
>> selected completion again.  That might be a bit tricky to represent
>> visually in an intuitive way, but it might give us everything we want.
>>
>> Maybe we could represent that visually by moving the selected completion
>> indicator (which in emacs -q is a green highlight) to *the minibuffer*
>> when the "selected" completion is not actually active.  Then the user
>> would quite quickly get the idea: RET submits whatever is highlighted in
>> green.
>
> Usually the active editing area is not highlighted in any way.
> So better would be to use highlighting only in the completions window.

Yes, but I wonder if we could have some simple indicator in the
minibuffer which isn't too visually noisy.  And which is only activated
if the user has previously selected a candidate in *Completions* and
then deselected it by typing.  Maybe highlighting the minibuffer prompt
instead of the text?  Well, not really necessary, just a thought.

> For completions-highlight-face=t it's clear that deselection should
> remove this face.  But what to do for completions-highlight-face=nil
> is not clear.  Maybe just to move point to area with no candidates?

I had been assuming "move point to area with no candidates" was how we
would implement deselection in any case.  Since "point is on a
candidate" is the definition of selection, as it stands.

Maybe we can deselect by moving point to just before (or after) the
selected candidate?  Move point to the whitespace in-between candidates.
Then no candidate is selected, and completions-highlight-face won't
highlight any candidate, but there's still a bit of visual indicator
(window-point) which shows what candidate was previously selected, and
if the user does want to re-select the candidate, the user can just hit
<down> (or <up>) to select the candidate again.

And completion-auto-update could maintain this state, too, just like it
maintains the selected candidate: if point is right before (but not on)
a candidate, it should stay right before (but not on) that candidate as
the user types and *Completions* updates.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-15 21:40                 ` Spencer Baugh
@ 2023-11-16 17:15                   ` T.V Raman
  0 siblings, 0 replies; 62+ messages in thread
From: T.V Raman @ 2023-11-16 17:15 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: emacs-devel

Spencer Baugh <sbaugh@janestreet.com> writes:

This is a good idea. I still believe we have too many completion knobs,
but I dont know how else to simplify things other than one step at a
time and trying  it out incrementally. But we  should do this with the
final goal of recuding the current combinatorial exposion of choices
which makes things both hard to test and to explain.

> Juri Linkov <juri@linkov.net> writes:
>>>>> Probably we have to make RET more smart, so that when more editing
>>>>> was performed in the minibuffer after the completions were displayed,
>>>>> then to use the minibuffer contents with exit-minibuffer,
>>>>> not an obsolete completion candidate that remains selected.
>>>>
>>>> Interesting solution!  So if the last relevant command was changing the
>>>> selected candidate, then RET submits the candidate; if the last relevant
>>>> command was editing the minibuffer, then RET submits the minibuffer
>>>> text.
>>>>
>>>> What about the case where I type some text, switch between some
>>>> completion candidates in *Completions*, then decide I don't want any of
>>>> them and hit RET to submit the minibuffer text?  That's something that
>>>> works today.  Can we support that somehow?
>>>
>>> Currently the suggested way to avoid selecting a highlighted candidate
>>> is to close the completions window with C-g, i.e. it adheres
>>> to the principle “what you see is what you get” - when you see
>>> a highlighted candidate then you will get it, otherwise you will get
>>> the minibuffer contents.
>>
>> So there are at least 2 variants what to do when completing-read is used
>> as selection rather than completion:
>>
>> 1. On editing the minibuffer close the completions window as expired.
>>
>> Shouldn't 'completion-auto-help' support this case?
>> Should it have a new value 'close'?
>> Or need to create a new option 'completion-auto-close'?
>
> I think a new option would be better, the different options for
> completion-auto-help all seem plausible to combine with that behavior.
>
> It's a bit tricky since completion-auto-update=t effectively implies
> completion-auto-close=t.
>
> Oh, actually, perhaps completion-auto-close should be merged with
> completion-auto-update.  Then completion-auto-update has three values:
>
> - nil (today's behavior)
> - close (close the completions window on editing the minibufer)
> - t (auto-update the completions window on editing the minibuffer)
>
> After all, both non-nil values would use basically the same
> implementation.
>
>> 2. AFAIR, 'completion-auto-update' already closes the completions window
>> if none of completion candidates matches the contents of the minibuffer?
>>
>> So editing the minibuffer never causes a situation where a highlighted
>> candidate doesn't match the minibuffer contents?
>>
>> And typing some characters to narrow down the completions
>> always keeps the highlighted candidate selected?
>>
>> Then there is no problem.
>
> Yes, that's correct.
>
> Very interesting analysis!  This makes sense.
>
>

-- 



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-16 14:41                     ` Spencer Baugh
@ 2023-11-16 17:28                       ` Juri Linkov
  2023-11-16 18:25                         ` Spencer Baugh
  0 siblings, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-11-16 17:28 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: emacs-devel

> Maybe we can deselect by moving point to just before (or after) the
> selected candidate?  Move point to the whitespace in-between candidates.
> Then no candidate is selected, and completions-highlight-face won't
> highlight any candidate, but there's still a bit of visual indicator
> (window-point) which shows what candidate was previously selected, and
> if the user does want to re-select the candidate, the user can just hit
> <down> (or <up>) to select the candidate again.

In fact, the whitespace in-between candidates is the only place where
point could be moved to deselect the candidate.  Because there is no space
at the end of the completions buffer, and even at the beginning when
both completion-show-help and completions-header-format are nil.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-16 17:28                       ` Juri Linkov
@ 2023-11-16 18:25                         ` Spencer Baugh
  2023-11-17  7:09                           ` Juri Linkov
  0 siblings, 1 reply; 62+ messages in thread
From: Spencer Baugh @ 2023-11-16 18:25 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

Juri Linkov <juri@linkov.net> writes:
>> Maybe we can deselect by moving point to just before (or after) the
>> selected candidate?  Move point to the whitespace in-between candidates.
>> Then no candidate is selected, and completions-highlight-face won't
>> highlight any candidate, but there's still a bit of visual indicator
>> (window-point) which shows what candidate was previously selected, and
>> if the user does want to re-select the candidate, the user can just hit
>> <down> (or <up>) to select the candidate again.
>
> In fact, the whitespace in-between candidates is the only place where
> point could be moved to deselect the candidate.  Because there is no space
> at the end of the completions buffer, and even at the beginning when
> both completion-show-help and completions-header-format are nil.

Oh, great!  So then let's just do that.

Possibly we should ensure there is one character worth of whitespace at
the end of the completions buffer, so we can consistently just move
point to right after the selected candidate to deselect it.


Also... doesn't this mean that with

(setq completion-show-help nil
      completions-header-format nil)

*Completions* will start out with the point on the first completion
candidate?  So M-RET will select it, and with
minibuffer-visible-completions=t, even RET will select it?

Maybe point should uniformly start at the end of *Completions* instead
of at the start?  In the one character worth of whitespace we might add?



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-16 18:25                         ` Spencer Baugh
@ 2023-11-17  7:09                           ` Juri Linkov
  2023-11-17 17:22                             ` Spencer Baugh
  0 siblings, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-11-17  7:09 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: emacs-devel

> Also... doesn't this mean that with
>
> (setq completion-show-help nil
>       completions-header-format nil)
>
> *Completions* will start out with the point on the first completion
> candidate?  So M-RET will select it, and with
> minibuffer-visible-completions=t, even RET will select it?
>
> Maybe point should uniformly start at the end of *Completions* instead
> of at the start?  In the one character worth of whitespace we might add?

Starting at the end of *Completions* would work only when
completion-auto-wrap is t.  Another variant is to add a narrow
character at the beginning of *Completions* like used for
an empty rectangular region in rectangle-mark-mode.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-17  7:09                           ` Juri Linkov
@ 2023-11-17 17:22                             ` Spencer Baugh
  2023-11-18 20:58                               ` sbaugh
  0 siblings, 1 reply; 62+ messages in thread
From: Spencer Baugh @ 2023-11-17 17:22 UTC (permalink / raw)
  To: emacs-devel

Juri Linkov <juri@linkov.net> writes:
>> Also... doesn't this mean that with
>>
>> (setq completion-show-help nil
>>       completions-header-format nil)
>>
>> *Completions* will start out with the point on the first completion
>> candidate?  So M-RET will select it, and with
>> minibuffer-visible-completions=t, even RET will select it?
>>
>> Maybe point should uniformly start at the end of *Completions* instead
>> of at the start?  In the one character worth of whitespace we might add?
>
> Starting at the end of *Completions* would work only when
> completion-auto-wrap is t.  Another variant is to add a narrow
> character at the beginning of *Completions* like used for
> an empty rectangular region in rectangle-mark-mode.

Yes, that sounds good.  And then we could uniformly move point before
the candidate when deselecting it, which IMO would be a little visually
nicer.




^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-17 17:22                             ` Spencer Baugh
@ 2023-11-18 20:58                               ` sbaugh
  2023-11-19  7:08                                 ` Juri Linkov
  0 siblings, 1 reply; 62+ messages in thread
From: sbaugh @ 2023-11-18 20:58 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1336 bytes --]

Spencer Baugh <sbaugh@janestreet.com> writes:

> Juri Linkov <juri@linkov.net> writes:
>>> Also... doesn't this mean that with
>>>
>>> (setq completion-show-help nil
>>>       completions-header-format nil)
>>>
>>> *Completions* will start out with the point on the first completion
>>> candidate?  So M-RET will select it, and with
>>> minibuffer-visible-completions=t, even RET will select it?
>>>
>>> Maybe point should uniformly start at the end of *Completions* instead
>>> of at the start?  In the one character worth of whitespace we might add?
>>
>> Starting at the end of *Completions* would work only when
>> completion-auto-wrap is t.  Another variant is to add a narrow
>> character at the beginning of *Completions* like used for
>> an empty rectangular region in rectangle-mark-mode.
>
> Yes, that sounds good.  And then we could uniformly move point before
> the candidate when deselecting it, which IMO would be a little visually
> nicer.

OK, how about this?  It's an adapted version of my
completions-auto-update patch, which provides (for now) only the feature
of deselecting the completion when point moves or the minibuffer
changes.  The infrastructure for doing this turns out to be basically
identical, which is interesting.

It sets completions-auto-update to 'deselect by default, which I think
is reasonable?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Deselect-the-selected-completion-candidate-when-typi.patch --]
[-- Type: text/x-patch, Size: 5933 bytes --]

From beb15769fdacc388a059e6bc79e924bc219bcb98 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh@catern.com>
Date: Sat, 18 Nov 2023 20:55:18 +0000
Subject: [PATCH] Deselect the selected completion candidate when typing

minibuffer-visible-completions makes RET submit the selected
completion candidate, if any, ignoring the contents of the minibuffer.
But a user might select a completion candidate and then want to type
something else in the minibuffer and submit what they typed.

Now typing will automatically deselect the selected completion
candidate.

* lisp/minibuffer.el (completion--insert): Add a space before each
candidate.
(completions-auto-update, completions--deselect)
(completions--update-if-displayed, completions--after-change)
(minibuffer--old-point, completions--post-command): Add.
(minibuffer-completion-help): Add completions--after-change and
completions--post-command as hooks.
(minibuffer-next-completion): Bind completions-auto-update to nil to
avoid immediately deselecting the completion.
---
 lisp/minibuffer.el | 72 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 62 insertions(+), 10 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index e0017d88780..026613c9eb2 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2196,15 +2196,18 @@ completion--insert
              (equal (or (car-safe str) str) selected))
     (setq completion--selected-posn (point)))
   (if (not (consp str))
-      (add-text-properties
-       (point)
-       (progn
-         (insert
-          (if group-fun
-              (funcall group-fun str 'transform)
-            str))
-         (point))
-       `(mouse-face highlight cursor-face ,completions-highlight-face completion--string ,str))
+      (progn
+        ;; We move point to this character to deselect the completion candidate.
+        (insert " ")
+        (add-text-properties
+         (point)
+         (progn
+           (insert
+            (if group-fun
+                (funcall group-fun str 'transform)
+              str))
+           (point))
+         `(mouse-face highlight cursor-face ,completions-highlight-face completion--string ,str)))
     ;; If `str' is a list that has 2 elements,
     ;; then the second element is a suffix annotation.
     ;; If `str' has 3 elements, then the second element
@@ -2391,6 +2394,49 @@ completions--fit-window-to-buffer
         (resize-temp-buffer-window win))
     (fit-window-to-buffer win completions-max-height)))
 
+(defcustom completions-auto-update 'deselect
+  "If non-nil, change the *Completions* buffer as you type.
+
+If `deselect', if a completion candidate in *Completions* is
+selected (point is on it), it will be deselected (point will be
+moved just before it) when the minibuffer point or contents
+change.
+
+This only affects the *Completions* buffer if it is already
+displayed."
+  :type '(choice (const :tag "*Completions* doesn't change as you type" nil)
+                 (const :tag "Typing deselects any completion candidate in *Completions*" deselect))
+  :version "30.1")
+
+(defun completions--deselect ()
+  "If in a completion candidate, move just before the start of it."
+  (when (get-text-property (point) 'mouse-face)
+    (when (and (not (bobp)) (get-text-property (1- (point)) 'mouse-face))
+      (goto-char (previous-single-property-change (point) 'mouse-face)))
+    (unless (bobp)
+      (backward-char 1))))
+
+(defun completions--update-if-displayed ()
+  "Update a displayed *Completions* buffer based on `completions-auto-update'"
+  (when completions-auto-update
+    (when-let (window (get-buffer-window "*Completions*" 0))
+      (with-selected-window window
+        (when (eq completions-auto-update 'deselect)
+          (completions--deselect))))))
+
+(defun completions--after-change ()
+  "Update displayed *Completions* buffer after change in minibuffer contents."
+  (when (minibufferp)
+    (completions--update-if-displayed)))
+
+(defvar-local minibuffer--old-point nil)
+
+(defun completions--post-command ()
+  "Update displayed *Completions* buffer after change in minibuffer point."
+  (when (and (minibufferp) (not (eq minibuffer--old-point (point))))
+    (setq minibuffer--old-point (point))
+    (completions--update-if-displayed)))
+
 (defun minibuffer-completion-help (&optional start end)
   "Display a list of possible completions of the current minibuffer contents."
   (interactive)
@@ -2413,6 +2459,8 @@ minibuffer-completion-help
           ;; If there are no completions, or if the current input is already
           ;; the sole completion, then hide (previous&stale) completions.
           (minibuffer-hide-completions)
+          (remove-hook 'post-command-hook #'completions--post-command t)
+          (remove-hook 'after-change-hook #'completions--after-change t)
           (if completions
               (completion--message "Sole completion")
             (unless completion-fail-discreetly
@@ -2476,6 +2524,9 @@ minibuffer-completion-help
             (body-function
              . ,#'(lambda (window)
                     (with-current-buffer mainbuf
+                      (when completions-auto-update
+                        (add-hook 'post-command-hook #'completions--post-command nil t)
+                        (add-hook 'after-change-hook #'completions--after-change t))
                       ;; Remove the base-size tail because `sort' requires a properly
                       ;; nil-terminated list.
                       (when last (setcdr last nil))
@@ -4688,7 +4739,8 @@ minibuffer-next-completion
           (next-line-completion (or n 1))
         (next-completion (or n 1)))
       (when auto-choose
-        (let ((completion-use-base-affixes t))
+        (let ((completion-use-base-affixes t)
+              (completions-auto-update nil))
           (choose-completion nil t t))))))
 
 (defun minibuffer-previous-completion (&optional n)
-- 
2.42.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-18 20:58                               ` sbaugh
@ 2023-11-19  7:08                                 ` Juri Linkov
  2023-11-19  8:19                                   ` Eli Zaretskii
  2023-11-19 14:41                                   ` Spencer Baugh
  0 siblings, 2 replies; 62+ messages in thread
From: Juri Linkov @ 2023-11-19  7:08 UTC (permalink / raw)
  To: sbaugh; +Cc: emacs-devel

> OK, how about this?  It's an adapted version of my
> completions-auto-update patch, which provides (for now) only the feature
> of deselecting the completion when point moves or the minibuffer
> changes.  The infrastructure for doing this turns out to be basically
> identical, which is interesting.

Indeed, it's easier to start with a simpler case, and then gradually
to add handling of more cases to the same option.

> It sets completions-auto-update to 'deselect by default, which I think
> is reasonable?

Isn't deselection needed only when minibuffer-visible-completions is enabled?

> minibuffer-visible-completions makes RET submit the selected
> completion candidate, if any, ignoring the contents of the minibuffer.
> But a user might select a completion candidate and then want to type
> something else in the minibuffer and submit what they typed.
>
> * lisp/minibuffer.el (completion--insert): Add a space before each
> candidate.

I don't think anyone would like such a space shifting the whole layout
to the right.  Rather I'd recommend to use a space after each candidate.
There is already a space between candidates.  Only at the end a space is
missing.

Or without adding a space at the end we could change `choose-completion`
to not select the candidate when point is at the end (`choose-completion`
needs fixing anyway since currently it raises an error at the end
of the first completion in case of no header.)

This still won't solve the case of no header.  So in this case
for the initial position we could add a narrow line at the top:

  (propertize "\n" 'face '(:height 0))

This solves a lot of problems, and will help to remove the complicated
special-handling of the 'first-completion' text property in many places.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-19  7:08                                 ` Juri Linkov
@ 2023-11-19  8:19                                   ` Eli Zaretskii
  2023-11-19 14:41                                   ` Spencer Baugh
  1 sibling, 0 replies; 62+ messages in thread
From: Eli Zaretskii @ 2023-11-19  8:19 UTC (permalink / raw)
  To: Juri Linkov; +Cc: sbaugh, emacs-devel

> From: Juri Linkov <juri@linkov.net>
> Cc: emacs-devel@gnu.org
> Date: Sun, 19 Nov 2023 09:08:36 +0200
> 
> This still won't solve the case of no header.  So in this case
> for the initial position we could add a narrow line at the top:
> 
>   (propertize "\n" 'face '(:height 0))

This only works on GUI frames, no?



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-19  7:08                                 ` Juri Linkov
  2023-11-19  8:19                                   ` Eli Zaretskii
@ 2023-11-19 14:41                                   ` Spencer Baugh
  2023-11-19 18:01                                     ` Juri Linkov
  2023-11-23 13:39                                     ` sbaugh
  1 sibling, 2 replies; 62+ messages in thread
From: Spencer Baugh @ 2023-11-19 14:41 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

Juri Linkov <juri@linkov.net> writes:
>> It sets completions-auto-update to 'deselect by default, which I think
>> is reasonable?
>
> Isn't deselection needed only when minibuffer-visible-completions is enabled?

I think we could provide some nice consistency by making it always
active.

As part of this change, I think we should make sure M-RET will submit a
completion candidate even if it's been "deselected".  That would be nice
because then M-RET serves a useful purpose with
minibuffer-visible-completions=t: you can submit the previously-selected
completion candidate even if you've typed (causing deselection) since
selecting it.

With that M-RET behavior, completions-auto-update='deselect doesn't
change behavior from Emacs 29, so I think it's a plausible default.

And if we do have completions-auto-update='deselect by default, then
perhaps we can consider another change to the defaults: make RET always
submit the selected completion candidate.  That would actually change
behavior, since M-<down> followed *immediately* by RET would submit the
selected completion candidate, but maybe it's worth it?

>> minibuffer-visible-completions makes RET submit the selected
>> completion candidate, if any, ignoring the contents of the minibuffer.
>> But a user might select a completion candidate and then want to type
>> something else in the minibuffer and submit what they typed.
>>
>> * lisp/minibuffer.el (completion--insert): Add a space before each
>> candidate.
>
> I don't think anyone would like such a space shifting the whole layout
> to the right.  Rather I'd recommend to use a space after each candidate.
> There is already a space between candidates.  Only at the end a space is
> missing.
>
> Or without adding a space at the end we could change `choose-completion`
> to not select the candidate when point is at the end

Oh, yes, I definitely like the idea of not submitting the candidate when
point is at the end, no need for any extra space.  This would work well
with my thought about having M-RET to submitting even a "deselected"
candidate: the new behavior of not submitting a candidate when point is
at the end would only be active for the new command
minibuffer-choose-completion-or-exit.

> (`choose-completion` needs fixing anyway since currently it raises an
> error at the end of the first completion in case of no header.)
>
> This still won't solve the case of no header.  So in this case
> for the initial position we could add a narrow line at the top:
>
>   (propertize "\n" 'face '(:height 0))
>
> This solves a lot of problems, and will help to remove the complicated
> special-handling of the 'first-completion' text property in many places.

This seems fine to me, but as Eli points out, terminal users probably
won't like the extra "wasted" line.  Maybe if we're in the terminal and
there's no header, we could add a single space before the first
completion?



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-19 14:41                                   ` Spencer Baugh
@ 2023-11-19 18:01                                     ` Juri Linkov
  2023-11-19 19:41                                       ` Spencer Baugh
  2023-11-20  2:58                                       ` Spencer Baugh
  2023-11-23 13:39                                     ` sbaugh
  1 sibling, 2 replies; 62+ messages in thread
From: Juri Linkov @ 2023-11-19 18:01 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: emacs-devel

>>> It sets completions-auto-update to 'deselect by default, which I think
>>> is reasonable?
>>
>> Isn't deselection needed only when minibuffer-visible-completions is enabled?
>
> I think we could provide some nice consistency by making it always
> active.
>
> As part of this change, I think we should make sure M-RET will submit a
> completion candidate even if it's been "deselected".  That would be nice
> because then M-RET serves a useful purpose with
> minibuffer-visible-completions=t: you can submit the previously-selected
> completion candidate even if you've typed (causing deselection) since
> selecting it.
>
> With that M-RET behavior, completions-auto-update='deselect doesn't
> change behavior from Emacs 29, so I think it's a plausible default.

Please note that currently there is no need to use M-RET by default
because the default value of minibuffer-completion-auto-choose is t,
and M-down inserts the candidate that is accepted by RET.

So M-RET could help only in case of minibuffer-visible-completions=t
when the editing deselected a completion candidate.

> And if we do have completions-auto-update='deselect by default, then
> perhaps we can consider another change to the defaults: make RET always
> submit the selected completion candidate.  That would actually change
> behavior, since M-<down> followed *immediately* by RET would submit the
> selected completion candidate, but maybe it's worth it?

I doubt that any change of the default behavior would be acceptable.

>>> * lisp/minibuffer.el (completion--insert): Add a space before each
>>> candidate.
>>
>> I don't think anyone would like such a space shifting the whole layout
>> to the right.  Rather I'd recommend to use a space after each candidate.
>> There is already a space between candidates.  Only at the end a space is
>> missing.
>>
>> Or without adding a space at the end we could change `choose-completion`
>> to not select the candidate when point is at the end
>
> Oh, yes, I definitely like the idea of not submitting the candidate when
> point is at the end, no need for any extra space.  This would work well
> with my thought about having M-RET to submitting even a "deselected"
> candidate: the new behavior of not submitting a candidate when point is
> at the end would only be active for the new command
> minibuffer-choose-completion-or-exit.

Agreed, so M-RET will override the logic of RET.

>> (`choose-completion` needs fixing anyway since currently it raises an
>> error at the end of the first completion in case of no header.)
>>
>> This still won't solve the case of no header.  So in this case
>> for the initial position we could add a narrow line at the top:
>>
>>   (propertize "\n" 'face '(:height 0))
>>
>> This solves a lot of problems, and will help to remove the complicated
>> special-handling of the 'first-completion' text property in many places.
>
> This seems fine to me, but as Eli points out, terminal users probably
> won't like the extra "wasted" line.  Maybe if we're in the terminal and
> there's no header, we could add a single space before the first
> completion?

A single space the first completion will break the vertical alignment.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-19 18:01                                     ` Juri Linkov
@ 2023-11-19 19:41                                       ` Spencer Baugh
  2023-11-20  2:58                                       ` Spencer Baugh
  1 sibling, 0 replies; 62+ messages in thread
From: Spencer Baugh @ 2023-11-19 19:41 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

Juri Linkov <juri@linkov.net> writes:
>>> This still won't solve the case of no header.  So in this case
>>> for the initial position we could add a narrow line at the top:
>>>
>>>   (propertize "\n" 'face '(:height 0))
>>>
>>> This solves a lot of problems, and will help to remove the complicated
>>> special-handling of the 'first-completion' text property in many places.
>>
>> This seems fine to me, but as Eli points out, terminal users probably
>> won't like the extra "wasted" line.  Maybe if we're in the terminal and
>> there's no header, we could add a single space before the first
>> completion?
>
> A single space the first completion will break the vertical alignment.

This is true, but inserting an empty newline will basically counteract
completions-header-format=nil.  (Perhaps that shouldn't have been
customizable in the first place...)



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-19 18:01                                     ` Juri Linkov
  2023-11-19 19:41                                       ` Spencer Baugh
@ 2023-11-20  2:58                                       ` Spencer Baugh
  1 sibling, 0 replies; 62+ messages in thread
From: Spencer Baugh @ 2023-11-20  2:58 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

Juri Linkov <juri@linkov.net> writes:
>>>> It sets completions-auto-update to 'deselect by default, which I think
>>>> is reasonable?
>>>
>>> Isn't deselection needed only when minibuffer-visible-completions is enabled?
>>
>> I think we could provide some nice consistency by making it always
>> active.
>>
>> As part of this change, I think we should make sure M-RET will submit a
>> completion candidate even if it's been "deselected".  That would be nice
>> because then M-RET serves a useful purpose with
>> minibuffer-visible-completions=t: you can submit the previously-selected
>> completion candidate even if you've typed (causing deselection) since
>> selecting it.
>>
>> With that M-RET behavior, completions-auto-update='deselect doesn't
>> change behavior from Emacs 29, so I think it's a plausible default.
>
> Please note that currently there is no need to use M-RET by default
> because the default value of minibuffer-completion-auto-choose is t,
> and M-down inserts the candidate that is accepted by RET.
>
> So M-RET could help only in case of minibuffer-visible-completions=t
> when the editing deselected a completion candidate.

That is true.  But M-RET is still important for completion-in-region.

In any case, deselecting by default doesn't change behavior for any of:
- completion-in-region
- minibuffer completion with minibuffer-completion-auto-choose=t
- minibuffer completion with minibuffer-completion-auto-choose=nil

So I think deselecting by default is a backwards-compatible change.

>> And if we do have completions-auto-update='deselect by default, then
>> perhaps we can consider another change to the defaults: make RET always
>> submit the selected completion candidate.  That would actually change
>> behavior, since M-<down> followed *immediately* by RET would submit the
>> selected completion candidate, but maybe it's worth it?
>
> I doubt that any change of the default behavior would be acceptable.

Well, M-<down>/M-<up> have only been present in one version of Emacs, so
a change to their default behavior, which supports an opt-out, seems
possible if it's a real improvement.  But anyway, this is better to
discuss once we've settled on the design of the deselection behavior.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-19 14:41                                   ` Spencer Baugh
  2023-11-19 18:01                                     ` Juri Linkov
@ 2023-11-23 13:39                                     ` sbaugh
  2023-11-24  7:54                                       ` Juri Linkov
  1 sibling, 1 reply; 62+ messages in thread
From: sbaugh @ 2023-11-23 13:39 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1222 bytes --]


Spencer Baugh <sbaugh@catern.com> writes:
>>> minibuffer-visible-completions makes RET submit the selected
>>> completion candidate, if any, ignoring the contents of the minibuffer.
>>> But a user might select a completion candidate and then want to type
>>> something else in the minibuffer and submit what they typed.
>>>
>>> * lisp/minibuffer.el (completion--insert): Add a space before each
>>> candidate.
>>
>> I don't think anyone would like such a space shifting the whole layout
>> to the right.  Rather I'd recommend to use a space after each candidate.
>> There is already a space between candidates.  Only at the end a space is
>> missing.
>>
>> Or without adding a space at the end we could change `choose-completion`
>> to not select the candidate when point is at the end
>
> Oh, yes, I definitely like the idea of not submitting the candidate when
> point is at the end, no need for any extra space.  This would work well
> with my thought about having M-RET to submitting even a "deselected"
> candidate: the new behavior of not submitting a candidate when point is
> at the end would only be active for the new command
> minibuffer-choose-completion-or-exit.

Here's an update patch with this approach.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Deselect-the-selected-completion-candidate-when-typi.patch --]
[-- Type: text/x-patch, Size: 7738 bytes --]

From 19344d19df371a7432ceb74f66c0f7ece9b4eed0 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh@catern.com>
Date: Thu, 23 Nov 2023 13:37:29 +0000
Subject: [PATCH] Deselect the selected completion candidate when typing

minibuffer-choose-completion-or-exit submits the selected completion
candidate, if any, ignoring the contents of the minibuffer.  But a
user might select a completion candidate and then want to type
something else in the minibuffer and submit what they typed.

Now typing will automatically deselect the selected completion
candidate so that minibuffer-choose-completion-or-exit will not choose
it.

minibuffer-choose-completion has the same behavior as before, and is
not affected by the deselection.

* lisp/minibuffer.el (completions-auto-update, completions--deselect)
(completions--update-if-displayed, completions--after-change)
(minibuffer--old-point, completions--post-command): Add.
(minibuffer-completion-help): Add completions--after-change and
completions--post-command as hooks.
(minibuffer-next-completion): Bind completions-auto-update to nil to
avoid immediately deselecting the completion.
(minibuffer-choose-completion-or-exit): Bind
choose-completion-deselect-if-after so deselection takes effect.
* lisp/simple.el (choose-completion-deselect-if-after): Add.
(completions--get-posn): Check choose-completion-deselect-if-after.
---
 lisp/minibuffer.el | 57 ++++++++++++++++++++++++++++++++++++++++++++--
 lisp/simple.el     | 39 ++++++++++++++++++-------------
 2 files changed, 78 insertions(+), 18 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index dd29c155fd3..990a69b35bb 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2440,6 +2440,52 @@ completions--fit-window-to-buffer
         (resize-temp-buffer-window win))
     (fit-window-to-buffer win completions-max-height)))
 
+(defcustom completions-auto-update 'deselect
+  "If non-nil, change the *Completions* buffer as you type.
+
+If `deselect', if a completion candidate in *Completions* is
+selected (point is on it), it will be deselected (point will be
+moved just before it) when the minibuffer point or contents
+change.
+
+This only affects the *Completions* buffer if it is already
+displayed."
+  :type '(choice (const :tag "*Completions* doesn't change as you type" nil)
+                 (const :tag "Typing deselects any completion candidate in *Completions*" deselect))
+  :version "30.1")
+
+(defun completions--deselect ()
+  "If in a completion candidate, move to just after the end of it.
+
+The candidate will still be chosen by `choose-completion' unless
+`choose-completion-deselect-if-after' is non-nil."
+  (when (get-text-property (point) 'mouse-face)
+    (goto-char (or (next-single-property-change (point) 'mouse-face)
+                   (point-max)))))
+
+(defun completions--update-if-displayed ()
+  "Update a displayed *Completions* buffer based on `completions-auto-update'"
+  (when completions-auto-update
+    (when-let (window (get-buffer-window "*Completions*" 0))
+      (with-selected-window window
+        (when (eq completions-auto-update 'deselect)
+          (completions--deselect))))))
+
+(defun completions--after-change ()
+  "Update displayed *Completions* buffer after change in minibuffer contents."
+  (when (minibufferp)
+    (completions--update-if-displayed)))
+
+(defvar-local minibuffer--old-point nil)
+
+(defun completions--post-command ()
+  "Update displayed *Completions* buffer after change in minibuffer point."
+  (when (and (minibufferp) (not (eq minibuffer--old-point (point))))
+    (setq minibuffer--old-point (point))
+    (unless (and completions-auto-update
+                 (memq this-command '(minibuffer-next-completion minibuffer-previous-completion)))
+      (completions--update-if-displayed))))
+
 (defun minibuffer-completion-help (&optional start end)
   "Display a list of possible completions of the current minibuffer contents."
   (interactive)
@@ -2462,6 +2508,8 @@ minibuffer-completion-help
           ;; If there are no completions, or if the current input is already
           ;; the sole completion, then hide (previous&stale) completions.
           (minibuffer-hide-completions)
+          (remove-hook 'post-command-hook #'completions--post-command t)
+          (remove-hook 'after-change-hook #'completions--after-change t)
           (if completions
               (completion--message "Sole completion")
             (unless completion-fail-discreetly
@@ -2526,6 +2574,9 @@ minibuffer-completion-help
             (body-function
              . ,#'(lambda (window)
                     (with-current-buffer mainbuf
+                      (when completions-auto-update
+                        (add-hook 'post-command-hook #'completions--post-command nil t)
+                        (add-hook 'after-change-hook #'completions--after-change t))
                       ;; Remove the base-size tail because `sort' requires a properly
                       ;; nil-terminated list.
                       (when last (setcdr last nil))
@@ -4739,7 +4790,8 @@ minibuffer-next-completion
           (next-line-completion (or n 1))
         (next-completion (or n 1)))
       (when auto-choose
-        (let ((completion-use-base-affixes t))
+        (let ((completion-use-base-affixes t)
+              (completions-auto-update nil))
           (choose-completion nil t t))))))
 
 (defun minibuffer-previous-completion (&optional n)
@@ -4787,7 +4839,8 @@ minibuffer-choose-completion-or-exit
 contents."
   (interactive "P")
   (condition-case nil
-      (minibuffer-choose-completion no-exit no-quit)
+      (let ((choose-completion-deselect-if-after t))
+        (minibuffer-choose-completion no-exit no-quit))
     (error (minibuffer-complete-and-exit))))
 
 (defun minibuffer-complete-history ()
diff --git a/lisp/simple.el b/lisp/simple.el
index 34205a223a7..2043233738a 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10096,24 +10096,31 @@ next-line-completion
           (if pos (goto-char pos))))
       (setq n (1+ n)))))
 
+(defvar choose-completion-deselect-if-after nil
+  "If non-nil, don't choose a completion candidate if point is right after it.
+
+This makes `completions--deselect' effective.")
+
 (defun completions--get-posn (position)
   "Return the completion at POSITION as a string."
-  (save-excursion
-    (goto-char position)
-    (let (beg)
-      (cond
-       ((and (not (eobp))
-             (get-text-property (point) 'completion--string))
-        (setq beg (1+ (point))))
-       ((and (not (bobp))
-             (get-text-property (1- (point)) 'completion--string))
-        (setq beg (point))))
-      (when beg
-        (setq beg (or (previous-single-property-change
-                       beg 'completion--string)
-                      beg))
-        (substring-no-properties
-         (get-text-property beg 'completion--string))))))
+  (if choose-completion-deselect-if-after
+      (substring-no-properties (get-text-property position 'completion--string))
+    (save-excursion
+      (goto-char position)
+      (let (beg)
+        (cond
+         ((and (not (eobp))
+               (get-text-property (point) 'completion--string))
+          (setq beg (1+ (point))))
+         ((and (not (bobp))
+               (get-text-property (1- (point)) 'completion--string))
+          (setq beg (point))))
+        (when beg
+          (setq beg (or (previous-single-property-change
+                         beg 'completion--string)
+                        beg))
+          (substring-no-properties
+           (get-text-property beg 'completion--string)))))))
 
 (defun choose-completion (&optional event no-exit no-quit)
   "Choose the completion at point.
-- 
2.42.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-23 13:39                                     ` sbaugh
@ 2023-11-24  7:54                                       ` Juri Linkov
  2023-11-25 15:19                                         ` Spencer Baugh
  0 siblings, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-11-24  7:54 UTC (permalink / raw)
  To: sbaugh; +Cc: emacs-devel

> Here's an update patch with this approach.

Sorry, the patch can't be applied, there is no existing
completions--get-posn to change:

> +This makes `completions--deselect' effective.")
> +
>  (defun completions--get-posn (position)
>    "Return the completion at POSITION as a string."
> -  (save-excursion
> -    (goto-char position)



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-24  7:54                                       ` Juri Linkov
@ 2023-11-25 15:19                                         ` Spencer Baugh
  2023-11-25 16:08                                           ` Eli Zaretskii
  2023-11-25 17:46                                           ` Juri Linkov
  0 siblings, 2 replies; 62+ messages in thread
From: Spencer Baugh @ 2023-11-25 15:19 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 443 bytes --]

Juri Linkov <juri@linkov.net> writes:
>> Here's an update patch with this approach.
>
> Sorry, the patch can't be applied, there is no existing
> completions--get-posn to change:
>
>> +This makes `completions--deselect' effective.")
>> +
>>  (defun completions--get-posn (position)
>>    "Return the completion at POSITION as a string."
>> -  (save-excursion
>> -    (goto-char position)

Oops, here it is again rebased directly onto master.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Deselect-the-selected-completion-candidate-when-typi.patch --]
[-- Type: text/x-patch, Size: 7291 bytes --]

From 874b455870ffd6057fd63e353240a91a742b3c2d Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh@catern.com>
Date: Thu, 23 Nov 2023 13:37:29 +0000
Subject: [PATCH] Deselect the selected completion candidate when typing

minibuffer-choose-completion-or-exit submits the selected completion
candidate, if any, ignoring the contents of the minibuffer.  But a
user might select a completion candidate and then want to type
something else in the minibuffer and submit what they typed.

Now typing will automatically deselect the selected completion
candidate so that minibuffer-choose-completion-or-exit will not choose
it.

minibuffer-choose-completion has the same behavior as before, and is
not affected by the deselection.

* lisp/minibuffer.el (completions-auto-update, completions--deselect)
(completions--update-if-displayed, completions--after-change)
(minibuffer--old-point, completions--post-command): Add.
(minibuffer-completion-help): Add completions--after-change and
completions--post-command as hooks.
(minibuffer-next-completion): Bind completions-auto-update to nil to
avoid immediately deselecting the completion.
(minibuffer-choose-completion-or-exit): Bind
choose-completion-deselect-if-after so deselection takes effect.
* lisp/simple.el (choose-completion-deselect-if-after): Add.
(completions--get-posn): Check choose-completion-deselect-if-after.
---
 lisp/minibuffer.el | 57 ++++++++++++++++++++++++++++++++++++++++++++--
 lisp/simple.el     | 10 +++++++-
 2 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 5c12d9fc914..a6acd1e999b 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2378,6 +2378,52 @@ completions--fit-window-to-buffer
         (resize-temp-buffer-window win))
     (fit-window-to-buffer win completions-max-height)))
 
+(defcustom completions-auto-update 'deselect
+  "If non-nil, change the *Completions* buffer as you type.
+
+If `deselect', if a completion candidate in *Completions* is
+selected (point is on it), it will be deselected (point will be
+moved just before it) when the minibuffer point or contents
+change.
+
+This only affects the *Completions* buffer if it is already
+displayed."
+  :type '(choice (const :tag "*Completions* doesn't change as you type" nil)
+                 (const :tag "Typing deselects any completion candidate in *Completions*" deselect))
+  :version "30.1")
+
+(defun completions--deselect ()
+  "If in a completion candidate, move to just after the end of it.
+
+The candidate will still be chosen by `choose-completion' unless
+`choose-completion-deselect-if-after' is non-nil."
+  (when (get-text-property (point) 'mouse-face)
+    (goto-char (or (next-single-property-change (point) 'mouse-face)
+                   (point-max)))))
+
+(defun completions--update-if-displayed ()
+  "Update a displayed *Completions* buffer based on `completions-auto-update'"
+  (when completions-auto-update
+    (when-let (window (get-buffer-window "*Completions*" 0))
+      (with-selected-window window
+        (when (eq completions-auto-update 'deselect)
+          (completions--deselect))))))
+
+(defun completions--after-change ()
+  "Update displayed *Completions* buffer after change in minibuffer contents."
+  (when (minibufferp)
+    (completions--update-if-displayed)))
+
+(defvar-local minibuffer--old-point nil)
+
+(defun completions--post-command ()
+  "Update displayed *Completions* buffer after change in minibuffer point."
+  (when (and (minibufferp) (not (eq minibuffer--old-point (point))))
+    (setq minibuffer--old-point (point))
+    (unless (and completions-auto-update
+                 (memq this-command '(minibuffer-next-completion minibuffer-previous-completion)))
+      (completions--update-if-displayed))))
+
 (defun minibuffer-completion-help (&optional start end)
   "Display a list of possible completions of the current minibuffer contents."
   (interactive)
@@ -2400,6 +2446,8 @@ minibuffer-completion-help
           ;; If there are no completions, or if the current input is already
           ;; the sole completion, then hide (previous&stale) completions.
           (minibuffer-hide-completions)
+          (remove-hook 'post-command-hook #'completions--post-command t)
+          (remove-hook 'after-change-hook #'completions--after-change t)
           (if completions
               (completion--message "Sole completion")
             (unless completion-fail-discreetly
@@ -2460,6 +2508,9 @@ minibuffer-completion-help
             (body-function
              . ,#'(lambda (_window)
                     (with-current-buffer mainbuf
+                      (when completions-auto-update
+                        (add-hook 'post-command-hook #'completions--post-command nil t)
+                        (add-hook 'after-change-hook #'completions--after-change t))
                       ;; Remove the base-size tail because `sort' requires a properly
                       ;; nil-terminated list.
                       (when last (setcdr last nil))
@@ -4673,7 +4724,8 @@ minibuffer-next-completion
           (next-line-completion (or n 1))
         (next-completion (or n 1)))
       (when auto-choose
-        (let ((completion-use-base-affixes t))
+        (let ((completion-use-base-affixes t)
+              (completions-auto-update nil))
           (choose-completion nil t t))))))
 
 (defun minibuffer-previous-completion (&optional n)
@@ -4721,7 +4773,8 @@ minibuffer-choose-completion-or-exit
 contents."
   (interactive "P")
   (condition-case nil
-      (minibuffer-choose-completion no-exit no-quit)
+      (let ((choose-completion-deselect-if-after t))
+        (minibuffer-choose-completion no-exit no-quit))
     (error (minibuffer-complete-and-exit))))
 
 (defun minibuffer-complete-history ()
diff --git a/lisp/simple.el b/lisp/simple.el
index 02c68912dba..791b7dddedc 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10094,6 +10094,11 @@ next-line-completion
           (if pos (goto-char pos))))
       (setq n (1+ n)))))
 
+(defvar choose-completion-deselect-if-after nil
+  "If non-nil, don't choose a completion candidate if point is right after it.
+
+This makes `completions--deselect' effective.")
+
 (defun choose-completion (&optional event no-exit no-quit)
   "Choose the completion at point.
 If EVENT, use EVENT's position to determine the starting position.
@@ -10114,6 +10119,9 @@ choose-completion
           (insert-function completion-list-insert-choice-function)
           (completion-no-auto-exit (if no-exit t completion-no-auto-exit))
           (choice
+           (if choose-completion-deselect-if-after
+               (substring-no-properties
+                (get-text-property (posn-point (event-start event)) 'completion--string))
            (save-excursion
              (goto-char (posn-point (event-start event)))
              (let (beg)
@@ -10129,7 +10137,7 @@ choose-completion
                               beg 'completion--string)
                              beg))
                (substring-no-properties
-                (get-text-property beg 'completion--string))))))
+                (get-text-property beg 'completion--string)))))))
 
       (unless (buffer-live-p buffer)
         (error "Destination buffer is dead"))
-- 
2.42.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-25 15:19                                         ` Spencer Baugh
@ 2023-11-25 16:08                                           ` Eli Zaretskii
  2023-11-25 18:23                                             ` sbaugh
  2023-11-25 17:46                                           ` Juri Linkov
  1 sibling, 1 reply; 62+ messages in thread
From: Eli Zaretskii @ 2023-11-25 16:08 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: juri, emacs-devel

> From: Spencer Baugh <sbaugh@catern.com>
> Date: Sat, 25 Nov 2023 15:19:37 +0000 (UTC)
> Cc: emacs-devel@gnu.org
> 
> +(defcustom completions-auto-update 'deselect
> +  "If non-nil, change the *Completions* buffer as you type.
                  ^^^^^^
"Update", not "change".

> +If `deselect', if a completion candidate in *Completions* is
> +selected (point is on it), it will be deselected (point will be
> +moved just before it) when the minibuffer point or contents
> +change.

This has several issues.

First, "If `deselect'" is sub-optimal; it is better to say

  The value of `deselect' means that ...

The double "if" ("If `deselect', if a completion candidate...") is
also sub-optimal.  At the very least, if you need to say something
like that, say

  If this, then if that, ...

Finally, I'm guessing that the value `deselect' means to deslect the
candidate _in_addition_to_ update "*Completions*" as the user types.
If my guess is correct, please say

  The value of `deselect' means that in addition to updating
  *Completions*, the selected candidate will be deselected...

> +This only affects the *Completions* buffer if it is already
> +displayed."

Not sure what this sentence adds.  What will happen if you drop it?

> +  :type '(choice (const :tag "*Completions* doesn't change as you type" nil)
> +                 (const :tag "Typing deselects any completion candidate in *Completions*" deselect))

And now I see that my guess above perhaps was wrong: there's no value
t in the choice?  Then why not make this a simple boolean?

> +(defun completions--deselect ()
> +  "If in a completion candidate, move to just after the end of it.
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
"If point is at a completion candidate, ..."

> +(defun completions--post-command ()
> +  "Update displayed *Completions* buffer after change in minibuffer point."
> +  (when (and (minibufferp) (not (eq minibuffer--old-point (point))))
> +    (setq minibuffer--old-point (point))
> +    (unless (and completions-auto-update
> +                 (memq this-command '(minibuffer-next-completion minibuffer-previous-completion)))
> +      (completions--update-if-displayed))))

Ugh, another post-command hook...  It is small wonder users complain
that Emacs is slow to respond and feels sluggish.  What will happen if
the user types fast?  Could there be a design that doesn't use
post-command-hook?



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-25 15:19                                         ` Spencer Baugh
  2023-11-25 16:08                                           ` Eli Zaretskii
@ 2023-11-25 17:46                                           ` Juri Linkov
  2023-11-26 14:33                                             ` Spencer Baugh
  1 sibling, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-11-25 17:46 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: emacs-devel

> minibuffer-choose-completion-or-exit submits the selected completion
> candidate, if any, ignoring the contents of the minibuffer.  But a
> user might select a completion candidate and then want to type
> something else in the minibuffer and submit what they typed.

Thanks, everything works nicely now except the special case
of completion-show-help=nil and completions-header-format=nil.

Initially the first completion is deselected, and <down> selects it.
But when the first key typed is M-<down> the second completion
is selected instead of the first because M-<down> moves to the
second column when point is between the first and second completions.

A possible workaround would be to check the special property
'first-completion'.  But then when the logic uses text properties,
why not to use more text properties that indicate that a candidate
is deselected (and remove highlighting in this case) instead of
moving point somewhere outside of the candidate?



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-25 16:08                                           ` Eli Zaretskii
@ 2023-11-25 18:23                                             ` sbaugh
  2023-11-25 18:48                                               ` Juri Linkov
  2023-11-25 19:00                                               ` Eli Zaretskii
  0 siblings, 2 replies; 62+ messages in thread
From: sbaugh @ 2023-11-25 18:23 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: juri, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 3834 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:
>> From: Spencer Baugh <sbaugh@catern.com>
>> Date: Sat, 25 Nov 2023 15:19:37 +0000 (UTC)
>> Cc: emacs-devel@gnu.org
>> 
>> +(defcustom completions-auto-update 'deselect
>> +  "If non-nil, change the *Completions* buffer as you type.
>                   ^^^^^^
> "Update", not "change".

Fixed.

>> +If `deselect', if a completion candidate in *Completions* is
>> +selected (point is on it), it will be deselected (point will be
>> +moved just before it) when the minibuffer point or contents
>> +change.
>
> This has several issues.
>
> First, "If `deselect'" is sub-optimal; it is better to say
>
>   The value of `deselect' means that ...
>
> The double "if" ("If `deselect', if a completion candidate...") is
> also sub-optimal.  At the very least, if you need to say something
> like that, say
>
>   If this, then if that, ...

Fixed by rewriting the docstring.

> Finally, I'm guessing that the value `deselect' means to deslect the
> candidate _in_addition_to_ update "*Completions*" as the user types.
> If my guess is correct, please say
>
>   The value of `deselect' means that in addition to updating
>   *Completions*, the selected candidate will be deselected...
>
>> +This only affects the *Completions* buffer if it is already
>> +displayed."
>
> Not sure what this sentence adds.  What will happen if you drop it?

Dropped.

>> +  :type '(choice (const :tag "*Completions* doesn't change as you type" nil)
>> +                 (const :tag "Typing deselects any completion candidate in *Completions*" deselect))
>
> And now I see that my guess above perhaps was wrong: there's no value
> t in the choice?  Then why not make this a simple boolean?

I want to add another value later to support actually updating
*Completions* as the user types.  That value will include the current
'deselect behavior, but do even more, using the same machinery.  By just
having one option we avoid proliferation of completion-related options.

Actually, though, I think updating *Completions* doesn't have to mean
deselecting the currently selected candidate.  It might make sense to
support completions-auto-deselect=nil and completions-auto-update=t.  So
a separate option makes sense.

So I just change this option to be completions-auto-deselect, which is
specific to deselecting on typing.

>> +(defun completions--deselect ()
>> +  "If in a completion candidate, move to just after the end of it.
>       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> "If point is at a completion candidate, ..."
>
>> +(defun completions--post-command ()
>> +  "Update displayed *Completions* buffer after change in minibuffer point."
>> +  (when (and (minibufferp) (not (eq minibuffer--old-point (point))))
>> +    (setq minibuffer--old-point (point))
>> +    (unless (and completions-auto-update
>> +                 (memq this-command '(minibuffer-next-completion minibuffer-previous-completion)))
>> +      (completions--update-if-displayed))))
>
> Ugh, another post-command hook...  It is small wonder users complain
> that Emacs is slow to respond and feels sluggish.  What will happen if
> the user types fast?  Could there be a design that doesn't use
> post-command-hook?

Yes, actually, this can be dropped for now.  We only really need the
after-change-based updating.

The post-command-hook only serves to deselect the completion candidate
when the user moves point.  But that's probably not necessary and maybe
even undesirable.

The core of all of this is that we need to update what's displayed in a
different buffer (*Completions*) based on what the user is doing and
typing in one buffer (the minibuffer).  So I think a hook-based design
is our only option?  (Maybe redisplay of *Completions* could check if
the first buffer has changed and modify it?)

Anyway, dropped the post-command-hook.

Fixed patch:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Deselect-the-selected-completion-candidate-when-typi.patch --]
[-- Type: text/x-patch, Size: 6325 bytes --]

From ece9fefeb267a24a7a09b1828104b619a62ea2a7 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh@catern.com>
Date: Thu, 23 Nov 2023 13:37:29 +0000
Subject: [PATCH] Deselect the selected completion candidate when typing

minibuffer-choose-completion-or-exit submits the selected completion
candidate, if any, ignoring the contents of the minibuffer.  But a
user might select a completion candidate and then want to type
something else in the minibuffer and submit what they typed.

Now typing will automatically deselect the selected completion
candidate so that minibuffer-choose-completion-or-exit will not choose
it.

minibuffer-choose-completion has the same behavior as before, and is
not affected by the deselection.

* lisp/minibuffer.el (completions-auto-deselect, completions--deselect)
(completions--after-change): Add.
(minibuffer-completion-help): Add completions--after-change hook.
(minibuffer-next-completion): Bind completions-auto-deselect to nil to
avoid immediately deselecting the completion.
(minibuffer-choose-completion-or-exit): Bind
choose-completion-deselect-if-after so deselection takes effect.
* lisp/simple.el (choose-completion-deselect-if-after): Add.
(choose-completion): Check choose-completion-deselect-if-after.
---
 lisp/minibuffer.el | 36 ++++++++++++++++++++++++++++++++++--
 lisp/simple.el     | 10 +++++++++-
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 5c12d9fc914..69483ad2aa4 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2378,6 +2378,33 @@ completions--fit-window-to-buffer
         (resize-temp-buffer-window win))
     (fit-window-to-buffer win completions-max-height)))
 
+(defcustom completions-auto-deselect t
+  "If non-nil, deselect the selected completion candidate when you type.
+
+A non-nil value means that after typing, point in *Completions*
+will be moved off any completion candidates.  This means
+`minibuffer-choose-completion-or-exit' will exit with the
+minibuffer's current contents, instead of a completion candidate."
+  :type '(choice (const :tag "Candidates in *Completions* stay selected as you type" nil)
+                 (const :tag "Typing deselects any completion candidate in *Completions*" t))
+  :version "30.1")
+
+(defun completions--deselect ()
+  "If point is in a completion candidate, move to just after the end of it.
+
+The candidate will still be chosen by `choose-completion' unless
+`choose-completion-deselect-if-after' is non-nil."
+  (when (get-text-property (point) 'mouse-face)
+    (goto-char (or (next-single-property-change (point) 'mouse-face)
+                   (point-max)))))
+
+(defun completions--after-change (_start _end _old-len)
+  "Update displayed *Completions* buffer after change in buffer contents."
+  (when completions-auto-deselect
+    (when-let (window (get-buffer-window "*Completions*" 0))
+      (with-selected-window window
+        (completions--deselect)))))
+
 (defun minibuffer-completion-help (&optional start end)
   "Display a list of possible completions of the current minibuffer contents."
   (interactive)
@@ -2400,6 +2427,7 @@ minibuffer-completion-help
           ;; If there are no completions, or if the current input is already
           ;; the sole completion, then hide (previous&stale) completions.
           (minibuffer-hide-completions)
+          (remove-hook 'after-change-functions #'completions--after-change t)
           (if completions
               (completion--message "Sole completion")
             (unless completion-fail-discreetly
@@ -2460,6 +2488,8 @@ minibuffer-completion-help
             (body-function
              . ,#'(lambda (_window)
                     (with-current-buffer mainbuf
+                      (when completions-auto-deselect
+                        (add-hook 'after-change-functions #'completions--after-change t))
                       ;; Remove the base-size tail because `sort' requires a properly
                       ;; nil-terminated list.
                       (when last (setcdr last nil))
@@ -4673,7 +4703,8 @@ minibuffer-next-completion
           (next-line-completion (or n 1))
         (next-completion (or n 1)))
       (when auto-choose
-        (let ((completion-use-base-affixes t))
+        (let ((completion-use-base-affixes t)
+              (completions-auto-deselect nil))
           (choose-completion nil t t))))))
 
 (defun minibuffer-previous-completion (&optional n)
@@ -4721,7 +4752,8 @@ minibuffer-choose-completion-or-exit
 contents."
   (interactive "P")
   (condition-case nil
-      (minibuffer-choose-completion no-exit no-quit)
+      (let ((choose-completion-deselect-if-after t))
+        (minibuffer-choose-completion no-exit no-quit))
     (error (minibuffer-complete-and-exit))))
 
 (defun minibuffer-complete-history ()
diff --git a/lisp/simple.el b/lisp/simple.el
index 02c68912dba..791b7dddedc 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10094,6 +10094,11 @@ next-line-completion
           (if pos (goto-char pos))))
       (setq n (1+ n)))))
 
+(defvar choose-completion-deselect-if-after nil
+  "If non-nil, don't choose a completion candidate if point is right after it.
+
+This makes `completions--deselect' effective.")
+
 (defun choose-completion (&optional event no-exit no-quit)
   "Choose the completion at point.
 If EVENT, use EVENT's position to determine the starting position.
@@ -10114,6 +10119,9 @@ choose-completion
           (insert-function completion-list-insert-choice-function)
           (completion-no-auto-exit (if no-exit t completion-no-auto-exit))
           (choice
+           (if choose-completion-deselect-if-after
+               (substring-no-properties
+                (get-text-property (posn-point (event-start event)) 'completion--string))
            (save-excursion
              (goto-char (posn-point (event-start event)))
              (let (beg)
@@ -10129,7 +10137,7 @@ choose-completion
                               beg 'completion--string)
                              beg))
                (substring-no-properties
-                (get-text-property beg 'completion--string))))))
+                (get-text-property beg 'completion--string)))))))
 
       (unless (buffer-live-p buffer)
         (error "Destination buffer is dead"))
-- 
2.42.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-25 18:23                                             ` sbaugh
@ 2023-11-25 18:48                                               ` Juri Linkov
  2023-11-26 13:10                                                 ` sbaugh
  2023-11-25 19:00                                               ` Eli Zaretskii
  1 sibling, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-11-25 18:48 UTC (permalink / raw)
  To: sbaugh; +Cc: Eli Zaretskii, emacs-devel

> +(defcustom completions-auto-deselect t

BTW, all related options have the same prefix `completion-auto-',
i.e. singular when related to the minibuffer, and plural
when used only for the *Completions* buffer.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-25 18:23                                             ` sbaugh
  2023-11-25 18:48                                               ` Juri Linkov
@ 2023-11-25 19:00                                               ` Eli Zaretskii
  1 sibling, 0 replies; 62+ messages in thread
From: Eli Zaretskii @ 2023-11-25 19:00 UTC (permalink / raw)
  To: sbaugh; +Cc: juri, emacs-devel

> From: sbaugh@catern.com
> Date: Sat, 25 Nov 2023 18:23:25 +0000 (UTC)
> Cc: juri@linkov.net, emacs-devel@gnu.org
> 
> > Ugh, another post-command hook...  It is small wonder users complain
> > that Emacs is slow to respond and feels sluggish.  What will happen if
> > the user types fast?  Could there be a design that doesn't use
> > post-command-hook?
> 
> Yes, actually, this can be dropped for now.  We only really need the
> after-change-based updating.
> 
> The post-command-hook only serves to deselect the completion candidate
> when the user moves point.  But that's probably not necessary and maybe
> even undesirable.
> 
> The core of all of this is that we need to update what's displayed in a
> different buffer (*Completions*) based on what the user is doing and
> typing in one buffer (the minibuffer).  So I think a hook-based design
> is our only option?

No, you could use an idle timer as well.  The advantage is that if the
user is typing fast, an idle timer based design will not make Emacs
less responsive.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-25 18:48                                               ` Juri Linkov
@ 2023-11-26 13:10                                                 ` sbaugh
  0 siblings, 0 replies; 62+ messages in thread
From: sbaugh @ 2023-11-26 13:10 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Eli Zaretskii, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 285 bytes --]

Juri Linkov <juri@linkov.net> writes:

>> +(defcustom completions-auto-deselect t
>
> BTW, all related options have the same prefix `completion-auto-',
> i.e. singular when related to the minibuffer, and plural
> when used only for the *Completions* buffer.

Renamed for consistency.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Deselect-the-selected-completion-candidate-when-typi.patch --]
[-- Type: text/x-patch, Size: 6319 bytes --]

From 8d97da6d1a4247407f508b2b37da3d49ee839135 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh@catern.com>
Date: Thu, 23 Nov 2023 13:37:29 +0000
Subject: [PATCH] Deselect the selected completion candidate when typing

minibuffer-choose-completion-or-exit submits the selected completion
candidate, if any, ignoring the contents of the minibuffer.  But a
user might select a completion candidate and then want to type
something else in the minibuffer and submit what they typed.

Now typing will automatically deselect the selected completion
candidate so that minibuffer-choose-completion-or-exit will not choose
it.

minibuffer-choose-completion has the same behavior as before, and is
not affected by the deselection.

* lisp/minibuffer.el (completion-auto-deselect, completions--deselect)
(completions--after-change): Add.
(minibuffer-completion-help): Add completions--after-change hook.
(minibuffer-next-completion): Bind completion-auto-deselect to nil to
avoid immediately deselecting the completion.
(minibuffer-choose-completion-or-exit): Bind
choose-completion-deselect-if-after so deselection takes effect.
* lisp/simple.el (choose-completion-deselect-if-after): Add.
(choose-completion): Check choose-completion-deselect-if-after.
---
 lisp/minibuffer.el | 36 ++++++++++++++++++++++++++++++++++--
 lisp/simple.el     | 10 +++++++++-
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 5c12d9fc914..841d29d12de 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2378,6 +2378,33 @@ completions--fit-window-to-buffer
         (resize-temp-buffer-window win))
     (fit-window-to-buffer win completions-max-height)))
 
+(defcustom completion-auto-deselect t
+  "If non-nil, deselect the selected completion candidate when you type.
+
+A non-nil value means that after typing, point in *Completions*
+will be moved off any completion candidates.  This means
+`minibuffer-choose-completion-or-exit' will exit with the
+minibuffer's current contents, instead of a completion candidate."
+  :type '(choice (const :tag "Candidates in *Completions* stay selected as you type" nil)
+                 (const :tag "Typing deselects any completion candidate in *Completions*" t))
+  :version "30.1")
+
+(defun completions--deselect ()
+  "If point is in a completion candidate, move to just after the end of it.
+
+The candidate will still be chosen by `choose-completion' unless
+`choose-completion-deselect-if-after' is non-nil."
+  (when (get-text-property (point) 'mouse-face)
+    (goto-char (or (next-single-property-change (point) 'mouse-face)
+                   (point-max)))))
+
+(defun completions--after-change (_start _end _old-len)
+  "Update displayed *Completions* buffer after change in buffer contents."
+  (when completion-auto-deselect
+    (when-let (window (get-buffer-window "*Completions*" 0))
+      (with-selected-window window
+        (completions--deselect)))))
+
 (defun minibuffer-completion-help (&optional start end)
   "Display a list of possible completions of the current minibuffer contents."
   (interactive)
@@ -2400,6 +2427,7 @@ minibuffer-completion-help
           ;; If there are no completions, or if the current input is already
           ;; the sole completion, then hide (previous&stale) completions.
           (minibuffer-hide-completions)
+          (remove-hook 'after-change-functions #'completions--after-change t)
           (if completions
               (completion--message "Sole completion")
             (unless completion-fail-discreetly
@@ -2460,6 +2488,8 @@ minibuffer-completion-help
             (body-function
              . ,#'(lambda (_window)
                     (with-current-buffer mainbuf
+                      (when completion-auto-deselect
+                        (add-hook 'after-change-functions #'completions--after-change t))
                       ;; Remove the base-size tail because `sort' requires a properly
                       ;; nil-terminated list.
                       (when last (setcdr last nil))
@@ -4673,7 +4703,8 @@ minibuffer-next-completion
           (next-line-completion (or n 1))
         (next-completion (or n 1)))
       (when auto-choose
-        (let ((completion-use-base-affixes t))
+        (let ((completion-use-base-affixes t)
+              (completion-auto-deselect nil))
           (choose-completion nil t t))))))
 
 (defun minibuffer-previous-completion (&optional n)
@@ -4721,7 +4752,8 @@ minibuffer-choose-completion-or-exit
 contents."
   (interactive "P")
   (condition-case nil
-      (minibuffer-choose-completion no-exit no-quit)
+      (let ((choose-completion-deselect-if-after t))
+        (minibuffer-choose-completion no-exit no-quit))
     (error (minibuffer-complete-and-exit))))
 
 (defun minibuffer-complete-history ()
diff --git a/lisp/simple.el b/lisp/simple.el
index 02c68912dba..791b7dddedc 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10094,6 +10094,11 @@ next-line-completion
           (if pos (goto-char pos))))
       (setq n (1+ n)))))
 
+(defvar choose-completion-deselect-if-after nil
+  "If non-nil, don't choose a completion candidate if point is right after it.
+
+This makes `completions--deselect' effective.")
+
 (defun choose-completion (&optional event no-exit no-quit)
   "Choose the completion at point.
 If EVENT, use EVENT's position to determine the starting position.
@@ -10114,6 +10119,9 @@ choose-completion
           (insert-function completion-list-insert-choice-function)
           (completion-no-auto-exit (if no-exit t completion-no-auto-exit))
           (choice
+           (if choose-completion-deselect-if-after
+               (substring-no-properties
+                (get-text-property (posn-point (event-start event)) 'completion--string))
            (save-excursion
              (goto-char (posn-point (event-start event)))
              (let (beg)
@@ -10129,7 +10137,7 @@ choose-completion
                               beg 'completion--string)
                              beg))
                (substring-no-properties
-                (get-text-property beg 'completion--string))))))
+                (get-text-property beg 'completion--string)))))))
 
       (unless (buffer-live-p buffer)
         (error "Destination buffer is dead"))
-- 
2.42.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-25 17:46                                           ` Juri Linkov
@ 2023-11-26 14:33                                             ` Spencer Baugh
  2023-11-27  7:22                                               ` Juri Linkov
  0 siblings, 1 reply; 62+ messages in thread
From: Spencer Baugh @ 2023-11-26 14:33 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1634 bytes --]

Juri Linkov <juri@linkov.net> writes:
>> minibuffer-choose-completion-or-exit submits the selected completion
>> candidate, if any, ignoring the contents of the minibuffer.  But a
>> user might select a completion candidate and then want to type
>> something else in the minibuffer and submit what they typed.
>
> Thanks, everything works nicely now except the special case
> of completion-show-help=nil and completions-header-format=nil.
>
> Initially the first completion is deselected, and <down> selects it.
> But when the first key typed is M-<down> the second completion
> is selected instead of the first because M-<down> moves to the
> second column when point is between the first and second completions.

I was thinking that issue is unrelated to this patch and so it could be
fixed separately.  But actually I guess this patch makes it more visible
indeed, so I guess we need to fix it now.

I think the "add a thin newline" approach is totally fine.  I did that
in my attached patch.

> A possible workaround would be to check the special property
> 'first-completion'.  But then when the logic uses text properties,
> why not to use more text properties that indicate that a candidate
> is deselected (and remove highlighting in this case) instead of
> moving point somewhere outside of the candidate?

Even if we work around this with text properties, I think it's nice for
deselection to be usually determined by location of point.  I think
that's easier to understand for the user - they should be able to
deselect or reselect something purely by moving point around, it
shouldn't require text property manipulation.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Deselect-the-selected-completion-candidate-when-typi.patch --]
[-- Type: text/x-patch, Size: 7133 bytes --]

From f4e2bdda0e30af933bee896aa7b5ca2b22684ab5 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh@catern.com>
Date: Thu, 23 Nov 2023 13:37:29 +0000
Subject: [PATCH] Deselect the selected completion candidate when typing

minibuffer-choose-completion-or-exit submits the selected completion
candidate, if any, ignoring the contents of the minibuffer.  But a
user might select a completion candidate and then want to type
something else in the minibuffer and submit what they typed.

Now typing will automatically deselect the selected completion
candidate so that minibuffer-choose-completion-or-exit will not choose
it.

minibuffer-choose-completion has the same behavior as before, and is
not affected by the deselection.

* lisp/minibuffer.el (completion-auto-deselect, completions--deselect)
(completions--after-change): Add.
(minibuffer-completion-help): Add completions--after-change hook.
(minibuffer-next-completion): Bind completion-auto-deselect to nil to
avoid immediately deselecting the completion.
(minibuffer-choose-completion-or-exit): Bind
choose-completion-deselect-if-after so deselection takes effect.
(display-completion-list): Guarantee a newline at the beginning of
*Completions* to avoid ambiguity about candidate selection.
* lisp/simple.el (choose-completion-deselect-if-after): Add.
(choose-completion): Check choose-completion-deselect-if-after.
---
 lisp/minibuffer.el | 43 +++++++++++++++++++++++++++++++++++++++----
 lisp/simple.el     | 11 ++++++++++-
 2 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 5c12d9fc914..303170125ff 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2310,8 +2310,11 @@ display-completion-list
 
     (with-current-buffer standard-output
       (goto-char (point-max))
-      (when completions-header-format
-        (insert (format completions-header-format (length completions))))
+      (if completions-header-format
+          (insert (format completions-header-format (length completions)))
+        (unless completion-show-help
+          ;; Ensure beginning-of-buffer isn't a completion.
+          (insert (propertize "\n" 'face '(:height 0)))))
       (completion--insert-strings completions group-fun)))
 
   (run-hooks 'completion-setup-hook)
@@ -2378,6 +2381,33 @@ completions--fit-window-to-buffer
         (resize-temp-buffer-window win))
     (fit-window-to-buffer win completions-max-height)))
 
+(defcustom completion-auto-deselect t
+  "If non-nil, deselect the selected completion candidate when you type.
+
+A non-nil value means that after typing, point in *Completions*
+will be moved off any completion candidates.  This means
+`minibuffer-choose-completion-or-exit' will exit with the
+minibuffer's current contents, instead of a completion candidate."
+  :type '(choice (const :tag "Candidates in *Completions* stay selected as you type" nil)
+                 (const :tag "Typing deselects any completion candidate in *Completions*" t))
+  :version "30.1")
+
+(defun completions--deselect ()
+  "If point is in a completion candidate, move to just after the end of it.
+
+The candidate will still be chosen by `choose-completion' unless
+`choose-completion-deselect-if-after' is non-nil."
+  (when (get-text-property (point) 'mouse-face)
+    (goto-char (or (next-single-property-change (point) 'mouse-face)
+                   (point-max)))))
+
+(defun completions--after-change (_start _end _old-len)
+  "Update displayed *Completions* buffer after change in buffer contents."
+  (when completion-auto-deselect
+    (when-let (window (get-buffer-window "*Completions*" 0))
+      (with-selected-window window
+        (completions--deselect)))))
+
 (defun minibuffer-completion-help (&optional start end)
   "Display a list of possible completions of the current minibuffer contents."
   (interactive)
@@ -2400,6 +2430,7 @@ minibuffer-completion-help
           ;; If there are no completions, or if the current input is already
           ;; the sole completion, then hide (previous&stale) completions.
           (minibuffer-hide-completions)
+          (remove-hook 'after-change-functions #'completions--after-change t)
           (if completions
               (completion--message "Sole completion")
             (unless completion-fail-discreetly
@@ -2460,6 +2491,8 @@ minibuffer-completion-help
             (body-function
              . ,#'(lambda (_window)
                     (with-current-buffer mainbuf
+                      (when completion-auto-deselect
+                        (add-hook 'after-change-functions #'completions--after-change t))
                       ;; Remove the base-size tail because `sort' requires a properly
                       ;; nil-terminated list.
                       (when last (setcdr last nil))
@@ -4673,7 +4706,8 @@ minibuffer-next-completion
           (next-line-completion (or n 1))
         (next-completion (or n 1)))
       (when auto-choose
-        (let ((completion-use-base-affixes t))
+        (let ((completion-use-base-affixes t)
+              (completion-auto-deselect nil))
           (choose-completion nil t t))))))
 
 (defun minibuffer-previous-completion (&optional n)
@@ -4721,7 +4755,8 @@ minibuffer-choose-completion-or-exit
 contents."
   (interactive "P")
   (condition-case nil
-      (minibuffer-choose-completion no-exit no-quit)
+      (let ((choose-completion-deselect-if-after t))
+        (minibuffer-choose-completion no-exit no-quit))
     (error (minibuffer-complete-and-exit))))
 
 (defun minibuffer-complete-history ()
diff --git a/lisp/simple.el b/lisp/simple.el
index 02c68912dba..bf57b285fca 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10094,6 +10094,11 @@ next-line-completion
           (if pos (goto-char pos))))
       (setq n (1+ n)))))
 
+(defvar choose-completion-deselect-if-after nil
+  "If non-nil, don't choose a completion candidate if point is right after it.
+
+This makes `completions--deselect' effective.")
+
 (defun choose-completion (&optional event no-exit no-quit)
   "Choose the completion at point.
 If EVENT, use EVENT's position to determine the starting position.
@@ -10114,6 +10119,10 @@ choose-completion
           (insert-function completion-list-insert-choice-function)
           (completion-no-auto-exit (if no-exit t completion-no-auto-exit))
           (choice
+           (if choose-completion-deselect-if-after
+               (if-let ((str (get-text-property (posn-point (event-start event)) 'completion--string)))
+                   (substring-no-properties str)
+                 (error "No completion here"))
            (save-excursion
              (goto-char (posn-point (event-start event)))
              (let (beg)
@@ -10129,7 +10138,7 @@ choose-completion
                               beg 'completion--string)
                              beg))
                (substring-no-properties
-                (get-text-property beg 'completion--string))))))
+                (get-text-property beg 'completion--string)))))))
 
       (unless (buffer-live-p buffer)
         (error "Destination buffer is dead"))
-- 
2.42.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-26 14:33                                             ` Spencer Baugh
@ 2023-11-27  7:22                                               ` Juri Linkov
  2023-11-28 14:48                                                 ` Spencer Baugh
  0 siblings, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-11-27  7:22 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: emacs-devel

>> A possible workaround would be to check the special property
>> 'first-completion'.  But then when the logic uses text properties,
>> why not to use more text properties that indicate that a candidate
>> is deselected (and remove highlighting in this case) instead of
>> moving point somewhere outside of the candidate?
>
> Even if we work around this with text properties, I think it's nice for
> deselection to be usually determined by location of point.  I think
> that's easier to understand for the user - they should be able to
> deselect or reselect something purely by moving point around, it
> shouldn't require text property manipulation.

I agree that it's better to indicate deselection by moving point.

After more testing I found a small problem:

  M-x calc TAB TAB

When the selected candidate is

  calc-dispatch (C-x *)

then point is moved before the suffix "(C-x *)",
and after editing it is selected on RET.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-27  7:22                                               ` Juri Linkov
@ 2023-11-28 14:48                                                 ` Spencer Baugh
  2023-11-28 17:23                                                   ` Juri Linkov
  0 siblings, 1 reply; 62+ messages in thread
From: Spencer Baugh @ 2023-11-28 14:48 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1119 bytes --]

Juri Linkov <juri@linkov.net> writes:
>>> A possible workaround would be to check the special property
>>> 'first-completion'.  But then when the logic uses text properties,
>>> why not to use more text properties that indicate that a candidate
>>> is deselected (and remove highlighting in this case) instead of
>>> moving point somewhere outside of the candidate?
>>
>> Even if we work around this with text properties, I think it's nice for
>> deselection to be usually determined by location of point.  I think
>> that's easier to understand for the user - they should be able to
>> deselect or reselect something purely by moving point around, it
>> shouldn't require text property manipulation.
>
> I agree that it's better to indicate deselection by moving point.
>
> After more testing I found a small problem:
>
>   M-x calc TAB TAB
>
> When the selected candidate is
>
>   calc-dispatch (C-x *)
>
> then point is moved before the suffix "(C-x *)",
> and after editing it is selected on RET.

Ah, good catch.  Fixed (by using 'completion--string to detect whether
point is on a completion rather 'mouse-face)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Deselect-the-selected-completion-candidate-when-typi.patch --]
[-- Type: text/x-patch, Size: 7149 bytes --]

From 9321015b4000ee1d26788a6b5b2d38d6c248c5d4 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh@catern.com>
Date: Thu, 23 Nov 2023 13:37:29 +0000
Subject: [PATCH] Deselect the selected completion candidate when typing

minibuffer-choose-completion-or-exit submits the selected completion
candidate, if any, ignoring the contents of the minibuffer.  But a
user might select a completion candidate and then want to type
something else in the minibuffer and submit what they typed.

Now typing will automatically deselect the selected completion
candidate so that minibuffer-choose-completion-or-exit will not choose
it.

minibuffer-choose-completion has the same behavior as before, and is
not affected by the deselection.

* lisp/minibuffer.el (completion-auto-deselect, completions--deselect)
(completions--after-change): Add.
(minibuffer-completion-help): Add completions--after-change hook.
(minibuffer-next-completion): Bind completion-auto-deselect to nil to
avoid immediately deselecting the completion.
(minibuffer-choose-completion-or-exit): Bind
choose-completion-deselect-if-after so deselection takes effect.
(display-completion-list): Guarantee a newline at the beginning of
*Completions* to avoid ambiguity about candidate selection.
* lisp/simple.el (choose-completion-deselect-if-after): Add.
(choose-completion): Check choose-completion-deselect-if-after.
---
 lisp/minibuffer.el | 43 +++++++++++++++++++++++++++++++++++++++----
 lisp/simple.el     | 11 ++++++++++-
 2 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 5c12d9fc914..382d4458e26 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2310,8 +2310,11 @@ display-completion-list
 
     (with-current-buffer standard-output
       (goto-char (point-max))
-      (when completions-header-format
-        (insert (format completions-header-format (length completions))))
+      (if completions-header-format
+          (insert (format completions-header-format (length completions)))
+        (unless completion-show-help
+          ;; Ensure beginning-of-buffer isn't a completion.
+          (insert (propertize "\n" 'face '(:height 0)))))
       (completion--insert-strings completions group-fun)))
 
   (run-hooks 'completion-setup-hook)
@@ -2378,6 +2381,33 @@ completions--fit-window-to-buffer
         (resize-temp-buffer-window win))
     (fit-window-to-buffer win completions-max-height)))
 
+(defcustom completion-auto-deselect t
+  "If non-nil, deselect the selected completion candidate when you type.
+
+A non-nil value means that after typing, point in *Completions*
+will be moved off any completion candidates.  This means
+`minibuffer-choose-completion-or-exit' will exit with the
+minibuffer's current contents, instead of a completion candidate."
+  :type '(choice (const :tag "Candidates in *Completions* stay selected as you type" nil)
+                 (const :tag "Typing deselects any completion candidate in *Completions*" t))
+  :version "30.1")
+
+(defun completions--deselect ()
+  "If point is in a completion candidate, move to just after the end of it.
+
+The candidate will still be chosen by `choose-completion' unless
+`choose-completion-deselect-if-after' is non-nil."
+  (when (get-text-property (point) 'completion--string)
+    (goto-char (or (next-single-property-change (point) 'completion--string)
+                   (point-max)))))
+
+(defun completions--after-change (_start _end _old-len)
+  "Update displayed *Completions* buffer after change in buffer contents."
+  (when completion-auto-deselect
+    (when-let (window (get-buffer-window "*Completions*" 0))
+      (with-selected-window window
+        (completions--deselect)))))
+
 (defun minibuffer-completion-help (&optional start end)
   "Display a list of possible completions of the current minibuffer contents."
   (interactive)
@@ -2400,6 +2430,7 @@ minibuffer-completion-help
           ;; If there are no completions, or if the current input is already
           ;; the sole completion, then hide (previous&stale) completions.
           (minibuffer-hide-completions)
+          (remove-hook 'after-change-functions #'completions--after-change t)
           (if completions
               (completion--message "Sole completion")
             (unless completion-fail-discreetly
@@ -2460,6 +2491,8 @@ minibuffer-completion-help
             (body-function
              . ,#'(lambda (_window)
                     (with-current-buffer mainbuf
+                      (when completion-auto-deselect
+                        (add-hook 'after-change-functions #'completions--after-change t))
                       ;; Remove the base-size tail because `sort' requires a properly
                       ;; nil-terminated list.
                       (when last (setcdr last nil))
@@ -4673,7 +4706,8 @@ minibuffer-next-completion
           (next-line-completion (or n 1))
         (next-completion (or n 1)))
       (when auto-choose
-        (let ((completion-use-base-affixes t))
+        (let ((completion-use-base-affixes t)
+              (completion-auto-deselect nil))
           (choose-completion nil t t))))))
 
 (defun minibuffer-previous-completion (&optional n)
@@ -4721,7 +4755,8 @@ minibuffer-choose-completion-or-exit
 contents."
   (interactive "P")
   (condition-case nil
-      (minibuffer-choose-completion no-exit no-quit)
+      (let ((choose-completion-deselect-if-after t))
+        (minibuffer-choose-completion no-exit no-quit))
     (error (minibuffer-complete-and-exit))))
 
 (defun minibuffer-complete-history ()
diff --git a/lisp/simple.el b/lisp/simple.el
index 02c68912dba..bf57b285fca 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10094,6 +10094,11 @@ next-line-completion
           (if pos (goto-char pos))))
       (setq n (1+ n)))))
 
+(defvar choose-completion-deselect-if-after nil
+  "If non-nil, don't choose a completion candidate if point is right after it.
+
+This makes `completions--deselect' effective.")
+
 (defun choose-completion (&optional event no-exit no-quit)
   "Choose the completion at point.
 If EVENT, use EVENT's position to determine the starting position.
@@ -10114,6 +10119,10 @@ choose-completion
           (insert-function completion-list-insert-choice-function)
           (completion-no-auto-exit (if no-exit t completion-no-auto-exit))
           (choice
+           (if choose-completion-deselect-if-after
+               (if-let ((str (get-text-property (posn-point (event-start event)) 'completion--string)))
+                   (substring-no-properties str)
+                 (error "No completion here"))
            (save-excursion
              (goto-char (posn-point (event-start event)))
              (let (beg)
@@ -10129,7 +10138,7 @@ choose-completion
                               beg 'completion--string)
                              beg))
                (substring-no-properties
-                (get-text-property beg 'completion--string))))))
+                (get-text-property beg 'completion--string)))))))
 
       (unless (buffer-live-p buffer)
         (error "Destination buffer is dead"))
-- 
2.42.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-28 14:48                                                 ` Spencer Baugh
@ 2023-11-28 17:23                                                   ` Juri Linkov
  2023-11-29  0:20                                                     ` Spencer Baugh
  0 siblings, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-11-28 17:23 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: emacs-devel

>> then point is moved before the suffix "(C-x *)",
>> and after editing it is selected on RET.
>
> Ah, good catch.  Fixed (by using 'completion--string to detect whether
> point is on a completion rather 'mouse-face)

Thank, now this works nicely.
Maybe this deserves a NEWS entry as well?



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-28 17:23                                                   ` Juri Linkov
@ 2023-11-29  0:20                                                     ` Spencer Baugh
  2023-12-03 17:21                                                       ` Juri Linkov
  0 siblings, 1 reply; 62+ messages in thread
From: Spencer Baugh @ 2023-11-29  0:20 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 349 bytes --]

Juri Linkov <juri@linkov.net> writes:

>>> then point is moved before the suffix "(C-x *)",
>>> and after editing it is selected on RET.
>>
>> Ah, good catch.  Fixed (by using 'completion--string to detect whether
>> point is on a completion rather 'mouse-face)
>
> Thank, now this works nicely.
> Maybe this deserves a NEWS entry as well?

Added.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Deselect-the-selected-completion-candidate-when-typi.patch --]
[-- Type: text/x-patch, Size: 8062 bytes --]

From e92d36a643df166406a8f4d9ca321213c6bb0704 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh@catern.com>
Date: Thu, 23 Nov 2023 13:37:29 +0000
Subject: [PATCH] Deselect the selected completion candidate when typing

minibuffer-choose-completion-or-exit submits the selected completion
candidate, if any, ignoring the contents of the minibuffer.  But a
user might select a completion candidate and then want to type
something else in the minibuffer and submit what they typed.

Now typing will automatically deselect the selected completion
candidate so that minibuffer-choose-completion-or-exit will not choose
it.

minibuffer-choose-completion has the same behavior as before, and is
not affected by the deselection.

* lisp/minibuffer.el (completion-auto-deselect, completions--deselect)
(completions--after-change): Add.
(minibuffer-completion-help): Add completions--after-change hook.
(minibuffer-next-completion): Bind completion-auto-deselect to nil to
avoid immediately deselecting the completion.
(minibuffer-choose-completion-or-exit): Bind
choose-completion-deselect-if-after so deselection takes effect.
(display-completion-list): Guarantee a newline at the beginning of
*Completions* to avoid ambiguity about candidate selection.
* lisp/simple.el (choose-completion-deselect-if-after): Add.
(choose-completion): Check choose-completion-deselect-if-after.
* etc/NEWS: Announce.
---
 etc/NEWS           |  9 +++++++++
 lisp/minibuffer.el | 43 +++++++++++++++++++++++++++++++++++++++----
 lisp/simple.el     | 11 ++++++++++-
 3 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 6661ac70e1b..b785b91cb4b 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -626,6 +626,15 @@ completions window.  When the completions window is not visible,
 then all these keys have their usual meaning in the minibuffer.
 This option is supported for in-buffer completion as well.
 
+*** Selected completion candidates are deselected on typing.
+When a user types, point in the *Completions* window will be moved off
+any completion candidates.  'minibuffer-choose-completion' ('M-RET')
+will still choose a previously-selected completion candidate, but the
+new command 'minibuffer-choose-completion-or-exit' (bound by
+'minibuffer-visible-completions') will exit with the minibuffer
+contents instead.  The deselection behavior can be controlled with the
+new user option 'completion-auto-deselect'.
+
 ** Pcomplete
 
 ---
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 5c12d9fc914..382d4458e26 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2310,8 +2310,11 @@ display-completion-list
 
     (with-current-buffer standard-output
       (goto-char (point-max))
-      (when completions-header-format
-        (insert (format completions-header-format (length completions))))
+      (if completions-header-format
+          (insert (format completions-header-format (length completions)))
+        (unless completion-show-help
+          ;; Ensure beginning-of-buffer isn't a completion.
+          (insert (propertize "\n" 'face '(:height 0)))))
       (completion--insert-strings completions group-fun)))
 
   (run-hooks 'completion-setup-hook)
@@ -2378,6 +2381,33 @@ completions--fit-window-to-buffer
         (resize-temp-buffer-window win))
     (fit-window-to-buffer win completions-max-height)))
 
+(defcustom completion-auto-deselect t
+  "If non-nil, deselect the selected completion candidate when you type.
+
+A non-nil value means that after typing, point in *Completions*
+will be moved off any completion candidates.  This means
+`minibuffer-choose-completion-or-exit' will exit with the
+minibuffer's current contents, instead of a completion candidate."
+  :type '(choice (const :tag "Candidates in *Completions* stay selected as you type" nil)
+                 (const :tag "Typing deselects any completion candidate in *Completions*" t))
+  :version "30.1")
+
+(defun completions--deselect ()
+  "If point is in a completion candidate, move to just after the end of it.
+
+The candidate will still be chosen by `choose-completion' unless
+`choose-completion-deselect-if-after' is non-nil."
+  (when (get-text-property (point) 'completion--string)
+    (goto-char (or (next-single-property-change (point) 'completion--string)
+                   (point-max)))))
+
+(defun completions--after-change (_start _end _old-len)
+  "Update displayed *Completions* buffer after change in buffer contents."
+  (when completion-auto-deselect
+    (when-let (window (get-buffer-window "*Completions*" 0))
+      (with-selected-window window
+        (completions--deselect)))))
+
 (defun minibuffer-completion-help (&optional start end)
   "Display a list of possible completions of the current minibuffer contents."
   (interactive)
@@ -2400,6 +2430,7 @@ minibuffer-completion-help
           ;; If there are no completions, or if the current input is already
           ;; the sole completion, then hide (previous&stale) completions.
           (minibuffer-hide-completions)
+          (remove-hook 'after-change-functions #'completions--after-change t)
           (if completions
               (completion--message "Sole completion")
             (unless completion-fail-discreetly
@@ -2460,6 +2491,8 @@ minibuffer-completion-help
             (body-function
              . ,#'(lambda (_window)
                     (with-current-buffer mainbuf
+                      (when completion-auto-deselect
+                        (add-hook 'after-change-functions #'completions--after-change t))
                       ;; Remove the base-size tail because `sort' requires a properly
                       ;; nil-terminated list.
                       (when last (setcdr last nil))
@@ -4673,7 +4706,8 @@ minibuffer-next-completion
           (next-line-completion (or n 1))
         (next-completion (or n 1)))
       (when auto-choose
-        (let ((completion-use-base-affixes t))
+        (let ((completion-use-base-affixes t)
+              (completion-auto-deselect nil))
           (choose-completion nil t t))))))
 
 (defun minibuffer-previous-completion (&optional n)
@@ -4721,7 +4755,8 @@ minibuffer-choose-completion-or-exit
 contents."
   (interactive "P")
   (condition-case nil
-      (minibuffer-choose-completion no-exit no-quit)
+      (let ((choose-completion-deselect-if-after t))
+        (minibuffer-choose-completion no-exit no-quit))
     (error (minibuffer-complete-and-exit))))
 
 (defun minibuffer-complete-history ()
diff --git a/lisp/simple.el b/lisp/simple.el
index 35bce6ab4b8..67d04032e64 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10092,6 +10092,11 @@ next-line-completion
           (if pos (goto-char pos))))
       (setq n (1+ n)))))
 
+(defvar choose-completion-deselect-if-after nil
+  "If non-nil, don't choose a completion candidate if point is right after it.
+
+This makes `completions--deselect' effective.")
+
 (defun choose-completion (&optional event no-exit no-quit)
   "Choose the completion at point.
 If EVENT, use EVENT's position to determine the starting position.
@@ -10112,6 +10117,10 @@ choose-completion
           (insert-function completion-list-insert-choice-function)
           (completion-no-auto-exit (if no-exit t completion-no-auto-exit))
           (choice
+           (if choose-completion-deselect-if-after
+               (if-let ((str (get-text-property (posn-point (event-start event)) 'completion--string)))
+                   (substring-no-properties str)
+                 (error "No completion here"))
            (save-excursion
              (goto-char (posn-point (event-start event)))
              (let (beg)
@@ -10127,7 +10136,7 @@ choose-completion
                               beg 'completion--string)
                              beg))
                (substring-no-properties
-                (get-text-property beg 'completion--string))))))
+                (get-text-property beg 'completion--string)))))))
 
       (unless (buffer-live-p buffer)
         (error "Destination buffer is dead"))
-- 
2.42.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-11-29  0:20                                                     ` Spencer Baugh
@ 2023-12-03 17:21                                                       ` Juri Linkov
  2023-12-03 18:13                                                         ` Eli Zaretskii
  0 siblings, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-12-03 17:21 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: emacs-devel

>>>> then point is moved before the suffix "(C-x *)",
>>>> and after editing it is selected on RET.
>>>
>>> Ah, good catch.  Fixed (by using 'completion--string to detect whether
>>> point is on a completion rather 'mouse-face)
>>
>> Thank, now this works nicely.
>> Maybe this deserves a NEWS entry as well?
>
> Added.

Thanks, with no more comments in three days, this is pushed now.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-12-03 17:21                                                       ` Juri Linkov
@ 2023-12-03 18:13                                                         ` Eli Zaretskii
  2023-12-06 17:20                                                           ` Juri Linkov
  0 siblings, 1 reply; 62+ messages in thread
From: Eli Zaretskii @ 2023-12-03 18:13 UTC (permalink / raw)
  To: Juri Linkov; +Cc: sbaugh, emacs-devel

> From: Juri Linkov <juri@linkov.net>
> Cc: emacs-devel@gnu.org
> Date: Sun, 03 Dec 2023 19:21:29 +0200
> 
> >>>> then point is moved before the suffix "(C-x *)",
> >>>> and after editing it is selected on RET.
> >>>
> >>> Ah, good catch.  Fixed (by using 'completion--string to detect whether
> >>> point is on a completion rather 'mouse-face)
> >>
> >> Thank, now this works nicely.
> >> Maybe this deserves a NEWS entry as well?
> >
> > Added.
> 
> Thanks, with no more comments in three days, this is pushed now.

I don't understand the NEWS entry:

  *** Selected completion candidates are deselected on typing.
  When a user types, point in the *Completions* window will be moved off
  any completion candidates.  'minibuffer-choose-completion' ('M-RET')
  will still choose a previously-selected completion candidate, but the
  new command 'minibuffer-choose-completion-or-exit' (bound by
  'minibuffer-visible-completions') will exit with the minibuffer
  contents instead.  The deselection behavior can be controlled with the
  new user option 'completion-auto-deselect'.

What are "selected completion candidates"?  I typed "C-x C-f TAB", and
Emacs popped the completions buffer, but without "selecting" any of
the candidates.  Searching for "select" in the buffer produced by
"M-x apropos complet RET" doesn't seem to find anything pertinent.
And there's nothing about this in the manual.  What am I missing?



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-12-03 18:13                                                         ` Eli Zaretskii
@ 2023-12-06 17:20                                                           ` Juri Linkov
  2023-12-06 17:50                                                             ` Eli Zaretskii
  0 siblings, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-12-06 17:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: sbaugh, emacs-devel

> I don't understand the NEWS entry:
>
>   *** Selected completion candidates are deselected on typing.
>   When a user types, point in the *Completions* window will be moved off
>   any completion candidates.  'minibuffer-choose-completion' ('M-RET')
>   will still choose a previously-selected completion candidate, but the
>   new command 'minibuffer-choose-completion-or-exit' (bound by
>   'minibuffer-visible-completions') will exit with the minibuffer
>   contents instead.  The deselection behavior can be controlled with the
>   new user option 'completion-auto-deselect'.
>
> What are "selected completion candidates"?  I typed "C-x C-f TAB", and
> Emacs popped the completions buffer, but without "selecting" any of
> the candidates.  Searching for "select" in the buffer produced by
> "M-x apropos complet RET" doesn't seem to find anything pertinent.
> And there's nothing about this in the manual.  What am I missing?

Maybe a better term would be "a highlighted completion candidate"?
This should denote a candidate where point is located in the
*Completions* buffer.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-12-06 17:20                                                           ` Juri Linkov
@ 2023-12-06 17:50                                                             ` Eli Zaretskii
  2023-12-07  7:44                                                               ` Juri Linkov
  0 siblings, 1 reply; 62+ messages in thread
From: Eli Zaretskii @ 2023-12-06 17:50 UTC (permalink / raw)
  To: Juri Linkov; +Cc: sbaugh, emacs-devel

> From: Juri Linkov <juri@linkov.net>
> Cc: sbaugh@catern.com,  emacs-devel@gnu.org
> Date: Wed, 06 Dec 2023 19:20:40 +0200
> 
> > I don't understand the NEWS entry:
> >
> >   *** Selected completion candidates are deselected on typing.
> >   When a user types, point in the *Completions* window will be moved off
> >   any completion candidates.  'minibuffer-choose-completion' ('M-RET')
> >   will still choose a previously-selected completion candidate, but the
> >   new command 'minibuffer-choose-completion-or-exit' (bound by
> >   'minibuffer-visible-completions') will exit with the minibuffer
> >   contents instead.  The deselection behavior can be controlled with the
> >   new user option 'completion-auto-deselect'.
> >
> > What are "selected completion candidates"?  I typed "C-x C-f TAB", and
> > Emacs popped the completions buffer, but without "selecting" any of
> > the candidates.  Searching for "select" in the buffer produced by
> > "M-x apropos complet RET" doesn't seem to find anything pertinent.
> > And there's nothing about this in the manual.  What am I missing?
> 
> Maybe a better term would be "a highlighted completion candidate"?
> This should denote a candidate where point is located in the
> *Completions* buffer.

Thanks, but I still don't think I follow.  How do I get this situation
where a completion candidate is "highlighted" or "selected", starting
from typing a command like "C-x C-f" and then typing TAB?



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-12-06 17:50                                                             ` Eli Zaretskii
@ 2023-12-07  7:44                                                               ` Juri Linkov
  2023-12-08  8:46                                                                 ` Eli Zaretskii
  0 siblings, 1 reply; 62+ messages in thread
From: Juri Linkov @ 2023-12-07  7:44 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: sbaugh, emacs-devel

>> >   *** Selected completion candidates are deselected on typing.
>> >   When a user types, point in the *Completions* window will be moved off
>> >   any completion candidates.  'minibuffer-choose-completion' ('M-RET')
>> >   will still choose a previously-selected completion candidate, but the
>> >   new command 'minibuffer-choose-completion-or-exit' (bound by
>> >   'minibuffer-visible-completions') will exit with the minibuffer
>> >   contents instead.  The deselection behavior can be controlled with the
>> >   new user option 'completion-auto-deselect'.
>> >
>> > What are "selected completion candidates"?  I typed "C-x C-f TAB", and
>> > Emacs popped the completions buffer, but without "selecting" any of
>> > the candidates.  Searching for "select" in the buffer produced by
>> > "M-x apropos complet RET" doesn't seem to find anything pertinent.
>> > And there's nothing about this in the manual.  What am I missing?
>>
>> Maybe a better term would be "a highlighted completion candidate"?
>> This should denote a candidate where point is located in the
>> *Completions* buffer.
>
> Thanks, but I still don't think I follow.  How do I get this situation
> where a completion candidate is "highlighted" or "selected", starting
> from typing a command like "C-x C-f" and then typing TAB?

C-x C-f TAB TAB M-<down>

Then e.g. DEL (<backspace>) will "deselect" the highlighted candidate.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: Navigating completions from minibuffer
  2023-12-07  7:44                                                               ` Juri Linkov
@ 2023-12-08  8:46                                                                 ` Eli Zaretskii
  0 siblings, 0 replies; 62+ messages in thread
From: Eli Zaretskii @ 2023-12-08  8:46 UTC (permalink / raw)
  To: Juri Linkov; +Cc: sbaugh, emacs-devel

> From: Juri Linkov <juri@linkov.net>
> Cc: sbaugh@catern.com,  emacs-devel@gnu.org
> Date: Thu, 07 Dec 2023 09:44:45 +0200
> 
> >> >   *** Selected completion candidates are deselected on typing.
> >> >   When a user types, point in the *Completions* window will be moved off
> >> >   any completion candidates.  'minibuffer-choose-completion' ('M-RET')
> >> >   will still choose a previously-selected completion candidate, but the
> >> >   new command 'minibuffer-choose-completion-or-exit' (bound by
> >> >   'minibuffer-visible-completions') will exit with the minibuffer
> >> >   contents instead.  The deselection behavior can be controlled with the
> >> >   new user option 'completion-auto-deselect'.
> >> >
> >> > What are "selected completion candidates"?  I typed "C-x C-f TAB", and
> >> > Emacs popped the completions buffer, but without "selecting" any of
> >> > the candidates.  Searching for "select" in the buffer produced by
> >> > "M-x apropos complet RET" doesn't seem to find anything pertinent.
> >> > And there's nothing about this in the manual.  What am I missing?
> >>
> >> Maybe a better term would be "a highlighted completion candidate"?
> >> This should denote a candidate where point is located in the
> >> *Completions* buffer.
> >
> > Thanks, but I still don't think I follow.  How do I get this situation
> > where a completion candidate is "highlighted" or "selected", starting
> > from typing a command like "C-x C-f" and then typing TAB?
> 
> C-x C-f TAB TAB M-<down>
> 
> Then e.g. DEL (<backspace>) will "deselect" the highlighted candidate.

Thanks, I tried to improve the documentation using the above
information.

Btw, I notice (with some sadness) that we are largely back to our
previous practice of not updating the manuals with information about
changes.  This has two adverse consequences:

  . the release cycle of the next major release will take longer
  . the manuals included in the next major release are more likely to
    be inaccurate and/or incomplete

People who complain about too slow release schedule of Emacs should
take note, and hopefully invest more effort in the future in updating
the documentation together with code changes.



^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2023-12-08  8:46 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-07  3:57 Navigating completions from minibuffer T.V Raman
2023-11-07  4:55 ` T.V Raman
2023-11-07  7:20   ` Juri Linkov
2023-11-07 17:53     ` T.V Raman
2023-11-07 19:36       ` T.V Raman
2023-11-08  7:39         ` Juri Linkov
2023-11-08 16:21           ` T.V Raman
2023-11-08 17:18             ` T.V Raman
2023-11-08 22:11               ` Slow completion-at-point was " T.V Raman
2023-11-09  7:22                 ` Slow completion-at-point Juri Linkov
2023-11-09 12:10                   ` Dmitry Gutov
2023-11-09 16:20                     ` Juri Linkov
2023-11-09 18:32                       ` João Távora
2023-11-11  2:48                     ` T.V Raman
2023-11-11 10:36                       ` Dmitry Gutov
2023-11-11 16:40                         ` T.V Raman
2023-11-11 19:00                           ` Juri Linkov
2023-11-11 19:43                             ` T.V Raman
2023-11-11 21:50                               ` Dmitry Gutov
2023-11-09 15:39                   ` T.V Raman
2023-11-09 12:20                 ` Slow completion-at-point was Re: Navigating completions from minibuffer Dmitry Gutov
2023-11-09 15:41                   ` T.V Raman
2023-11-09 17:46                 ` T.V Raman
2023-11-10 13:12           ` Spencer Baugh
2023-11-11 18:58             ` Juri Linkov
2023-11-14  7:36               ` Juri Linkov
2023-11-15 21:40                 ` Spencer Baugh
2023-11-16 17:15                   ` T.V Raman
2023-11-15 22:03                 ` Spencer Baugh
2023-11-16  7:16                   ` Juri Linkov
2023-11-16 14:41                     ` Spencer Baugh
2023-11-16 17:28                       ` Juri Linkov
2023-11-16 18:25                         ` Spencer Baugh
2023-11-17  7:09                           ` Juri Linkov
2023-11-17 17:22                             ` Spencer Baugh
2023-11-18 20:58                               ` sbaugh
2023-11-19  7:08                                 ` Juri Linkov
2023-11-19  8:19                                   ` Eli Zaretskii
2023-11-19 14:41                                   ` Spencer Baugh
2023-11-19 18:01                                     ` Juri Linkov
2023-11-19 19:41                                       ` Spencer Baugh
2023-11-20  2:58                                       ` Spencer Baugh
2023-11-23 13:39                                     ` sbaugh
2023-11-24  7:54                                       ` Juri Linkov
2023-11-25 15:19                                         ` Spencer Baugh
2023-11-25 16:08                                           ` Eli Zaretskii
2023-11-25 18:23                                             ` sbaugh
2023-11-25 18:48                                               ` Juri Linkov
2023-11-26 13:10                                                 ` sbaugh
2023-11-25 19:00                                               ` Eli Zaretskii
2023-11-25 17:46                                           ` Juri Linkov
2023-11-26 14:33                                             ` Spencer Baugh
2023-11-27  7:22                                               ` Juri Linkov
2023-11-28 14:48                                                 ` Spencer Baugh
2023-11-28 17:23                                                   ` Juri Linkov
2023-11-29  0:20                                                     ` Spencer Baugh
2023-12-03 17:21                                                       ` Juri Linkov
2023-12-03 18:13                                                         ` Eli Zaretskii
2023-12-06 17:20                                                           ` Juri Linkov
2023-12-06 17:50                                                             ` Eli Zaretskii
2023-12-07  7:44                                                               ` Juri Linkov
2023-12-08  8:46                                                                 ` Eli Zaretskii

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).