unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Stefan Monnier <monnier@iro.umontreal.ca>
To: Daniel Mendler <mail@daniel-mendler.de>
Cc: emacs-devel@gnu.org
Subject: Re: Improvement proposals for `completing-read'
Date: Wed, 07 Apr 2021 13:20:30 -0400	[thread overview]
Message-ID: <jwvim4y813t.fsf-monnier+emacs@gnu.org> (raw)
In-Reply-To: <jwvo8eq83zq.fsf-monnier+emacs@gnu.org> (Stefan Monnier's message of "Wed, 07 Apr 2021 13:11:39 -0400")

BTW, rereading the below, I see I'm sounding a bit too authoritative.
I'm the original author of the minibuffer.el completion code, but
remember that what I wrote is just my opinion: you'll want to
convince the actual maintainers for some of those changes ;-)


        Stefan


Stefan Monnier [2021-04-07 13:11:39] wrote:

>>       It might deserve a completely new function to replace
>>       `completing-read', but I think it would be good to make this
>>       new function such that it makes `completing-read' obsolete.
>>
>> The cost of introduction of a new function is not to be underestimated
>> in particular if it sits at a central place. Introducing another
>> function which only differs slightly from the existing `completing-read'
>> function could do more harm than good if it increases inconsistency and
>
> All I meant is that the design could start from a clean slate, and
> afterwards look at the result and see whether/how it can be retrofitted
> into `completing-read`.
>
>> Proposal 1: Disabling the history
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>>   I propose to allow the symbol `t' as `HIST' argument to
>>   `completing-read' in order to disable the history. This aligns
>>   `completing-read' with `read-from-minibuffer'. This change requires a
>>   modification of the function `completion-all-sorted-completions',
>>   which sorts the candidates by history position and currently assumes
>>   that the `minibuffer-history-variable' is a variable symbol.
>>
>>   Example:
>>   ,----
>>   | (completing-read "No History: " '(first second third) nil nil nil t)
>>   `----
>
> [ I'm not sure there's a great benefit here, since in the situation
>   where simplicity is what matters, using nil seems like a much better
>   choice, but: ]
> Good idea.
>
>> Proposal 2: More efficient sorting
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>>   Currently candidate sorting is `O(m*n*log(n))' with history length m
>>   and candidate list length n. This leads to a noticeable slowdown for
>>   large values of `history-length'. I propose to improve the speed of
>>   `completion-all-sorted-completions' by using a hash table. The Vertico
>>   package provides an optimized sorting function, see `vertico--sort'.
>
> You're asking whether we should fix a performance bug, the answer is: yes.
>
>> Proposal 3: Sort file names by history
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>>   Currently `completion-all-sorted-completions' does not sort file
>>   candidates based on history, when the candidates are file names and
>>   the history elements are paths.
>
> I think this is just a bug in that we don't pay attention to boundaries
> when sorting.  It's probably just a matter of prepending the prefix
> removed from the all-completions output when looking for an element in
> the list (the end of this prefix is returned in the last `cdr` of
> `completion-all-completions`).  Similarly, we may want to compare with
> `string-prefix-p` rather than `equal`.
>
>> Proposal 4: Add support for `group-function'
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>>   Completion tables can provide the functions `display-sort-function',
>>   `cycle-sort-function', `annotation-function' and `affixation-function'
>>   as completion metadata. I am proposing the addition of a
>>   `group-function', which receives a list of candidates and returns a
>>   list of groups `((group-title . group-candidates) ...)'. The group
>>   function should retain the present order of the candidates within the
>>   groups.
>
> Sounds fine to me, yes.
>
> [ This touches a delicate issue, of course: since some completion styles
>   have their idea of sorting (e.g. `flex`), some UIs have other ideas,
>   and then some completion tables have yet more ideas.
>
>   I'm not super-happy with all those functions, to be honest, but it's
>   not clear what an API should look like to better decouple the UIs,
>   styles, and backends in this respect, so for now the best is probably
>   to keep piling on stuff until a clearer picture emerges.  ]
>
>>   This function is used in two ways. After sorting the candidates, the
>>   group function is called with the candidate list in order to produce a
>>   grouped list. Then the completion UI can call the group function a
>>   second time when displaying the candidate groups in order to determine
>>   the group titles.
>
> I'd have expected the "list of lists" result to already include the
> group titles.
>
>>   This is useful for example if candidates originate from different
>>   sources. Grouping is popular in Helm, for example as seen in
>>   [helm-m-x].
>
> Of course, it may be difficult for your function to recover the origin
> of a candidate if the same candidate can come from two or more sources.
>
>> Proposal 5: Forbid the null completions for `REQUIRE-MATCH=t'
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>>   If `completing-read' is passed `t' as argument to `REQUIRE-MATCH', the
>>   completion must match a candidate from the completion table. However
>>   there is also the possibility to exit the minibuffer with a null
>>   completion. I propose to disallow this possibility. This change makes
>>   it easier for users of `completing-read' since they can rely on
>>   setting `REQUIRE-MATCH' to `t' and do not have to handle the null
>>   completion specially.
> [...]
>>   If it is desired to avoid a backward incompatible change one could
>>   consider adding a new special value for `REQUIRE-MATCH', for example
>>   `'require-candidate', which explicitly forbids null completion.
>
> I generally like the idea (I've also been bothered by this possibility
> to return an empty string), but I haven't looked into fixing the
> problem.  There's already an obvious way to tell `completing-read`
> whether the null string is acceptable (by making the completion-table's
> `test-completion` return non-nil for it), so maybe we don't need
> a special new value.  But I don't have a good sense of the scale of the
> potential compatibility breakage [I suspect that such a change might
> also fix some code which doesn't bother to check for an empty output. ]
> IOW, this deserves a bit for `grep`ping through all the ELisp code you
> can get your hands on and try to see how/if it would be affected by such
> a change.
>
> As you say, in the worst case we can introduce a new value for
> REQUIRE-MATCH, so as to be backward-compatibility-safe.  But I'd be
> interested to see if there are cases where the current empty-string
> "(mis)feature" is actually beneficial.
>
>> Proposal 6: Return text properties from `completing-read'
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>>   As of now, `completing-read' strips text properties from the result
>>   string. This behavior is reasonable for strings, which are not present
>>   in the collection if `REQUIRE-MATCH/=t'. However if a candidate string
>>   is selected, which is a member of the collection, the text properties
>>   can be retained. If this is implemented and `REQUIRE-MATCH=t', the
>>   user of `completing-read' can always rely on text properties to attach
>>   arbitrary data to the candidates.
>
> I think what you mean is that the text properties should be stripped
> from the text taken from the minibuffer, but should be preserved from
> the text taken from the completion tables's candidates (and then
> together with that, you'd want to guarantee that when require-match is
> non-nil the string object returned is actually one of those candidates
> returned by the completion table)?
>
> This is one of the important differences between "completion" and
> "selection" in that completion is about using a completion-table as
> a helper to write a chunk of text (but the resulting text in the end
> should not be affected by how the user used the completion table to
> come up with the final text), whereas selection is about choosing among
> a set of candidates and the result is expected to be `eq` to one of
> the candidates.
>
> I agree that it would be good to move towards making `completing-read`
> better support the "selection" use case.
>
>> Proposal 7: Allow duplicates and retain object identity
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>>   If a completion table contains duplicates, these duplicates should not
>>   be removed. There are not many completion tables which generate
>>   duplicate candidates and there exist multiple completion systems which
>>   do not perform deduplication at all.
>
> [ I've been resisting this for quite some years, as Drew can testify.  ]
>
> While I agree with preserving object identity, the issue of duplicates
> is more problematic, because it means the user can't choose between them
> using self-insert-command + RET.  IOW such completion-tables are
> fundamentally making assumptions about the kind of UI with which they
> can be used.
>
>> Proposal 8: Completion style optimization of filtering and highlighting
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>>   While working on Selectrum and Vertico it has been found that
>>   highlighting has a significant cost. This matters if the number of
>>   displayed candidates differs greatly from the number of filtered
>>   candidates. Therefore it would be good to have a possibility to
>>   separate highlighting and filtering.
>
> Agreed.  It doesn't seem easy to retro fit this into the current API, tho.
> [ The redesign of the completion API which I had started back in 2019
>   (see scratch/completion-api for a very rough sketch of the general
>   direction) also aimed to fix this.  ]
>
>>   In the Orderless completion-style, there is a variable
>>   `orderless-skip-highlighting' which can be set to `t' or to
>>   a predicate function. Depending on the value of this variable
>>   highlighting is applied or not applied by
>>   `completion-all-completions'.
>
> That's not a great solution, but as a temporary patch until we have
> a better API it's OK.
>
>>   In the first step, all the candidates can be computed and filtered
>>   with `orderless-skip-highlighting=t', see
>>   `vertico--recompute-candidates'. Afterwards, when displaying the
>>   candidates, the completion UI has to pass the small subset of
>>   candidates once again through `completion-all-completions', this time
>>   with `orderless-skip-highlighting=nil', see `vertico--highlight'.
>
> I suspect "pass the small subset of candidates once again through
> `completion-all-completions'" can be tricky to do (e.g. for things like
> file-name completion with `partial-completion`).
>
>>   I propose to generalize this Orderless feature by introducing a
>>   variable `completion-skip-highlighting', which behaves the same as
>>   `orderless-skip-highlighting' and is implemented for all built-in
>>   completion styles. In Orderless, the filtering and highlighting is
>>   already separate internally, therefore skipping the highlighting
>>   turned out to be a natural decision in Orderless. The situation could
>>   be different for the built-in styles.
>
> I think in all styles I can think of highlighting is done as a separate step.
>
>>   As an alternative, one can introduce a third function
>>   `completion-highlight-completions', which is specified in
>>   `completion-styles-alist'. But I suspect that the introduction of an
>>   extra function requires more effort.
>
> I'd rather not go there, indeed.
>
>
>         Stefan




  reply	other threads:[~2021-04-07 17:20 UTC|newest]

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-07 11:16 Improvement proposals for `completing-read' Daniel Mendler
2021-04-07 17:11 ` Stefan Monnier
2021-04-07 17:20   ` Stefan Monnier [this message]
2021-04-07 19:46     ` Daniel Mendler
2021-04-07 21:26       ` Stefan Monnier
2021-04-08  9:01         ` Daniel Mendler
2021-04-08 14:44           ` Stefan Monnier
2021-04-08 15:26             ` Stefan Kangas
2021-04-08 15:47               ` Daniel Mendler
2021-04-08 17:31               ` Stefan Monnier
2021-04-08 15:37             ` Daniel Mendler
2021-04-08 17:22               ` [External] : " Drew Adams
2021-04-08 18:22                 ` Dmitry Gutov
2021-04-08 18:48                   ` Drew Adams
2021-04-08 19:03                     ` Dmitry Gutov
2021-04-08 19:32                       ` Drew Adams
2021-04-08 17:30               ` Stefan Monnier
2021-04-08 17:57                 ` Daniel Mendler
2021-04-08 18:13                   ` Stefan Monnier
2021-04-08 19:15                     ` Daniel Mendler
2021-04-08 19:20               ` Dmitry Gutov
2021-04-08 19:46                 ` [External] : " Drew Adams
2021-04-08 20:12                   ` Dmitry Gutov
2021-04-08 21:12                     ` Drew Adams
2021-04-08 22:37                     ` Stefan Kangas
2021-04-09  0:03                       ` Dmitry Gutov
2021-04-09  2:09                         ` Using more and/or better icons in Emacs Stefan Kangas
2021-04-09  3:09                           ` Lars Ingebrigtsen
2021-04-09  3:35                           ` chad
2021-04-09 12:06                             ` Stefan Kangas
2021-04-09  7:41                           ` Yuri Khan
2021-04-09  9:59                             ` tomas
2021-04-09 11:15                               ` Dmitry Gutov
2021-04-09 11:19                           ` Dmitry Gutov
2021-04-09 12:22                             ` Stefan Kangas
2021-04-09 12:29                               ` Dmitry Gutov
2021-04-09 17:46                                 ` Stefan Kangas
2021-04-09 18:45                                   ` Eli Zaretskii
2021-04-09 19:30                                   ` Alan Third
2021-04-09 19:40                                     ` Alan Third
2021-04-09 22:38                                       ` Dmitry Gutov
2021-04-10  0:56                                       ` Stefan Kangas
2021-04-10  1:43                                         ` Stefan Kangas
2021-04-10  9:12                                           ` Alan Third
2021-04-10 10:56                                             ` Stefan Kangas
2021-04-10 13:48                                               ` Alan Third
2021-04-12 19:39                                                 ` Alan Third
2021-04-13  1:25                                                   ` Stefan Kangas
2021-04-13  7:35                                                     ` Alan Third
2021-04-13 10:39                                                       ` Stefan Kangas
2021-04-13 19:50                                                         ` Alan Third
2021-04-13 22:44                                                           ` Stefan Kangas
2021-04-14  6:46                                                           ` Eli Zaretskii
2021-04-15 15:37                                                             ` Alan Third
2021-04-15 15:50                                                               ` Eli Zaretskii
2021-04-15 17:10                                                                 ` Alan Third
2021-04-11 21:57                                       ` Dmitry Gutov
2021-04-09 23:16                                   ` Alan Third
2021-04-10  0:55                                     ` Stefan Kangas
2021-04-10  7:23                                       ` Eli Zaretskii
2021-04-10  9:17                                         ` Alan Third
2021-04-10  9:25                                           ` Eli Zaretskii
2021-04-08 17:22             ` [External] : Re: Improvement proposals for `completing-read' Drew Adams
2021-04-08 18:33               ` Drew Adams
2021-04-07 23:11       ` Drew Adams
2021-04-08  7:56       ` Eli Zaretskii
2021-04-07 18:39 ` Jean Louis
2021-04-07 19:49   ` Daniel Mendler
2021-04-07 22:16 ` Dmitry Gutov
2021-04-08  8:37   ` Daniel Mendler
2021-04-08 20:44     ` Dmitry Gutov
2021-04-08 21:30       ` Daniel Mendler
2021-04-10  2:21         ` Dmitry Gutov
2021-04-10  9:18           ` Daniel Mendler
2021-04-11  0:51             ` Dmitry Gutov
2021-04-11 13:08               ` Daniel Mendler
2021-04-12  0:32                 ` Dmitry Gutov
2021-04-12  0:40                   ` Daniel Mendler
2021-04-12 10:47                     ` Dmitry Gutov
2021-04-12 11:04                       ` Daniel Mendler
2021-04-14  0:00                         ` Dmitry Gutov
2021-04-14 10:44                           ` Daniel Mendler
2021-04-07 23:49 ` [External] : " Drew Adams
2021-04-08  9:29   ` Daniel Mendler
2021-04-08 17:19     ` Drew Adams
2021-04-09 11:19       ` Jean Louis
2021-04-09 11:47         ` Daniel Mendler
2021-04-09 17:22         ` Drew Adams
2021-04-09 17:41           ` Daniel Mendler

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=jwvim4y813t.fsf-monnier+emacs@gnu.org \
    --to=monnier@iro.umontreal.ca \
    --cc=emacs-devel@gnu.org \
    --cc=mail@daniel-mendler.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).