all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
       [not found] ` <20190202232828.4AE452159A@vcs0.savannah.gnu.org>
@ 2019-02-06  3:11   ` Dmitry Gutov
  2019-02-06 10:09     ` João Távora
  2019-02-11 21:10   ` new-flex-completion-style (was: [Emacs-diffs] scratch/ 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness) Stefan Monnier
  1 sibling, 1 reply; 71+ messages in thread
From: Dmitry Gutov @ 2019-02-06  3:11 UTC (permalink / raw)
  To: emacs-devel, João Távora

On 03.02.2019 02:28, Jo�o T�vora wrote:
> +          ;; Sort again in case the completion style has propertized
> +          ;; completions with a 'completion-style-sort-order.
> +          (setq completions
> +                (sort completions
> +                      (lambda (a b)
> +                        (let ((va (get-text-property 0 'completion-style-sort-order a))
> +                              (vb (get-text-property 0 'completion-style-sort-order b)))

Shouldn't we be concerned that this overrides display-sort-function 
returned by the completion table?

Maybe some sort of customizable mechanism is in order, similar to 
completion-styles.

Or more simply, we just leave it to the completion table's author to set 
display-sort-function to a special value that makes use of these 
properties. It's not like setting it to a different value is going to 
make sense in this case.

> +          ;; Annotate completions with <...>
> +          ;; the completion style annotation.

Is this for debugging?



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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-06  3:11   ` [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness Dmitry Gutov
@ 2019-02-06 10:09     ` João Távora
  2019-02-06 18:54       ` Dmitry Gutov
  0 siblings, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-06 10:09 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: emacs-devel

Dmitry Gutov <dgutov@yandex.ru> writes:

> On 03.02.2019 02:28, Jo�o T�vora wrote:
>> +          ;; Sort again in case the completion style has propertized
>> +          ;; completions with a 'completion-style-sort-order.
>> +          (setq completions
>> +                (sort completions
>> +                      (lambda (a b)
>> +                        (let ((va (get-text-property 0 'completion-style-sort-order a))
>> +                              (vb (get-text-property 0 'completion-style-sort-order b)))
>
> Shouldn't we be concerned that this overrides display-sort-function
> returned by the completion table?

Perhaps.  But it only does so when the completion style explicitly
wanted it.  And even so, the sort order should be stable, i.e. if the
completion style puts numerically equal values in two completions, they
should retain the backend's order.  And, obviously, it it doesn't put
any values in that property, then the backend's order is also retained.

In my experience, at least for the "flex" (also called "scatter", by the
way) completion style, the frontend's sorting takes precedence

> Maybe some sort of customizable mechanism is in order, similar to
> completion-styles.

It is already customizable: you don't have to use "flex" completion
style.  Let's first try it out and then see if we need _more_
customization.

> Or more simply, we just leave it to the completion table's author to
> set display-sort-function to a special value that makes use of these
> properties. It's not like setting it to a different value is going to
> make sense in this case.
>
>> +          ;; Annotate completions with <...>
>> +          ;; the completion style annotation.
>
> Is this for debugging?

At the moment, yes mostly.  But it could not be.  In SLY, I give users
an indication of how the scoring algorithm is working.  See it in
action:

https://raw.githubusercontent.com/joaotavora/sly/master/doc/animations/company-flex-completion.gif

João



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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-06 10:09     ` João Távora
@ 2019-02-06 18:54       ` Dmitry Gutov
  2019-02-06 19:47         ` João Távora
  0 siblings, 1 reply; 71+ messages in thread
From: Dmitry Gutov @ 2019-02-06 18:54 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

On 06.02.2019 13:09, João Távora wrote:

> Perhaps.  But it only does so when the completion style explicitly
> wanted it.  And even so, the sort order should be stable, i.e. if the
> completion style puts numerically equal values in two completions, they
> should retain the backend's order.  And, obviously, it it doesn't put
> any values in that property, then the backend's order is also retained.

To put it simply, we already have a way to indicate the completions 
sorting: provide a particular property, or metadata. I'd prefer not to 
couple completion style with sorting, because someone somewhere might 
prefer to go without it (and use some other sorting options, e.g. by 
frequency of use or mentions in the buffer).

> In my experience, at least for the "flex" (also called "scatter", by the
> way) completion style, the frontend's sorting takes precedence

Not sure what you mean by frontend here.

> It is already customizable: you don't have to use "flex" completion
> style.  Let's first try it out and then see if we need _more_
> customization.

I'd rather we start with the "more simply" alternative I've mentioned. 
But others are welcome to add their opinions.

>> Is this for debugging?
> 
> At the moment, yes mostly.  But it could not be.  In SLY, I give users
> an indication of how the scoring algorithm is working.  See it in
> action:
> 
> https://raw.githubusercontent.com/joaotavora/sly/master/doc/animations/company-flex-completion.gif

It's kind of neat, but to be honest I don't see how these percentages 
help a random user.

Even if they do, there's no need to couple this annotation addition to 
the completion style. Just use a new annotation function that looks up 
the text properties that the style adds, and adds them on.



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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-06 18:54       ` Dmitry Gutov
@ 2019-02-06 19:47         ` João Távora
  2019-02-12  0:25           ` Dmitry Gutov
  0 siblings, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-06 19:47 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: emacs-devel

Dmitry Gutov <dgutov@yandex.ru> writes:

> On 06.02.2019 13:09, João Távora wrote:
>
>> Perhaps.  But it only does so when the completion style explicitly
>> wanted it.  And even so, the sort order should be stable, i.e. if the
>> completion style puts numerically equal values in two completions, they
>> should retain the backend's order.  And, obviously, it it doesn't put
>> any values in that property, then the backend's order is also retained.
>
> To put it simply, we already have a way to indicate the completions
> sorting: provide a particular property, or metadata.

Perhaps I'm missing something, and that is taiting all the remaining
discussion.  Aren't these properties/metadata thingies specific to the
completion table (files, buffers, code completions, etc)?

> I'd prefer not to couple completion style with sorting, because
> someone somewhere might prefer to go without it (and use some other
> sorting options, e.g. by frequency of use or mentions in the buffer).




>
>> In my experience, at least for the "flex" (also called "scatter", by the
>> way) completion style, the frontend's sorting takes precedence
>
> Not sure what you mean by frontend here.

I meant the completion style.  Though technically the completion style
is a degree short of a frontend, because it is a way to select the
completions collected by the backend (the completion table in Emacs
parlance) and pass them to the graphical frontend, be it icomplete's,
the *Completions* buffer or company.

In otherwords I should be able to mix and match

- frontends
- completion styles
- backends

Right?  Well all I'm saying is that, when using the flex/scatter
completion style, it's almost always, if not always always, a better
idea to stable-sort by flex-match score.

One good way to see this is to try my code with your company.el package,
which doesn't (hopefully _doesn't yet_) use the completion style's
sorting hints.  You can try it in Emacs Lisp. First do:

   (setq completion-styles '(flex))

Now go into the *scratch* buffer and type "undo". You'll see it's not
very useful: the first match you get is ":argument-precedence-order", a
legitimate match, for sure, but you probably meant something related to
the undo facilities.  And you have to scroll quite a bit before you to
"buffer-undo-list", which is buried deep in the many many b's that
match.

>> It is already customizable: you don't have to use "flex" completion
>> style.  Let's first try it out and then see if we need _more_
>> customization.
>
> I'd rather we start with the "more simply" alternative I've
> mentioned. But others are welcome to add their opinions.

Eventually, we can add a keybinding to resort exclusively according to
the table or exclusively according to the completion style.

>>> Is this for debugging?
>>
>> At the moment, yes mostly.  But it could not be.  In SLY, I give users
>> an indication of how the scoring algorithm is working.  See it in
>> action:
>>
>> https://raw.githubusercontent.com/joaotavora/sly/master/doc/animations/company-flex-completion.gif
>
> It's kind of neat, but to be honest I don't see how these percentages
> help a random user.

I can agree they should be improved.  It would be good to integrate some
prior art regarding flex string matching that has a good measure
of the match quality.  The one in the prototype is a empirical thing
that works quite OK for Common Lisp and myself.  `string-distance', for
instance, gives the the Levenshtein distance.  It's got a fancy name,
but it's not very useful for flex completion before

  (string-distance "foo" "barfoo") = (string-distance "foo" "frodos")

And we want "barfoo" to come first.  string-distance talks about
"deletions, insertions and substitutions required to transform a string
into another".  Perhaps if it measured also "move operations" it would
be a better measure.

Then instead of the percentage, we could show just the number of 1-char
editing operations, including moves, to turn the pattern into the
candidate.  That's a measure with actual meaning.

> Even if they do, there's no need to couple this annotation addition to
> the completion style. Just use a new annotation function that looks up
> the text properties that the style adds, and adds them on.

Again, this would only affect the specific completion table that I'm
writing this function for, right?  Or can I write metadata functions for
completion styles?

João



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

* new-flex-completion-style (was: [Emacs-diffs] scratch/ 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness)
       [not found] ` <20190202232828.4AE452159A@vcs0.savannah.gnu.org>
  2019-02-06  3:11   ` [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness Dmitry Gutov
@ 2019-02-11 21:10   ` Stefan Monnier
  2019-02-11 22:16     ` new-flex-completion-style João Távora
  2019-02-11 22:57     ` new-flex-completion-style (was: [Emacs-diffs] scratch/ 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness) Drew Adams
  1 sibling, 2 replies; 71+ messages in thread
From: Stefan Monnier @ 2019-02-11 21:10 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

>     Score, sort and annotate flex-style completions according to match
>     tightness

Sorting is a complicated matter here: we have completion tables,
completion styles, and completion front-ends, and all three seem to want
to be able to sort.

Obviously, the front-end has ultimate control, so we can't stop it from
sorting the way it likes, but we'd like it to be able to make an
informed choice.

As for sorting by the completion table or sorting by the completion
style, it's hard to figure out what should be done in general.
FWIW, it seems that all the completion tables that care about sorting do
it by sorting directly in `all-completions` and then setting the
*-sort-function to `identity`.  Presumably this can only DTRT for "flat"
completion tables.

W.r.t the UI sorting minibuffer.el has 2 different UIs with 2 different
sorting behaviors: there's the *Completions* buffer where results are
sorted alphabetically, and there's the force-complete cycling which
sorts by most-recently seen (using the minibuffer history variable) and
by length.

All this was designed in the context of completion tables and styles
where all returned candidates are basically equally likely.

Flex is going in the direction of completion systems where instead of
splitting the candidates between "possible matches" and "impossible
matches", the matches are all considered as possible, with some more
likely than others.

So in such a context, it's of utmost importance for the completion
table-or-style to provide its own sorting.  And in that case, I guess
most UIs should simply follow that sorting (instead of the current
situation where each UI uses its own sorting).

Still, in a case such as lisp/ecomplete.el where the completion table
provides its own sorting based on recent-usage-frequency, how should
this sorting be combined with that of flex?  I can see arguments in
favor of saying that the flex-weight should be ignored in favor of the
usage-frequency.

>     Up until now, there was no way for completion styles to control
>     sorting.  This change add such a facility and activated it for the new
>     "flex" completion style.

I'd like to move towards a completion-style API that uses cl-generic.
E.g. introduce generic functions like `completion-style-try-completion`
which would be like `completion-try-completion` but takes an additional
`style` argument and dispatches based on it (replacing the dispatch
based on completion-style-alist).

Maybe the sorting code (currently in minibuffer-completion-help) should
be moved to such a generic function, so the completion style would have
the choice of how it uses the `display-sort-function`.  But then should
we do the same with the sorting done in
`completion-all-sorted-completions` or should we come up with a single
generic function that covers both needs?

>     * lisp/minibuffer.el (minibuffer-completion-help): Use
>     completion-style-sort-order and compeltion-style-annotation
                                      ^^^^^^^^^^
                                      completion
>     properties.
>     (completion-pcm--hilit-commonality): Propertize completion with
>     'completion-pcm-commonality-score.
>     (completion-flx-all-completions): Porpertize completion with
                                        ^^^^^^^^^^
                                        Propertize

>     completion-style-sort-order and completion-style-annotation.

Regarding annotations, I think being able to `concat` at the end is
too limited.  If you take your example from sly, we'd like the "15%"
annotations to be right-aligned and I don't see an easy way to do that
with the facility you introduce.

The current annotation facility is also too limited in another way: in
read-char-by-name we annotate each char name with the actual char it
names, but we'd really like to prepend this annotation rather than
append it (it would make the chars much easier to see and to compare),
but the current annotation system doesn't offer this flexibility.

So I'd encourage you to come up with a more flexible annotation system
that allows prepending annotations as well as right-alignment (and
ideally combinations of those, with several columns, ...).


        Stefan



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

* Re: new-flex-completion-style
  2019-02-11 21:10   ` new-flex-completion-style (was: [Emacs-diffs] scratch/ 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness) Stefan Monnier
@ 2019-02-11 22:16     ` João Távora
  2019-02-11 23:02       ` new-flex-completion-style Dmitry Gutov
                         ` (2 more replies)
  2019-02-11 22:57     ` new-flex-completion-style (was: [Emacs-diffs] scratch/ 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness) Drew Adams
  1 sibling, 3 replies; 71+ messages in thread
From: João Távora @ 2019-02-11 22:16 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: dgutov, emacs-devel

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

> W.r.t the UI sorting minibuffer.el has 2 different UIs with 2 different
> sorting behaviors: there's the *Completions* buffer where results are
> sorted alphabetically, and there's the force-complete cycling which
> sorts by most-recently seen (using the minibuffer history variable) and
> by length.

Tangent: When using icomplete (who else here uses icomplete?), this is
(the length) not good at all for switching buffers.  I want it to behave
like ido, where the natural order of buffer-list is preserved when the
buffer can't be found in the minibuffer-history-variable.  IOW for the
icomplete UI, sorting by length makes little sense.  It may make sense
for completion-at-point cycling.  I'm working on a patch for this.

> All this was designed in the context of completion tables and styles
> where all returned candidates are basically equally likely.
>
> Flex is going in the direction of completion systems where instead of
> splitting the candidates between "possible matches" and "impossible
> matches", the matches are all considered as possible, with some more
> likely than others.
> So in such a context, it's of utmost importance for the completion
> table-or-style to provide its own sorting.  And in that case, I guess
> most UIs should simply follow that sorting (instead of the current
> situation where each UI uses its own sorting).

The only problem is that completion-style doesn't have a point to
plug-in sorting yet.  So I thought good place to start is to place hints
in the completion-candidates.

> Still, in a case such as lisp/ecomplete.el where the completion table
> provides its own sorting based on recent-usage-frequency, how should
> this sorting be combined with that of flex?  I can see arguments in
> favor of saying that the flex-weight should be ignored in favor of the
> usage-frequency.

ecomplete has its own UI in ecomplete-display-matches? It's a question
of using or discarding the completion-style sorting hints stored in each
candidate.

My view of the matter is: completion table provides its sorting which
_can_ be overriden by completion style's sorting which _can_ be
overriden by completion UI's sorting.  AFAIU this can be done by writing
comparison functions that return nil if the current sorting should be
agnostic to both elements.

>>     Up until now, there was no way for completion styles to control
>>     sorting.  This change add such a facility and activated it for the new
>>     "flex" completion style.
>
> I'd like to move towards a completion-style API that uses cl-generic.
> E.g. introduce generic functions like `completion-style-try-completion`
> which would be like `completion-try-completion` but takes an additional
> `style` argument and dispatches based on it (replacing the dispatch
> based on completion-style-alist).

This is a good change, but it's not absolutely necessary to what I am
proposing right now.

>>     * lisp/minibuffer.el (minibuffer-completion-help): Use
>>     completion-style-sort-order and compeltion-style-annotation
>                                       ^^^^^^^^^^
>                                       completion
>>     properties.
>>     (completion-pcm--hilit-commonality): Propertize completion with
>>     'completion-pcm-commonality-score.
>>     (completion-flx-all-completions): Porpertize completion with
>                                         ^^^^^^^^^^
>                                         Propertize

Thanks.

>>     completion-style-sort-order and completion-style-annotation.
> Regarding annotations, I think being able to `concat` at the end is
> too limited.  If you take your example from sly, we'd like the "15%"
> annotations to be right-aligned and I don't see an easy way to do that
> with the facility you introduce.

I don't see the problem fully, but probably I'd rather remove the
annotation completely for now, until we have a better of how where we
want to place it.  As Dmitry suggested, the flex score annotation is
mostly a gimmick, we shouldn't add it until we have a good idea of how
it should work.
>
> The current annotation facility is also too limited in another way: in
> read-char-by-name we annotate each char name with the actual char it
> names, but we'd really like to prepend this annotation rather than
> append it (it would make the chars much easier to see and to compare),
> but the current annotation system doesn't offer this flexibility.
>
> So I'd encourage you to come up with a more flexible annotation system
> that allows prepending annotations as well as right-alignment (and
> ideally combinations of those, with several columns, ...).

What do you suggest?  I'd prefer small things that can be added
incrementally.  IOW, I don't have time for grand designs right now, I'm
mostly scratching the personal itch that is making icomplete.el not make
me miss ido.el so much.

So to summarize, I propose to add (1) the fafa9ec commit introducing
flex completion and (2) a new commit extracted from 2c7577558 which adds
the flex scoring calculation to each match, but doesn't do anything with
it yet.  Deal?

The first commit by itself can already greatly improve icomplete Ui.
And the second commit should encourage UI devs to start taking the
completion-style-sort-order hint into account.  If Dmitry does that in
company-capf, we get decent flex completion for little cost.

João



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

* RE: new-flex-completion-style (was: [Emacs-diffs] scratch/ 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness)
  2019-02-11 21:10   ` new-flex-completion-style (was: [Emacs-diffs] scratch/ 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness) Stefan Monnier
  2019-02-11 22:16     ` new-flex-completion-style João Távora
@ 2019-02-11 22:57     ` Drew Adams
  1 sibling, 0 replies; 71+ messages in thread
From: Drew Adams @ 2019-02-11 22:57 UTC (permalink / raw)
  To: Stefan Monnier, João Távora; +Cc: emacs-devel

FWIW -

I guess you're arguing for an ability to sort completion candidates at multiple places/levels, including far upstream from interactive use.

My concern/interest is more about interactive use, where sorting can usefully interact with progressive filtering.  I like late binding. ;-)

In my context (Icicles) users can filter completion candidates incrementally in various ways, and sorting can act either on "raw" completion candidates (e.g. alist entries, including their cdrs) or on displayed candidates (e.g. text in *Completions*).

Unlike vanilla Emacs, the same sort order applies (intentionally) for displaying matching completions and for cycling among those candidates.

Users can switch among any number of sort orders (predicates) interactively.

The default set of sort orders available for this switching is defined by a user option.  But the code context (e.g. code that calls `completing-read') can change this set.  So different commands can make different sets of sort orders available.

Users can define new sort orders with a macro, which adds them to those made available by the user option.

Maybe some such capabilities would be relevant to your context; dunno.

https://www.emacswiki.org/emacs/Icicles_-_Sorting_Candidates



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

* Re: new-flex-completion-style
  2019-02-11 22:16     ` new-flex-completion-style João Távora
@ 2019-02-11 23:02       ` Dmitry Gutov
  2019-02-11 23:11         ` new-flex-completion-style João Távora
  2019-02-12  0:16       ` new-flex-completion-style Óscar Fuentes
  2019-02-12 14:08       ` new-flex-completion-style Stefan Monnier
  2 siblings, 1 reply; 71+ messages in thread
From: Dmitry Gutov @ 2019-02-11 23:02 UTC (permalink / raw)
  To: João Távora, Stefan Monnier; +Cc: emacs-devel

On 12.02.2019 01:16, João Távora wrote:
> And the second commit should encourage UI devs to start taking the
> completion-style-sort-order hint into account.  If Dmitry does that in
> company-capf, we get decent flex completion for little cost.

Note that if you adopt the approach I suggested (leave sorting to the 
display-sort-function), it will work with company-capf automatically.

And this can work in two ways: either the completion style adds text 
properties and the sort function looks it up, or the completion style 
(?) or the completion table does the sorting right away, and the 
display-sort-function is #'identity.



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

* Re: new-flex-completion-style
  2019-02-11 23:02       ` new-flex-completion-style Dmitry Gutov
@ 2019-02-11 23:11         ` João Távora
  2019-02-12  0:10           ` new-flex-completion-style Dmitry Gutov
  0 siblings, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-11 23:11 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Stefan Monnier, emacs-devel

On Mon, Feb 11, 2019 at 11:02 PM Dmitry Gutov <dgutov@yandex.ru> wrote:
>
> On 12.02.2019 01:16, João Távora wrote:
> > And the second commit should encourage UI devs to start taking the
> > completion-style-sort-order hint into account.  If Dmitry does that in
> > company-capf, we get decent flex completion for little cost.
>
> Note that if you adopt the approach I suggested (leave sorting to the
> display-sort-function), it will work with company-capf automatically.
>
> And this can work in two ways: either the completion style adds text
> properties and the sort function looks it up, or the completion style
> (?) or the completion table does the sorting right away, and the
> display-sort-function is #'identity.

Apparently there is something I am still missing about
display-sort-function. I admit to not have looked very hard at it. This
is probably why I didn't understand your suggestion.

Why don't we do this:  I add the two (presumably) unproblematic commits
(the new flex style + propertize completions with a numeric property), you
show me a patch where display-sort-function is plugged into the style,
supposing it is not very hard to do.  Deal?

João


-- 
João Távora



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

* Re: new-flex-completion-style
  2019-02-11 23:11         ` new-flex-completion-style João Távora
@ 2019-02-12  0:10           ` Dmitry Gutov
  0 siblings, 0 replies; 71+ messages in thread
From: Dmitry Gutov @ 2019-02-12  0:10 UTC (permalink / raw)
  To: João Távora; +Cc: Stefan Monnier, emacs-devel

On 12.02.2019 02:11, João Távora wrote:
> Why don't we do this:  I add the two (presumably) unproblematic commits
> (the new flex style + propertize completions with a numeric property), you
> show me a patch where display-sort-function is plugged into the style,
> supposing it is not very hard to do.  Deal?

Not plugged, but is integrated with. But sure.



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

* Re: new-flex-completion-style
  2019-02-11 22:16     ` new-flex-completion-style João Távora
  2019-02-11 23:02       ` new-flex-completion-style Dmitry Gutov
@ 2019-02-12  0:16       ` Óscar Fuentes
  2019-02-12 22:04         ` new-flex-completion-style João Távora
  2019-02-12 14:08       ` new-flex-completion-style Stefan Monnier
  2 siblings, 1 reply; 71+ messages in thread
From: Óscar Fuentes @ 2019-02-12  0:16 UTC (permalink / raw)
  To: emacs-devel

João Távora <joaotavora@gmail.com> writes:

> I don't see the problem fully, but probably I'd rather remove the
> annotation completely for now, until we have a better of how where we
> want to place it.  As Dmitry suggested, the flex score annotation is
> mostly a gimmick, we shouldn't add it until we have a good idea of how
> it should work.

Do you know flx [1] ? Would it be possible to implement it on top of
your work by providing a score function and/or a sort function?

1. https://github.com/lewang/flx




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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-06 19:47         ` João Távora
@ 2019-02-12  0:25           ` Dmitry Gutov
  2019-02-12 13:19             ` Stefan Monnier
  2019-02-12 17:21             ` João Távora
  0 siblings, 2 replies; 71+ messages in thread
From: Dmitry Gutov @ 2019-02-12  0:25 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

On 06.02.2019 22:47, João Távora wrote:

> Perhaps I'm missing something, and that is taiting all the remaining
> discussion.  Aren't these properties/metadata thingies specific to the
> completion table (files, buffers, code completions, etc)?

metadata - yes, properties - no (those are extra elements at the end of 
the list returned by completion-at-point-functions).

See completion--metadata and completion-extra-properties.

display-sort-function, for now, can only be a metadata element (though 
that shouldn't be hard to change). annotation-function, however, can be 
either.

So as things stand, the use of this completion style that'd see in mind, 
is when a particular completion function returns a table that indicates 
a particular category (for which the use of flex completion style is 
enabled), and a particular display-sort-function in its metadata.

Consequently, a preexisting completion tables wouldn't be supported. But 
like I said, it shouldn't be hard to change either.

> In otherwords I should be able to mix and match
> 
> - frontends
> - completion styles
> - backends
> 
> Right?  Well all I'm saying is that, when using the flex/scatter
> completion style, it's almost always, if not always always, a better
> idea to stable-sort by flex-match score.

I dunno, sorting takes CPU time anyways. Not sure a combination of 
several sorting functions will frequently give a better result than just 
one of them.

> One good way to see this is to try my code with your company.el package,
> which doesn't (hopefully _doesn't yet_) use the completion style's
> sorting hints.  You can try it in Emacs Lisp. First do:
> 
>     (setq completion-styles '(flex))
> 
> Now go into the *scratch* buffer and type "undo". You'll see it's not
> very useful: the first match you get is ":argument-precedence-order", a
> legitimate match, for sure, but you probably meant something related to
> the undo facilities.  And you have to scroll quite a bit before you to
> "buffer-undo-list", which is buried deep in the many many b's that
> match.

But then, if you enable company-sort-by-occurrence via 
company-transformers, the completion style's sorting won't be visible 
anymore anyway.

It's a question whether any other sorting approaches end up being 
helpful, but maybe some hybrid functions will work, where both 
occurrences and flex score are taken into account.

> Eventually, we can add a keybinding to resort exclusively according to
> the table or exclusively according to the completion style.

In the approach I'm thinking of, both options are the same sorting function.

> And we want "barfoo" to come first.  string-distance talks about
> "deletions, insertions and substitutions required to transform a string
> into another".  Perhaps if it measured also "move operations" it would
> be a better measure.

That's helpful to consider for the actual scores, and sorting.

> Then instead of the percentage, we could show just the number of 1-char
> editing operations, including moves, to turn the pattern into the
> candidate.  That's a measure with actual meaning.

And still, seeing it wouldn't help me if I'm just writing code. Sorry 
for being blunt.

Sort by them, sure. But show the values to the user? Why?

>> Even if they do, there's no need to couple this annotation addition to
>> the completion style. Just use a new annotation function that looks up
>> the text properties that the style adds, and adds them on.
> 
> Again, this would only affect the specific completion table that I'm
> writing this function for, right?  Or can I write metadata functions for
> completion styles?

The former, more or less. This creates a certain limitation, sure, but 
it shouldn't be a problem for Eglot.



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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-12  0:25           ` Dmitry Gutov
@ 2019-02-12 13:19             ` Stefan Monnier
  2019-02-12 22:55               ` Dmitry Gutov
  2019-02-12 17:21             ` João Távora
  1 sibling, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2019-02-12 13:19 UTC (permalink / raw)
  To: emacs-devel

> See completion--metadata and completion-extra-properties.

But a completion style like `flex` can't affect either of those.
And I expect some people will want to put in their `completion-styles`,
so `flex` should work well for all/most completion tables and all/most
completion-at-point-functions (and calls to completing-read).

> I dunno, sorting takes CPU time anyways. Not sure a combination of several
> sorting functions will frequently give a better result than just one
> of them.

I think I agree here: the stability of the `flex` sort is likely to make
little difference in practice (more specifically, the sets of matches
which share the same flex-score will be sufficiently numerous and small
that the sorting within them is not significant).

> But then, if you enable company-sort-by-occurrence via company-transformers,
> the completion style's sorting won't be visible anymore anyway.

I think this is OK: the front-end can indeed override the
sorting chosen by the completion-style and the completion-table.
If the result is poor, it's the front-end's problem and it is in
a position to fix it.

> It's a question whether any other sorting approaches end up being helpful,
> but maybe some hybrid functions will work, where both occurrences and flex
> score are taken into account.

Not sure how that can be done in a modular way: how can we specify an
API where `flex` can provide its scores, `sort-by-occurrence` can
specify its scores, they don't know about each other, and yet the two
sets of scores get mixed in a useful way?


        Stefan




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

* Re: new-flex-completion-style
  2019-02-11 22:16     ` new-flex-completion-style João Távora
  2019-02-11 23:02       ` new-flex-completion-style Dmitry Gutov
  2019-02-12  0:16       ` new-flex-completion-style Óscar Fuentes
@ 2019-02-12 14:08       ` Stefan Monnier
  2019-02-12 22:17         ` new-flex-completion-style João Távora
  2019-02-18 20:46         ` new-flex-completion-style João Távora
  2 siblings, 2 replies; 71+ messages in thread
From: Stefan Monnier @ 2019-02-12 14:08 UTC (permalink / raw)
  To: emacs-devel

>> W.r.t the UI sorting minibuffer.el has 2 different UIs with 2 different
>> sorting behaviors: there's the *Completions* buffer where results are
>> sorted alphabetically, and there's the force-complete cycling which
>> sorts by most-recently seen (using the minibuffer history variable) and
>> by length.
> Tangent: When using icomplete (who else here uses icomplete?), this is
> (the length) not good at all for switching buffers.

Not sure if it's related to icomplete.  Maybe the length-heuristic is
just not good for buffer names.  It was mostly motivated by experience
with M-x where I do believe that there is a correlation between command
name length and frequency of use of that command.

I think this length heuristic also works reasonably well in several
other circumstances (e.g. file names).

[ I'm clearly talking about the TAB-cycling use case, but I can't think
  of a good reason why the icomplete-mode should be very different.  ]

> I want it to behave like ido, where the natural order of buffer-list
> is preserved when the buffer can't be found in the
> minibuffer-history-variable.

How 'bout we change the buffer name completion table so it specifies its
own cycle-sort-function which uses buffer-list, then.  It seems like it
would be a clear win (the buffer-list order is a much better heuristic
than the length).

> The only problem is that completion-style doesn't have a point to
> plug-in sorting yet.

That's right.

> So I thought good place to start is to place hints
> in the completion-candidates.

It's probably a good idea, yes.

>> Still, in a case such as lisp/ecomplete.el where the completion table
>> provides its own sorting based on recent-usage-frequency, how should
>> this sorting be combined with that of flex?  I can see arguments in
>> favor of saying that the flex-weight should be ignored in favor of the
>> usage-frequency.
> ecomplete has its own UI in ecomplete-display-matches?

It also offers a completion-table (which I use via
a completion-at-point-function).

> My view of the matter is: completion table provides its sorting which
> _can_ be overriden by completion style's sorting which _can_ be
> overriden by completion UI's sorting.  AFAIU this can be done by writing
> comparison functions that return nil if the current sorting should be
> agnostic to both elements.

Writing the function is of course the easy part. 
The problem is where/how to insert this function.

>> I'd like to move towards a completion-style API that uses cl-generic.
>> E.g. introduce generic functions like `completion-style-try-completion`
>> which would be like `completion-try-completion` but takes an additional
>> `style` argument and dispatches based on it (replacing the dispatch
>> based on completion-style-alist).
>
> This is a good change, but it's not absolutely necessary to what I am
> proposing right now.

Definitely.  I just wanted to explain that the design to the current
solution can be done with this other change in mind.

>>>     * lisp/minibuffer.el (minibuffer-completion-help): Use
>>>     completion-style-sort-order and compeltion-style-annotation
>>                                       ^^^^^^^^^^
>>                                       completion
>>>     properties.
>>>     (completion-pcm--hilit-commonality): Propertize completion with
>>>     'completion-pcm-commonality-score.
>>>     (completion-flx-all-completions): Porpertize completion with
>>                                         ^^^^^^^^^^
>>                                         Propertize
> Thanks.

Duh!  I meant to add some idiotic scolding about those typos but got
side tracked by the annotations issue.  Sorry.  I promise to be more
firm next time.

>>>     completion-style-sort-order and completion-style-annotation.
>> Regarding annotations, I think being able to `concat` at the end is
>> too limited.  If you take your example from sly, we'd like the "15%"
>> annotations to be right-aligned and I don't see an easy way to do that
>> with the facility you introduce.
> I don't see the problem fully,

Hmm... I guess in the completion-style case, you could indeed look at
all the returned completions to compute the max-length and do some
right-alignment based on that.  For some reason, I feel like it'd be
better done elsewhere, tho (e.g. maybe company would rather right-align
based on the max-length of the *displayed* completions rather than
based on the max-length of all the completions).

> but probably I'd rather remove the annotation completely for now,
> until we have a better of how where we want to place it.  As Dmitry
> suggested, the flex score annotation is mostly a gimmick, we shouldn't
> add it until we have a good idea of how it should work.

Indeed, this annotation issue is orthogonal, so it can be kept for later.

>> So I'd encourage you to come up with a more flexible annotation system
>> that allows prepending annotations as well as right-alignment (and
>> ideally combinations of those, with several columns, ...).
>
> I'd prefer small things that can be added
> incrementally.

So do I.

> What do you suggest?

Nothing so far.

> So to summarize, I propose to add (1) the fafa9ec commit introducing
> flex completion and (2) a new commit extracted from 2c7577558 which adds
> the flex scoring calculation to each match, but doesn't do anything with
> it yet.  Deal?

Fine by me.  I'd call the score property `completion-score` because
I don't see any reason why it should be specific to the completion-style
(you could even have `flex` combine its score with a `completion-score`
property previously set by the completion-table, and then have the
front end combine that with its own scoring).

I think you can also make minibuffer-completion-help sort according to
that `completion-score`.

Regarding the code, see comments below.


        Stefan


> +          (setq completions
> +                (sort completions
> +                      (lambda (a b)
> +                        (let ((va (get-text-property 0 'completion-style-sort-order a))
> +                              (vb (get-text-property 0 'completion-style-sort-order b)))
> +                          (if (and va vb) (< va vb) va)))))

This will signal an error when one of the completions is the empty string :-(

> @@ -3056,22 +3067,41 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
>           (let* ((pos (if point-idx (match-beginning point-idx) (match-end 0)))
>                  (md (match-data))
>                  (start (pop md))
> -                (end (pop md)))
> +                (end (pop md))
> +                (len (length str))
> +                (score-numerator 0)
> +                (score-denominator 0)
> +                (aux 0)
> +                (update-score
> +                 (lambda (a b)
> +                   "Update score variables given match range (A B)."
> +                   (setq
> +                    score-numerator   (+ score-numerator (- b a))
> +                    score-denominator (+ score-denominator (expt (- a aux) 1.5))
> +                    aux              b))))

I don't understand this scoring algorithm: please add a comment
explaining it (and give a meaningful name to `aux`).

> +           (funcall update-score 0 start)
>             (while md
> -             (put-text-property start (pop md)
> +             (funcall update-score start (car md))
> +             (put-text-property start
> +                                (pop md)

The extra line-break after `start` seems spurious.

> +           (put-text-property
> +            0 1 'completion-pcm-commonality-score
> +            (/ score-numerator (* len (1+ score-denominator)) 1.0) str))

This will signal an error when `str` is the empty string :-(

BTW, maybe PCM could also use this scoring for sorting (i.e. we could
set `completion-score` directly here)

> +           (let ((score (get-text-property 0 'completion-pcm-commonality-score comp)))
> +             (put-text-property 0 1 'completion-style-sort-order (- score) comp)

This will signal an error when `comp` is the empty string :-(




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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-12  0:25           ` Dmitry Gutov
  2019-02-12 13:19             ` Stefan Monnier
@ 2019-02-12 17:21             ` João Távora
  2019-02-12 23:47               ` Dmitry Gutov
  1 sibling, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-12 17:21 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: emacs-devel

Dmitry Gutov <dgutov@yandex.ru> writes:

> Consequently, a preexisting completion tables wouldn't be
> supported. But like I said, it shouldn't be hard to change either.

Oh.  That's what I feared (I think) It would be nice to add something
seemingly orthogonal like a "completion style" to all completion UI's
and all tables, without needing to change the completion tables
(granted, it would be good to *also* not change the UI's, but I'm not
sure there a solution for that).

> I dunno, sorting takes CPU time anyways. Not sure a combination of
> several sorting functions will frequently give a better result than
> just one of them.

I dunno what you dunno.  When using flex/scatter it's *really* important
to sort by flex-match.  I suggested "stable sorting" because it's a
slightly more decent thing to completion tables.  And by sorting twice
it's not like we're changing the Big-O complexity or anything.

But I also don't mind a scheme where the style's sorting completely
takes over (and we save those CPU cycles).

> But then, if you enable company-sort-by-occurrence via
> company-transformers, the completion style's sorting won't be visible
> anymore anyway.

I don't know what company-transformers are.  On the one hand I suppose
when you want to sort by occurance, you ... want to sort by occurrence.
So if you use the symbol "foofooubarbarnbazbazdquuxquuxo" very often
you'll see it sort to the top for your "undo" example.  So maybe company
should take the style's sorting last here, dunno.

> It's a question whether any other sorting approaches end up being
> helpful, but maybe some hybrid functions will work, where both
> occurrences and flex score are taken into account.

In this case I would first sort by occurance and then style-score.
There's no easy way to make a hybrid function, so we must pick a
default.  For all the examples I've been given, it seems that
flex-sorting should always come last. Since flex is the first and only
style that carries some sorting idea with it, perhaps it's not a very
bad idea to give it _some_ priority by default.

>> Eventually, we can add a keybinding to resort exclusively according to
>> the table or exclusively according to the completion style.
>
> In the approach I'm thinking of, both options are the same sorting
> function.

How would you synthetize it? 

> And still, seeing it wouldn't help me if I'm just writing code. Sorry
> for being blunt.

I'm a big boy, I can take blunt... :-)

> Sort by them, sure. But show the values to the user? Why?

In the general case, so the user has an idea _why_ something is being
automatically.  Humans generally gain confidence in algorithms if
they're shown human-comprehensible hints as to why it is is doing
something (humans generally also like this from other humans, which
explains why you ask me so many questions :-).

In this particular case, it's a very common idiom when displaying
tables/lists of something.  Perhaps in the "occurance sorting" field,
he/she will choose another word used less frequently for stylistic
purposes.

But, all that said, I'm not going to kill myself over the annotation,
nor do I think it even merits a customization option, though it's
probably not hard to do it anyway.

> The former, more or less. This creates a certain limitation, sure, but
> it shouldn't be a problem for Eglot.

Hmm? By far, Eglot isn't the only one thing I'm interested in enhancing
(actually, I've had few opportunities to actualy _use_ Eglot lately).

João




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

* Re: new-flex-completion-style
  2019-02-12  0:16       ` new-flex-completion-style Óscar Fuentes
@ 2019-02-12 22:04         ` João Távora
  2019-02-13  0:28           ` new-flex-completion-style Óscar Fuentes
  0 siblings, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-12 22:04 UTC (permalink / raw)
  To: Óscar Fuentes; +Cc: emacs-devel

Óscar Fuentes <ofv@wanadoo.es> writes:

> João Távora <joaotavora@gmail.com> writes:

> Do you know flx [1] ? Would it be possible to implement it on top of
> your work by providing a score function and/or a sort function?
>
> 1. https://github.com/lewang/flx

I remember looking at this a long time ago.  It looked interesting, but
is almost certainly more complex/featureful than my implementation,
which is reasonably simple and tries to play along with the Emacs's
completion style/table/UI framework, something which is still relatively
fluid (as you can read in this thread).  So I'd rather take it slowly
before adding new features.

But I don't know what features you are looking for exactly, can you be
specific?

João



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

* Re: new-flex-completion-style
  2019-02-12 14:08       ` new-flex-completion-style Stefan Monnier
@ 2019-02-12 22:17         ` João Távora
  2019-02-13 17:29           ` new-flex-completion-style João Távora
  2019-02-18 20:46         ` new-flex-completion-style João Távora
  1 sibling, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-12 22:17 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> Not sure if it's related to icomplete.  Maybe the length-heuristic is
> just not good for buffer names.

Agreed. 

> I think this length heuristic also works reasonably well in several
> other circumstances (e.g. file names).

OK. Makes sense.  Just to be sure we're talking about
completion-all-sorted-completions, right?

> It seems like it would be a clear win (the buffer-list order is a much
> better heuristic than the length).

I'm so glad you're volunteering to do this ;-)

>>> Still, in a case such as lisp/ecomplete.el where the completion table
>>> provides its own sorting based on recent-usage-frequency, how should
>>> this sorting be combined with that of flex?  I can see arguments in
>>> favor of saying that the flex-weight should be ignored in favor of the
>>> usage-frequency.
>> ecomplete has its own UI in ecomplete-display-matches?
>
> It also offers a completion-table (which I use via
> a completion-at-point-function).

But I can use that table with another UI right?  Is that
completion-at-point-function in Emacs or in your config?

>> My view of the matter is: completion table provides its sorting which
>> _can_ be overriden by completion style's sorting which _can_ be
>> overriden by completion UI's sorting.  AFAIU this can be done by writing
>> comparison functions that return nil if the current sorting should be
>> agnostic to both elements.
>
> Writing the function is of course the easy part. 
> The problem is where/how to insert this function.

We have to decide on a good standard order/combination of sorting
functions.  If we decide that's not good enough for some cases we can go
for more indirections à la CL method combinations.  (wonder if
cl-generic has method combinations).

But this could very possibly be overdesigning at this point.

> Duh!  I meant to add some idiotic scolding about those typos but got
> side tracked by the annotations issue.  Sorry.  I promise to be more
> firm next time.

Since this makes fixing my dumb mistakes more fun, I hereby scold you
for your lack of scolding.

>> I don't see the problem fully,
> Hmm... I guess in the completion-style case, you could indeed look at
> all the returned completions to compute the max-length and do some
> right-alignment based on that.  For some reason, I feel like it'd be
> better done elsewhere, tho (e.g. maybe company would rather right-align
> based on the max-length of the *displayed* completions rather than
> based on the max-length of all the completions).

I'll think better about this once we sort out the sorting, which has
priority.

>> So to summarize, I propose to add (1) the fafa9ec commit introducing
>> flex completion and (2) a new commit extracted from 2c7577558 which adds
>> the flex scoring calculation to each match, but doesn't do anything with
>> it yet.  Deal?
>
> Fine by me.  I'd call the score property `completion-score` because
> I don't see any reason why it should be specific to the completion-style
> (you could even have `flex` combine its score with a `completion-score`
> property previously set by the completion-table, and then have the
> front end combine that with its own scoring).
>
> I think you can also make minibuffer-completion-help sort according to
> that `completion-score`.
>
> Regarding the code, see comments below.

I've pushed a new version fixing the problems you reported off-list.  I
did that _before_ reading this message.

I'll take a look at this new batch, do the obvious fixes.  But before
submitting anything sorting-related, I'd like Dmitry to show a patch for
his sorting idea on top of scratch/new-flex-completion-style, try it out
a bit and then report back here.

João





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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-12 13:19             ` Stefan Monnier
@ 2019-02-12 22:55               ` Dmitry Gutov
  2019-02-13 16:00                 ` Stefan Monnier
  0 siblings, 1 reply; 71+ messages in thread
From: Dmitry Gutov @ 2019-02-12 22:55 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

On 12.02.2019 16:19, Stefan Monnier wrote:
>> See completion--metadata and completion-extra-properties.
> 
> But a completion style like `flex` can't affect either of those.
> And I expect some people will want to put in their `completion-styles`,
> so `flex` should work well for all/most completion tables and all/most
> completion-at-point-functions (and calls to completing-read).

On the one hand, yes, but it's the abstraction we already have, and it 
will allow flex to work properly at least with certain completion 
tables. Which is a win.

On the other hand, a search for display-sort-function through Emacs's 
sources seems to indicate that the design is kind of a failure: there 
are only a couple places that set it to something, and in both cases 
it's #'identity, meaning "do not re-sort".

So minibuffer.el might want to take a cue from Company and 
company-transformers, to make this universal, we could add sorting as a 
feature of completion styles, or as a separate user option, for maximum 
flexibility. I'd simply like to avoid hardcoding extra sorting behavior, 
like the patch proposes.

> I think I agree here: the stability of the `flex` sort is likely to make
> little difference in practice (more specifically, the sets of matches
> which share the same flex-score will be sufficiently numerous and small
> that the sorting within them is not significant).

Yep.

> Not sure how that can be done in a modular way: how can we specify an
> API where `flex` can provide its scores, `sort-by-occurrence` can
> specify its scores, they don't know about each other, and yet the two
> sets of scores get mixed in a useful way?

Conveying information via text properties seems like a viable approach. 
We already use them to indicate matching characters, for instance.

Now, I wouldn't say it's terrible that sort-by-occurrence-and-score 
would know specifically about flex (I don't think there's going to be a 
lot of different styles in this flavor), but sure, like you proposed in 
another email, the property can have a neutral name like completion-score.

To emphasize: there won't be a sort-by-occurrence whatever, but a 
function called, say, sort-by-occurrence-and-score could take both 
occurrences and flex scores into account.



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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-12 17:21             ` João Távora
@ 2019-02-12 23:47               ` Dmitry Gutov
  0 siblings, 0 replies; 71+ messages in thread
From: Dmitry Gutov @ 2019-02-12 23:47 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

On 12.02.2019 20:21, João Távora wrote:

> Oh.  That's what I feared (I think) It would be nice to add something
> seemingly orthogonal like a "completion style" to all completion UI's
> and all tables, without needing to change the completion tables
> (granted, it would be good to *also* not change the UI's, but I'm not
> sure there a solution for that).

You have a point, sure. But I'd rather reuse the abstraction we already 
have as the first step, and then maybe extend it (or add a new one), 
rather add sorting code that uses these text properties to an existing 
function.

> I dunno what you dunno.  When using flex/scatter it's *really* important
> to sort by flex-match.  I suggested "stable sorting" because it's a
> slightly more decent thing to completion tables.  And by sorting twice
> it's not like we're changing the Big-O complexity or anything.

Constants matter sometimes, too. Not necessarily in this case, but...

> But I also don't mind a scheme where the style's sorting completely
> takes over (and we save those CPU cycles).

That would be ideal, I think.

> I don't know what company-transformers are.

Not too hard to find out, I think.

> On the one hand I suppose
> when you want to sort by occurance, you ... want to sort by occurrence.
> So if you use the symbol "foofooubarbarnbazbazdquuxquuxo" very often
> you'll see it sort to the top for your "undo" example.  So maybe company
> should take the style's sorting last here, dunno.

OK, I was probably wrong here. Like, if only some of the completions 
have occurences, the rest would be sorted by flex scores, and that... 
sounds pretty good.

> In this case I would first sort by occurance and then style-score.
> There's no easy way to make a hybrid function, so we must pick a
> default.  For all the examples I've been given, it seems that
> flex-sorting should always come last. Since flex is the first and only
> style that carries some sorting idea with it, perhaps it's not a very
> bad idea to give it _some_ priority by default.

You probably mean assign the least priority to flex's scores. The flex 
score sort would happen first with this approach, though.

Almost all completions will have different scores, so sorting by them 
last would make all the previous sorting disappear.

>>> Eventually, we can add a keybinding to resort exclusively according to
>>> the table or exclusively according to the completion style.
>>
>> In the approach I'm thinking of, both options are the same sorting
>> function.
> 
> How would you synthetize it?

Err, not the way you'd want. The table would just be designed to be used 
with the completion style. And so its sorting function.

> In the general case, so the user has an idea _why_ something is being
> automatically.  Humans generally gain confidence in algorithms if
> they're shown human-comprehensible hints as to why it is is doing
> something (humans generally also like this from other humans, which
> explains why you ask me so many questions :-).

For a little while, maybe. To obtain the said confidence. And then, I'd 
opt to turn it off, because I prefer to avoid too much visual clutter 
(one of the reasons to use Emacs).

> In this particular case, it's a very common idiom when displaying
> tables/lists of something.  Perhaps in the "occurance sorting" field,
> he/she will choose another word used less frequently for stylistic
> purposes.
> 
> But, all that said, I'm not going to kill myself over the annotation,
> nor do I think it even merits a customization option, though it's
> probably not hard to do it anyway.

You see, regarding the annotations as well, it makes more sense to reuse 
the existing mechanism, or make it more flexible as well, somehow.

>> The former, more or less. This creates a certain limitation, sure, but
>> it shouldn't be a problem for Eglot.
> 
> Hmm? By far, Eglot isn't the only one thing I'm interested in enhancing
> (actually, I've had few opportunities to actualy _use_ Eglot lately).

Sly's completion table could take the same approach. As long as the 
completion table is under your control, it's all good.

By the way, we could also add an indirection for display-sort-function 
(and maybe the -cycle- one as well) similar to the styles. So we not 
only assign a style (or several of them) based on the category, but also 
the sorting function. This way, sorting of buffers the right way would 
still work and make sense. And at the same time, the user could change 
certain categories to use both flex matching and flex score sorting.

That's more work for the user, but still. Seems kinda elegant.



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

* Re: new-flex-completion-style
  2019-02-12 22:04         ` new-flex-completion-style João Távora
@ 2019-02-13  0:28           ` Óscar Fuentes
  2019-02-13 11:20             ` new-flex-completion-style João Távora
  0 siblings, 1 reply; 71+ messages in thread
From: Óscar Fuentes @ 2019-02-13  0:28 UTC (permalink / raw)
  To: emacs-devel

João Távora <joaotavora@gmail.com> writes:

> Óscar Fuentes <ofv@wanadoo.es> writes:
>
>> João Távora <joaotavora@gmail.com> writes:
>
>> Do you know flx [1] ? Would it be possible to implement it on top of
>> your work by providing a score function and/or a sort function?
>>
>> 1. https://github.com/lewang/flx
>
> I remember looking at this a long time ago.  It looked interesting, but
> is almost certainly more complex/featureful than my implementation,
> which is reasonably simple and tries to play along with the Emacs's
> completion style/table/UI framework, something which is still relatively
> fluid (as you can read in this thread).  So I'd rather take it slowly
> before adding new features.
>
> But I don't know what features you are looking for exactly, can you be
> specific?

Basically, flx takes an input string and a list of candidates, assigns
an score to each candidate and returns a filtered list of candidates
sorted by the score.

This seems the same you described on your commit message.




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

* Re: new-flex-completion-style
  2019-02-13  0:28           ` new-flex-completion-style Óscar Fuentes
@ 2019-02-13 11:20             ` João Távora
  2019-02-13 14:23               ` new-flex-completion-style Óscar Fuentes
  2019-02-13 15:24               ` new-flex-completion-style Stefan Monnier
  0 siblings, 2 replies; 71+ messages in thread
From: João Távora @ 2019-02-13 11:20 UTC (permalink / raw)
  To: Óscar Fuentes; +Cc: emacs-devel

On Wed, Feb 13, 2019 at 12:29 AM Óscar Fuentes <ofv@wanadoo.es> wrote:
>
> João Távora <joaotavora@gmail.com> writes:
>
> > Óscar Fuentes <ofv@wanadoo.es> writes:
> >
> >> João Távora <joaotavora@gmail.com> writes:
> >
> >> Do you know flx [1] ? Would it be possible to implement it on top of
> >> your work by providing a score function and/or a sort function?
> >>
> >> 1. https://github.com/lewang/flx
> >
> > I remember looking at this a long time ago.  It looked interesting, but
> > is almost certainly more complex/featureful than my implementation,
> > which is reasonably simple and tries to play along with the Emacs's
> > completion style/table/UI framework, something which is still relatively
> > fluid (as you can read in this thread).  So I'd rather take it slowly
> > before adding new features.
> >
> > But I don't know what features you are looking for exactly, can you be
> > specific?
>
> Basically, flx takes an input string and a list of candidates, assigns
> an score to each candidate and returns a filtered list of candidates
> sorted by the score.
>
> This seems the same you described on your commit message.

Indeed. I just had a look again.  The engine itself it around 360 loc
which should be 5-10x times longer than what I'm proposing.  The
scoring itself seems quite more intricate, with special cases and
customization for word separators, a "heatmap", camel-case
exceptions, and probably some I haven't understood.

My implementation, on the other hand, takes advantage of the
existing emacs PCM mechanism to generate a
".*<letter>.*<anotherletter>.*" regex to do the matching.
Importantly, it's agnostic to the type of thing represented by
the string being matched. Scoring is hooked onto the existing
logic for char highlighting.  The formula is a simple ad-hoc
thing that I invented and has been working OK.  It's quotient of
a running sum of a function of distances that are known when
highlighting chars.  Basically, it values "tighter" matches in
short strings, so matching "bar" to "obarb" scores higher than
matching it to "foobarbaz" which scores higher than
matching it to "booazzraa".

"Working OK" here means that the thing I meant is almost always
in the first three or four candidates. Perhaps you should try it
and confirm this, or show me cases where it isn't.

But you didn't answer my question: what specific features of flx
are you looking for?  I'd be happy to implement them if I have
the time, but I have to understand what they are.


João



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

* Re: new-flex-completion-style
  2019-02-13 11:20             ` new-flex-completion-style João Távora
@ 2019-02-13 14:23               ` Óscar Fuentes
  2019-02-13 14:38                 ` new-flex-completion-style Drew Adams
  2019-02-13 15:24               ` new-flex-completion-style Stefan Monnier
  1 sibling, 1 reply; 71+ messages in thread
From: Óscar Fuentes @ 2019-02-13 14:23 UTC (permalink / raw)
  To: emacs-devel

João Távora <joaotavora@gmail.com> writes:

> But you didn't answer my question: what specific features of flx
> are you looking for?  I'd be happy to implement them if I have
> the time, but I have to understand what they are.

My question was related to the modifications you are making to the
generic Emacs completion system to allow this type of score+sort
methods. Since flx works on the same principles, if your changes makes
the scoring and sorting user-configurable, alternative methods such as
flx would become usable as well.

I wasn't asking for changes on your "flex" completion method which, BTW,
looks to me as an evolution of ivy's and ido's flex method.

Thanks.




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

* RE: new-flex-completion-style
  2019-02-13 14:23               ` new-flex-completion-style Óscar Fuentes
@ 2019-02-13 14:38                 ` Drew Adams
  0 siblings, 0 replies; 71+ messages in thread
From: Drew Adams @ 2019-02-13 14:38 UTC (permalink / raw)
  To: Óscar Fuentes, emacs-devel

> your "flex" completion method which, BTW, looks to
> me as an evolution of ivy's and ido's flex method.

And Icicles's before those, FWIW.

https://www.emacswiki.org/emacs/Icicles_-_Completion_Methods_and_Styles#ScatterMatchCompletion



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

* Re: new-flex-completion-style
  2019-02-13 11:20             ` new-flex-completion-style João Távora
  2019-02-13 14:23               ` new-flex-completion-style Óscar Fuentes
@ 2019-02-13 15:24               ` Stefan Monnier
  2019-02-13 15:33                 ` new-flex-completion-style Drew Adams
  2019-02-13 15:40                 ` new-flex-completion-style Óscar Fuentes
  1 sibling, 2 replies; 71+ messages in thread
From: Stefan Monnier @ 2019-02-13 15:24 UTC (permalink / raw)
  To: emacs-devel

> But you didn't answer my question: what specific features of flx
> are you looking for?

IIUC Le Wang's `flx` has two main features:
- Its scoring is supposed to be particularly good.
- It's supposed to be particularly fast.

> I'd be happy to implement them if I have
> the time, but I have to understand what they are.

Other than using flx.el I don't see any good way to "implement" those
features (especially the one about speed).

Of course, I have no idea if flx.el's scoring is indeed significantly
better in practice, nor if it's significantly faster in practice either.

BTW, the issue of scoring quality is not nearly as obvious as one might
think because the score one should give to a particular match depends on
the user's expectation and the user's expectation often depend on the
past behavior of the tool, i.e. on the scoring.


        Stefan




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

* RE: new-flex-completion-style
  2019-02-13 15:24               ` new-flex-completion-style Stefan Monnier
@ 2019-02-13 15:33                 ` Drew Adams
  2019-02-13 15:40                 ` new-flex-completion-style Óscar Fuentes
  1 sibling, 0 replies; 71+ messages in thread
From: Drew Adams @ 2019-02-13 15:33 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

> BTW, the issue of scoring quality is not nearly as obvious as one might
> think because the score one should give to a particular match depends
> on the user's expectation and the user's expectation often depend on
> the past behavior of the tool, i.e. on the scoring.

+1 - good point. There's room for the tool to learn too.

And it can depend on the context - intended use of
the chosen completion(s).  The completing function
(completion table etc.) typically does not have a
good view of the user's context, including intent.

Put differently, if scoring only has the matches
and the input pattern to go on, the most it can do
is offer some measure of comparison based on just
those two inputs.  A score that's really useful to
a user might depend on more.



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

* Re: new-flex-completion-style
  2019-02-13 15:24               ` new-flex-completion-style Stefan Monnier
  2019-02-13 15:33                 ` new-flex-completion-style Drew Adams
@ 2019-02-13 15:40                 ` Óscar Fuentes
  2019-02-13 17:34                   ` new-flex-completion-style Daniel Pittman
  1 sibling, 1 reply; 71+ messages in thread
From: Óscar Fuentes @ 2019-02-13 15:40 UTC (permalink / raw)
  To: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> But you didn't answer my question: what specific features of flx
>> are you looking for?
>
> IIUC Le Wang's `flx` has two main features:
> - Its scoring is supposed to be particularly good.

This is all about personal taste. For me it is great, others don't think
so. Also, it takes a while to get used to and adjust your input
according to the scoring method.

> - It's supposed to be particularly fast.

Not quite. The initial implementation was terribly slow. Then it became
usable at the expense of memory usage (caching), which is way higher
than it should be for a feature like this.

It is in my to-do list to implement the algorithm in C, either into
Emacs core or as an extension, and see if the speed improvement is good
enough to dispense with all the caching.

>> I'd be happy to implement them if I have
>> the time, but I have to understand what they are.
>
> Other than using flx.el I don't see any good way to "implement" those
> features (especially the one about speed).
>
> Of course, I have no idea if flx.el's scoring is indeed significantly
> better in practice, nor if it's significantly faster in practice either.
>
> BTW, the issue of scoring quality is not nearly as obvious as one might
> think because the score one should give to a particular match depends on
> the user's expectation and the user's expectation often depend on the
> past behavior of the tool, i.e. on the scoring.

Indeed.




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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-12 22:55               ` Dmitry Gutov
@ 2019-02-13 16:00                 ` Stefan Monnier
  2019-02-14  1:33                   ` Dmitry Gutov
  0 siblings, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2019-02-13 16:00 UTC (permalink / raw)
  To: emacs-devel

> On the one hand, yes, but it's the abstraction we already have, and it will
> allow flex to work properly at least with certain completion tables. Which
> is a win.

The problem I see with it is that performing the style-sorting via
completion-metadata or via completion-extra-properties is a hack that
works by breaking abstractions.

So, not only it will only work with some completion tables, but for that
you'll need to introduce "wrong" code in those completion tables.

I'd rather we extend the infrastructure so that completion styles can do
their own sorting.

> On the other hand, a search for display-sort-function through Emacs's
> sources seems to indicate that the design is kind of a failure: there are
> only a couple places that set it to something, and in both cases it's
> #'identity, meaning "do not re-sort".

Indeed.  Those cases *do* perform sorting, but they sort directly inside
their `all-completions` function rather than in their display-sort-function.

So yes, the design is kind of a failure, tho the alternative of having
a boolean in the metadata to say "don't sort" is no simpler.

> So minibuffer.el might want to take a cue from Company and
> company-transformers, to make this universal, we could add sorting as
> a feature of completion styles, or as a separate user option, for maximum
> flexibility.

The question is really: how/where would a completion style specify which
sorting it wants to do (based on the above-mentioned past experience,
we can assume that they'll want to do their sorting directly in
completion-all-completions and then specify "don't sort any further"),
and then how to change minibuffer.el to do that.

Currently, completion-all-completions does not return any information
about which style was used, so either we change this API so that it also
returns which style was used, or some info about the style gets added as
text-properties to influence subsequent sorting, or
completion-all-completions is changed to perform the sorting (which may
require extending its calling convention so the caller can tell it which
kind of sorting it wants).

> Now, I wouldn't say it's terrible that sort-by-occurrence-and-score would
> know specifically about flex (I don't think there's going to be a lot of
> different styles in this flavor), but sure, like you proposed in another
> email, the property can have a neutral name like completion-score.

Using scores would make it possible to combine different scoring systems
by weighting the different parts.  I'm not completely happy with the use
of text-properties, tho (e.g. ideally completion-all-completion could
return a list of pairs of the form (CANDIDATE . SCORE)).  But it has the
very significant advantage of requiring much fewer changes.


        Stefan




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

* Re: new-flex-completion-style
  2019-02-12 22:17         ` new-flex-completion-style João Távora
@ 2019-02-13 17:29           ` João Távora
  2019-02-13 18:54             ` new-flex-completion-style Stefan Monnier
  0 siblings, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-13 17:29 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

João Távora <joaotavora@gmail.com> writes:

> I'll take a look at this new batch, do the obvious fixes.  But before
> submitting anything sorting-related, I'd like Dmitry to show a patch for
> his sorting idea on top of scratch/new-flex-completion-style, try it out
> a bit and then report back here.

>> +          (setq completions
>> +                (sort completions
>> +                      (lambda (a b)
>> +                        (let ((va (get-text-property 0 'completion-style-sort-order a))
>> +                              (vb (get-text-property 0 'completion-style-sort-order b)))
>> +                          (if (and va vb) (< va vb) va)))))
>
> This will signal an error when one of the completions is the empty
> string :-(

I've removed this for now, I.e. there's absolutely no sorting yet before
we agree on who should be doing it and where.  But why would the empty
string be there anyway?

>> @@ -3056,22 +3067,41 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
>>           (let* ((pos (if point-idx (match-beginning point-idx) (match-end 0)))
>>                  (md (match-data))
>>                  (start (pop md))
>> -                (end (pop md)))
>> +                (end (pop md))
>> +                (len (length str))
>> +                (score-numerator 0)
>> +                (score-denominator 0)
>> +                (aux 0)
>> +                (update-score
>> +                 (lambda (a b)
>> +                   "Update score variables given match range (A B)."
>> +                   (setq
>> +                    score-numerator   (+ score-numerator (- b a))
>> +                    score-denominator (+ score-denominator (expt (- a aux) 1.5))
>> +                    aux              b))))
>
> I don't understand this scoring algorithm: please add a comment
> explaining it

I don't "understand" it either :-) i.e. it was developed empirically,
more or less.  But let's try to:

Consider these bad ascii(tm) schematics matching the pattern "foo" to
the strings "barfobazoquux" and "barfoobazquux":

          bar         fo             baz         o             quux
          ---         ++             ---         +             ---- 
   <start>   <match_1>  <match_1_end>   <match_n> <match_n_end>    <end>
    
    
          bar         foo             bazquux
          ---         +++             ------- 
   <start>   <match_1>   <match_1_end>       <end>
   
+++ indicates parts where the pattern matched
--- indicates parts where the pattern didn't match

The formula assigns higher scores to "better" matches. It's bound by
[0..1] and in the form of a quotient.  For the numerator, it counts the
+++.  For the denominator, it takes counts the number of --- in each
such group, exponentiates that number to a "falloff constant", adds it
to the total, adds one to the final sum, and then multiples by the
length of the string.

If no --- you get

   (length/(length * (1 + 0)) == 1

If no +++, you get 0 (but this never happens cause we pre-filtered the
matches with pcm).

The falloff constant (FC) used in the denominator is important.  A
negative falloff will value tighter matches, a positive value will value
more evenly spread out matches.  I set the constant to 1.5 some time
ago, and I haven't gone back, but perhaps it could be -1.5.

Anyway with FC=1.5 the examples above would be:

   first string  1.507%
   second string 1.197%

with FC=-1.5 it would be

   first string  15.849%
   second string 19,834%

If haven't mangled the numbers, this seems to point that -1.5 is a
better default for the constant, which shouldn't be hardcoded anyway.
On the other hand, I've been working with -1.5 for a long time now and
never had any obvious problems.  It's probably what you said elsewhere,
"good" scoring is a question of getting used to whatever the system is
doing, IOW humans learn, too.

Also note that it doesn't make any sense to compare scores between
different match lengths, only between same match lenghts at different
positions on different strings.

Anyway, what do you think?  Is this acceptable or so you have anything
better?

> (and give a meaningful name to `aux`).

Oh happy days when hackers could code "aux" and feel very smug about it.

OK, I'll call it "last-b".

>> +           (funcall update-score 0 start)
>>             (while md
>> -             (put-text-property start (pop md)
>> +             (funcall update-score start (car md))
>> +             (put-text-property start
>> +                                (pop md)
>
> The extra line-break after `start` seems spurious.

Were you expecting it to have very deep, hidden meaning?  But OK.

>
>> +           (put-text-property
>> +            0 1 'completion-pcm-commonality-score
>> +            (/ score-numerator (* len (1+ score-denominator)) 1.0) str))
>
> This will signal an error when `str` is the empty string :-(

Ooops, but that that happen?  Can an empty string be pcm-matched
by some pattern?  There's 

> BTW, maybe PCM could also use this scoring for sorting (i.e. we could
> set `completion-score` directly here)
>
>> +           (let ((score (get-text-property 0 'completion-pcm-commonality-score comp)))
>> +             (put-text-property 0 1 'completion-style-sort-order (- score) comp)
>
> This will signal an error when `comp` is the empty string :-(

Same here.



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

* Re: new-flex-completion-style
  2019-02-13 15:40                 ` new-flex-completion-style Óscar Fuentes
@ 2019-02-13 17:34                   ` Daniel Pittman
  0 siblings, 0 replies; 71+ messages in thread
From: Daniel Pittman @ 2019-02-13 17:34 UTC (permalink / raw)
  Cc: emacs-devel

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

On Wed, Feb 13, 2019 at 10:42 AM Óscar Fuentes <ofv@wanadoo.es> wrote:

> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
> >> But you didn't answer my question: what specific features of flx
> >> are you looking for?
> > - It's supposed to be particularly fast.
>
> Not quite. The initial implementation was terribly slow. Then it became
> usable at the expense of memory usage (caching), which is way higher
> than it should be for a feature like this.
>
> It is in my to-do list to implement the algorithm in C, either into
> Emacs core or as an extension, and see if the speed improvement is good
> enough to dispense with all the caching.
>

FWIW, I have a general intention with no concrete action as yet to work out
how easiest to wire up fzf for matching, since it is extremely fast,
reasonably memory efficient, and at least for me does a good heuristic job
of matching things the way I expect them to match.  The MIT license makes
it possible to use as a module, though I also considered if a "pipe" mode
akin to {i,a,hun}spell might be a smarter strategy.

https://github.com/junegunn/fzf

This was motivated by my experience with flx, which was ... not positive,
in terms of matching in the way I expected.  It was better than the ".*
between every letter" model that it replaced, however.

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

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

* Re: new-flex-completion-style
  2019-02-13 17:29           ` new-flex-completion-style João Távora
@ 2019-02-13 18:54             ` Stefan Monnier
  2019-02-13 19:13               ` new-flex-completion-style João Távora
  0 siblings, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2019-02-13 18:54 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

> I've removed this for now, I.e. there's absolutely no sorting yet before
> we agree on who should be doing it and where.  But why would the empty
> string be there anyway?

Don't know: you'd have to ask it.

> I don't "understand" it either :-)

My question wasn't to justify the idea behind the algorithm but just to
describe in words what the code is supposedly computing.  I.e. something
like what you wrote here:

> The formula assigns higher scores to "better" matches. It's bound by
> [0..1] and in the form of a quotient.  For the numerator, it counts the
> +++.  For the denominator, it takes counts the number of --- in each
> such group, exponentiates that number to a "falloff constant", adds it
> to the total, adds one to the final sum, and then multiples by the
> length of the string.

Making sure I understand:
- "counts the +++" will always return the length of the pattern, right?
  So this is used just to normalize the result to ]0..1].
- if the falloff constant is 0, the denominator is the number of places
  where a "star" had to be added (plus one).  And if the falloff
  constant is positive it prefers more insertions of shorter text
  chunks over fewer insertions of longer text chunks, and if it's
  negative it oddly prefers longer insertions over shorter ones.

> Anyway, what do you think?  Is this acceptable or so you have anything
> better?

Fine by me (tho maybe I wouldn't count the final "---", to more
closely match [no pun intended] the usual prefix completion).

FWIW, in my "forgive" completion style I used the equivalent of
a falloff constant of 0 (i.e. I didn't care about the length of the
"---" but only about their number).

> OK, I'll call it "last-b".

It'll be eternally indebted to you.

>>> +           (funcall update-score 0 start)
>>>             (while md
>>> -             (put-text-property start (pop md)
>>> +             (funcall update-score start (car md))
>>> +             (put-text-property start
>>> +                                (pop md)
>>
>> The extra line-break after `start` seems spurious.
> Were you expecting it to have very deep, hidden meaning?  But OK.

I was actually bothered by the fact that the `diff` indicates a change
on an expression that's actually not modified (other than by insertion
of a line-break).  Anal retentiveness for ever!

>>> +           (put-text-property
>>> +            0 1 'completion-pcm-commonality-score
>>> +            (/ score-numerator (* len (1+ score-denominator)) 1.0) str))
>>
>> This will signal an error when `str` is the empty string :-(
>
> Ooops, but that that happen?  Can an empty string be pcm-matched
> by some pattern?  There's 

I think it can if the pattern is empty.  So maybe all those
put/get-text-property are fine if you make sure this code is never even
called when the pattern is empty.

BTW, the patch below seems to improve the behavior (e.g. it lets
`.../emacs/cfi TAB` complete to `.../emacs/config` as it should since
all remaining matches also match "config").


        Stefan


diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 8ea70b14f1..f5171bb2d0 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -3434,22 +3434,7 @@ completion-flex-try-completion
                 #'completion-flex--make-flex-pattern)))
     (if minibuffer-completing-file-name
         (setq all (completion-pcm--filename-try-filter all)))
-    (cond ((not (consp all))
-           all)
-          ((not (consp (cdr all))) ; single completion
-           (if (equal string (car all))
-               t
-             (cons (car all) (length (car all)))))
-          (t
-           ;; If more than one completion, try some "merging".
-           ;; Meaning add as much as possible to the user's
-           ;; pattern without losing any possible matches in
-           ;; `all'.  If that fails, leave user input
-           ;; untouched.
-           (let ((probe (completion-pcm--merge-try pattern all prefix suffix)))
-             (if (stringp probe)
-                 (cons probe (length probe))
-               (cons string point)))))))
+    (completion-pcm--merge-try pattern all prefix suffix)))
 
 (defun completion-flex-all-completions (string table pred point)
   "Get flex-completions of STRING in TABLE, given PRED and POINT."



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

* Re: new-flex-completion-style
  2019-02-13 18:54             ` new-flex-completion-style Stefan Monnier
@ 2019-02-13 19:13               ` João Távora
  2019-02-14 13:36                 ` new-flex-completion-style Stefan Monnier
  0 siblings, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-13 19:13 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

On Wed, Feb 13, 2019 at 6:54 PM Stefan Monnier <monnier@iro.umontreal.ca> wrote:

> Making sure I understand:
> - "counts the +++" will always return the length of the pattern, right?
>   So this is used just to normalize the result to ]0..1].
> - if the falloff constant is 0, the denominator is the number of places
>   where a "star" had to be added (plus one).  And if the falloff
>   constant is positive it prefers more insertions of shorter text
>   chunks over fewer insertions of longer text chunks, and if it's
>   negative it oddly prefers longer insertions over shorter ones.

Yes and Yes.  The length of the pattern but probably not as
calculated by (length pattern).

I don't think it's odd.  I call the former "scattered match"
and the latter a "tighter match".  For the particular way I
remember symbol names, files names, etc, it's probably a good
idea, since I can almost always remember a full word in the name.

But sure enough I've had it configured for "scattered match"
all along and I didn't know!

> > Anyway, what do you think?  Is this acceptable or so you have anything
> > better?
>
> Fine by me (tho maybe I wouldn't count the final "---", to more
> closely match [no pun intended] the usual prefix completion).

Maybe this should be configurable, but in general I don't
think staying close to prefix completion should be a
goal, since this is a completely different game.  IOW, valuing
a string ends/beginning differently makes little sense in flex.

> >>> +           (put-text-property
> >>> +            0 1 'completion-pcm-commonality-score
> >>> +            (/ score-numerator (* len (1+ score-denominator)) 1.0) str))
> >>
> >> This will signal an error when `str` is the empty string :-(
> >
> > Ooops, but that that happen?  Can an empty string be pcm-matched
> > by some pattern?  There's
>
> I think it can if the pattern is empty.  So maybe all those
> put/get-text-property are fine if you make sure this code is never even
> called when the pattern is empty.

OK, I'll figure something out.

> BTW, the patch below seems to improve the behavior (e.g. it lets
> `.../emacs/cfi TAB` complete to `.../emacs/config` as it should since
> all remaining matches also match "config").

cool!



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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-13 16:00                 ` Stefan Monnier
@ 2019-02-14  1:33                   ` Dmitry Gutov
  2019-02-19 16:10                     ` Stefan Monnier
  0 siblings, 1 reply; 71+ messages in thread
From: Dmitry Gutov @ 2019-02-14  1:33 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

On 13.02.2019 19:00, Stefan Monnier wrote:
> So, not only it will only work with some completion tables, but for that
> you'll need to introduce "wrong" code in those completion tables.

Since we seem to want to redo completion tables in a major way anyway, I 
wouldn't worry about that too much, as long as the result is functional.

> I'd rather we extend the infrastructure so that completion styles can do
> their own sorting.

That's one option. Another option, which I've mentioned before, is to 
create an indirection for sorting functions via the completion table's 
category. Similar to the one that completions styles have.

> So yes, the design is kind of a failure, tho the alternative of having
> a boolean in the metadata to say "don't sort" is no simpler.

It's simpler but more ad-hoc, to be sure.

> The question is really: how/where would a completion style specify which
> sorting it wants to do (based on the above-mentioned past experience,
> we can assume that they'll want to do their sorting directly in
> completion-all-completions and then specify "don't sort any further"),
> and then how to change minibuffer.el to do that.

As we can see from the patch, using text properties (and actually sort 
later) also seems like a viable approach.

> Currently, completion-all-completions does not return any information
> about which style was used, so either we change this API so that it also
> returns which style was used, or some info about the style gets added as
> text-properties to influence subsequent sorting, or
> completion-all-completions is changed to perform the sorting (which may
> require extending its calling convention so the caller can tell it which
> kind of sorting it wants).

The category-based approach should circumvent that problem.

With this approach, completion styles don't indicate sorting, and 
whatever entity did set up the completion style to be used (the user, a 
configuration package, etc) would need to set up both completion styles 
and sorting functions to match.

> Using scores would make it possible to combine different scoring systems
> by weighting the different parts.  I'm not completely happy with the use
> of text-properties, tho (e.g. ideally completion-all-completion could
> return a list of pairs of the form (CANDIDATE . SCORE)).  But it has the
> very significant advantage of requiring much fewer changes.

I think text properties are fine here. In Company, we use them for 
various bits of information.

Further, if your goal is to combine different scoring systems, it'll 
probably be required to assign different scores (from different systems) 
to each completion. The form (CANDIDATE . SCORE) won't cut it, but text 
properties should.



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

* Re: new-flex-completion-style
  2019-02-13 19:13               ` new-flex-completion-style João Távora
@ 2019-02-14 13:36                 ` Stefan Monnier
  2019-02-14 13:55                   ` new-flex-completion-style João Távora
  0 siblings, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2019-02-14 13:36 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

> I don't think it's odd.  I call the former "scattered match"
> and the latter a "tighter match".

Don't you find it odd that "foo" gives a better score to
"fotttttttttttttttto" than to "foto" ?

[ Given them the same score sounds acceptable, tho.  ]


        Stefan



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

* Re: new-flex-completion-style
  2019-02-14 13:36                 ` new-flex-completion-style Stefan Monnier
@ 2019-02-14 13:55                   ` João Távora
  2019-02-14 14:59                     ` new-flex-completion-style João Távora
  0 siblings, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-14 13:55 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

On Thu, Feb 14, 2019 at 1:36 PM Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>
> > I don't think it's odd.  I call the former "scattered match"
> > and the latter a "tighter match".
>
> Don't you find it odd that "foo" gives a better score to
> "fotttttttttttttttto" than to "foto" ?

Perhaps.  But as it stands it doesn't make sense to
compare scores across different length strings.

It does make sense to compare the score between
foo's matches of foot and foto.

> [ Given them the same score sounds acceptable, tho.  ]

Feel free to add some kind of normalization to the function
if you can come up with it.  Or come up with another function
entirely.  As I said, a function that measures the distance
in "boring editing operations" between the pattern and the target
would be a nicer measure.

-- 
João Távora



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

* Re: new-flex-completion-style
  2019-02-14 13:55                   ` new-flex-completion-style João Távora
@ 2019-02-14 14:59                     ` João Távora
  2019-02-14 15:28                       ` new-flex-completion-style Óscar Fuentes
  2019-02-14 15:35                       ` new-flex-completion-style Daniel Pittman
  0 siblings, 2 replies; 71+ messages in thread
From: João Távora @ 2019-02-14 14:59 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

On Thu, Feb 14, 2019 at 1:55 PM João Távora <joaotavora@gmail.com> wrote:
>
> On Thu, Feb 14, 2019 at 1:36 PM Stefan Monnier <monnier@iro.umontreal.ca> wrote:
> >
> > > I don't think it's odd.  I call the former "scattered match"
> > > and the latter a "tighter match".
> >
> > Don't you find it odd that "foo" gives a better score to
> > "fotttttttttttttttto" than to "foto" ?
>
> Perhaps.  But as it stands it doesn't make sense to
> compare scores across different length strings.
>
> It does make sense to compare the score between
> foo's matches of foot and foto.
>
> > [ Given them the same score sounds acceptable, tho.  ]
>
> Feel free to add some kind of normalization to the function
> if you can come up with it.  Or come up with another function
> entirely.  As I said, a function that measures the distance
> in "boring editing operations" between the pattern and the target
> would be a nicer measure.

I've been experimenting with a simpler function that just counts the
number of "holes" and the length of those holes separately
in the denominator. The numerator is the same and a perfect
match is still a 1. It seems to fare better for your cases. For foo

Eventually we could weight the number and length
of holes differently so we can get this:

score(foo,barfoobaz) > score(foo,fabrobazo) >
score(foo,fotttttttttttttttttttttto)

Which would be nicer, I think.

João



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

* Re: new-flex-completion-style
  2019-02-14 14:59                     ` new-flex-completion-style João Távora
@ 2019-02-14 15:28                       ` Óscar Fuentes
  2019-02-14 15:44                         ` new-flex-completion-style Drew Adams
  2019-02-14 16:21                         ` new-flex-completion-style João Távora
  2019-02-14 15:35                       ` new-flex-completion-style Daniel Pittman
  1 sibling, 2 replies; 71+ messages in thread
From: Óscar Fuentes @ 2019-02-14 15:28 UTC (permalink / raw)
  To: emacs-devel

João Távora <joaotavora@gmail.com> writes:

> Eventually we could weight the number and length
> of holes differently so we can get this:
>
> score(foo,barfoobaz) > score(foo,fabrobazo) >
> score(foo,fotttttttttttttttttttttto)
>
> Which would be nicer, I think.

My experience on this type of discussions about flx says that you should
design a scoring algorithm based on some generic, human-related
heuristic that makes sense to you and stick to it. You will hear lots of
complaints by those that dislike the system, showing specific examples
that demonstrate "obvious" deficiencies on your approach. But it is
impossible to create something that makes everybody happy.

As long as Emacs can't read our minds, there will be no good-enough
completion mechanism. And even then... we are dealing with the Emacs
user base, you know :-)




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

* Re: new-flex-completion-style
  2019-02-14 14:59                     ` new-flex-completion-style João Távora
  2019-02-14 15:28                       ` new-flex-completion-style Óscar Fuentes
@ 2019-02-14 15:35                       ` Daniel Pittman
  2019-02-14 16:12                         ` new-flex-completion-style João Távora
  2019-02-14 16:34                         ` new-flex-completion-style Drew Adams
  1 sibling, 2 replies; 71+ messages in thread
From: Daniel Pittman @ 2019-02-14 15:35 UTC (permalink / raw)
  To: João Távora; +Cc: Stefan Monnier, emacs-devel

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

On Thu, Feb 14, 2019 at 10:16 AM João Távora <joaotavora@gmail.com> wrote:

> On Thu, Feb 14, 2019 at 1:55 PM João Távora <joaotavora@gmail.com> wrote:
> > On Thu, Feb 14, 2019 at 1:36 PM Stefan Monnier <monnier@iro.umontreal.ca>
> wrote:
> > >
> > > > I don't think it's odd.  I call the former "scattered match"
> > > > and the latter a "tighter match".
> > >
> > > Don't you find it odd that "foo" gives a better score to
> > > "fotttttttttttttttto" than to "foto" ?
> >
> > Perhaps.  But as it stands it doesn't make sense to
> > compare scores across different length strings.
> >
> > It does make sense to compare the score between
> > foo's matches of foot and foto.
> >
> > > [ Given them the same score sounds acceptable, tho.  ]
> >
> > Feel free to add some kind of normalization to the function
> > if you can come up with it.  Or come up with another function
> > entirely.  As I said, a function that measures the distance
> > in "boring editing operations" between the pattern and the target
> > would be a nicer measure.
>

The Levenshtein distance and close variants generally do a reasonable job
of approximating human expectations, yes.  Close variants (eg: only
delete/insert, no mutate) also work well.

The cost of building the Levenshtein edit distance matrix for picking or
ordering candidates is quite high, though;
https://en.wikipedia.org/wiki/Approximate_string_matching gives a good
summary, and you really don't want to use the most naive option if you can
avoid it.  Computation costs go through the roof very fast; the cost is
roughly proportional to the length of the candidate cubed, using the brute
force approach.

The other shortfall of using only edit distance is that most of the time
people expect to front-weight the search: you may have a closer edit
distance match later in the string, but people usually want a less exact
match, closer to the start, intuitively.


> I've been experimenting with a simpler function that just counts the
> number of "holes" and the length of those holes separately
> in the denominator. The numerator is the same and a perfect
> match is still a 1. It seems to fare better for your cases. For foo
>

I'd very, very strongly encourage y'all to take a look at the existing work
on the problem, not least because of the algorithmic complexity costs when
you apply this to a large corpus of candidates.  Consider, for example,
completion over the set of all defined symbols in Emacs, which is ~ 55,000
candidates, and IIRC I calculated the average length to 9 characters, so
brute force matching would be be on the order of 40 **million** comparisons
for the first pattern character, though thankfully dropping fast as you
eliminate non-matching candidates entirely.  (Raw comparisons, accounting
for all possible matches in all possible candidate, of that pattern, so
each candidate gets $length / $pattern_length comparisons performed.)

Anyway, the point is: this is an area where serious study has been
invested, and I strongly urge you to take advantage of that, rather than
trying to reinvent this surprisingly complex wheel.  This isn't simple to
do, and it definitely isn't simple to do in a high performance way.

PS: whatever else you do, make it trivial to configure what function is
used for ordering the candidate results.  That matters far more that the
details of the default match / order choice, because it allows easy
innovation over time.

PPS: the best modern tools seem to be derived from the problem of genome
sequence matching, but heuristics are definitely helpful too.  Again, fzf
is the best version of that I have found.

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

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

* RE: new-flex-completion-style
  2019-02-14 15:28                       ` new-flex-completion-style Óscar Fuentes
@ 2019-02-14 15:44                         ` Drew Adams
  2019-02-14 16:21                         ` new-flex-completion-style João Távora
  1 sibling, 0 replies; 71+ messages in thread
From: Drew Adams @ 2019-02-14 15:44 UTC (permalink / raw)
  To: Óscar Fuentes, emacs-devel

> As long as Emacs can't read our minds, there will be no good-enough
> completion mechanism. And even then... we are dealing with the Emacs
> user base, you know :-)

Yes.  Not only are users different but they use different
contexts, and the same user has different preferences in
different contexts.

And even when user A's preference for a particular context
is Preference-AA, s?he can sometimes want to change things
dynamically - in this case, change sort ordering.

A default, context-specific user preference-driven sort
order is fine, but a user can still want to change orders
on the fly.  That can happen, among other reasons, due to
what s?he is currently typing as an input pattern.



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

* Re: new-flex-completion-style
  2019-02-14 15:35                       ` new-flex-completion-style Daniel Pittman
@ 2019-02-14 16:12                         ` João Távora
  2019-02-14 16:16                           ` new-flex-completion-style João Távora
  2019-02-14 16:34                         ` new-flex-completion-style Drew Adams
  1 sibling, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-14 16:12 UTC (permalink / raw)
  To: Daniel Pittman; +Cc: Stefan Monnier, emacs-devel

Daniel Pittman <slippycheeze@google.com> writes:

>  > Feel free to add some kind of normalization to the function
>  > if you can come up with it.  Or come up with another function
>  > entirely.  As I said, a function that measures the distance
>  > in "boring editing operations" between the pattern and the target
>  > would be a nicer measure.
>
> The Levenshtein distance and close variants generally do a reasonable
> job of approximating human expectations, yes.  Close variants (eg:
> only delete/insert, no mutate) also work well.

`string-distance' in Emacs is the Levenshtein distance and it does a
terrible job.  it says "foo" is as close to "foobar" as it is to
"fboror", which is not acceptable.  And neither is a variant like
Damerau–Levenshtein.  I could possibly use a variant that computes
things in "elementary boring editing operations", which includes moves.

There is a fundamental misunderstanding on your side I think.  The
distance formulae exist to solve another class of problems, which
include comparing strings of characters where one is _not_ a subsequence
of the other (a subsequence being a not-necessarily-contiguous in-order
subset of elements).  Often these problems want to compute not only the
distance _and_ but also the set of insertion, deletions, transposition
that bring a string to another.  This is why they are slow.  But they do
enable fancy things like auto-correct.

Those occur in the super well-studied high-tech fields that you suggest
I'm ignorant of.  And while I'm certainly no expert on the matter, I do
think none of that matters here.  Emacs uses things like "string-match"
to tell if a string matches another.  If it doesn't it doesn't, and
that's OK for "flex".

If, for some reason, the regexp starts being slow for flex-matching,
since it writes a regexp like ".*f.*o.*o.*", then it's very easy to
optimize these flex patterns in C directly.  A greedy implementation
(which is fine) will be just O(n).

So I don't know what speed problems you are referring to.  Neither is it
clear to me what fields your "fzf" suggestion would be "blazingly fast"
(as it self-describes itself) and/or how plugging it into Emacs would
solve anything.

In short for "flex", at least for the "flex" I'm interested in, Emacs
can separate the matching and scoring problem, so your worries do not
make sense.  This "flex" style even already exists in Emacs, but only in
ido.el.  That's what I'm trying to being to other areas of Emacs.

On the other hand, if you're writing an "autocorrection" completion
style then yes, these things could start making sense.  But I'm not
writing that.

> PPS: the best modern tools seem to be derived from the problem of
> genome sequence matching, but heuristics are definitely helpful too.
> Again, fzf is the best version of that I have found.

Does it autocorrect?  If yes, it might be a good choice for that other
completion style you may be describing.  It's hardly a good choice for
"flex".

João



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

* Re: new-flex-completion-style
  2019-02-14 16:12                         ` new-flex-completion-style João Távora
@ 2019-02-14 16:16                           ` João Távora
  0 siblings, 0 replies; 71+ messages in thread
From: João Távora @ 2019-02-14 16:16 UTC (permalink / raw)
  To: Daniel Pittman; +Cc: Stefan Monnier, emacs-devel

João Távora <joaotavora@gmail.com> writes:

> subset of elements).  Often these problems want to compute not only the
> distance _and_ but also the set of insertion, deletions, transposition
           ^^^^^
Doh. Messed up the grammar there.  To be clear I meant these
problems want the distance _and_ the operations that transform one
string into another.

João



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

* Re: new-flex-completion-style
  2019-02-14 15:28                       ` new-flex-completion-style Óscar Fuentes
  2019-02-14 15:44                         ` new-flex-completion-style Drew Adams
@ 2019-02-14 16:21                         ` João Távora
  1 sibling, 0 replies; 71+ messages in thread
From: João Távora @ 2019-02-14 16:21 UTC (permalink / raw)
  To: Óscar Fuentes; +Cc: emacs-devel

On Thu, Feb 14, 2019 at 3:33 PM Óscar Fuentes <ofv@wanadoo.es> wrote:
>
> João Távora <joaotavora@gmail.com> writes:
>
> > Eventually we could weight the number and length
> > of holes differently so we can get this:
> >
> > score(foo,barfoobaz) > score(foo,fabrobazo) >
> > score(foo,fotttttttttttttttttttttto)
> >
> > Which would be nicer, I think.
>
> My experience on this type of discussions about flx says that you should
> design a scoring algorithm based on some generic, human-related
> heuristic that makes sense to you and stick to it. You will hear lots of
> complaints by those that dislike the system, showing specific examples
> that demonstrate "obvious" deficiencies on your approach. But it is
> impossible to create something that makes everybody happy.

I agree with all your arguments, but I do think Stefan has a pretty
good point in that example.  There's no reason not to heed it.

> As long as Emacs can't read our minds, there will be no good-enough
> completion mechanism. And even then... we are dealing with the Emacs
> user base, you know :-)

Indeed...



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

* RE: new-flex-completion-style
  2019-02-14 15:35                       ` new-flex-completion-style Daniel Pittman
  2019-02-14 16:12                         ` new-flex-completion-style João Távora
@ 2019-02-14 16:34                         ` Drew Adams
  2019-02-14 17:03                           ` new-flex-completion-style João Távora
  1 sibling, 1 reply; 71+ messages in thread
From: Drew Adams @ 2019-02-14 16:34 UTC (permalink / raw)
  To: Daniel Pittman, João Távora; +Cc: Stefan Monnier, emacs-devel

> The Levenshtein distance and close variants generally do
> a reasonable job of approximating human expectations, yes.
> Close variants (eg: only delete/insert, no mutate) also
> work well.
>
> The cost of building the Levenshtein edit distance matrix
> for picking or ordering candidates is quite high, though; ...
> gives a good summary, and you really don't want to use the
> most naive option if you can avoid it.  Computation costs
> go through the roof very fast; the cost is roughly
> proportional to the length of the candidate cubed, using the
> brute force approach.
>
> The other shortfall of using only edit distance is that most
> of the time people expect to front-weight the search: you
> may have a closer edit distance match later in the string,
> but people usually want a less exact match, closer to the
> start, intuitively.
>
> > I've been experimenting with a simpler function that just
> > counts the number of "holes" and the length of those holes
> > separately in the denominator. The numerator is the same
> > and a perfect match is still a 1. It seems to fare better
> > for your cases. For foo
>
> I'd very, very strongly encourage y'all to take a look at
> the existing work on the problem, not least because of the
> algorithmic complexity costs when you apply this to a large
> corpus of candidates.  Consider, for example, completion
> over the set of all defined symbols in Emacs, which is
> ~ 55,000 candidates, and IIRC I calculated the average
> length to 9 characters, so brute force matching would be
> be on the order of 40 **million** comparisons for the first
> pattern character, though thankfully dropping fast as you
> eliminate non-matching candidates entirely.  (Raw comparisons,
> accounting for all possible matches in all possible candidate,
> of that pattern, so each candidate gets
> $length / $pattern_length comparisons performed.)
>
> Anyway, the point is: this is an area where serious study
> has been invested, and I strongly urge you to take advantage
> of that, rather than trying to reinvent this surprisingly
> complex wheel.  This isn't simple to do, and it definitely
> isn't simple to do in a high performance way.
>
> PS: whatever else you do, make it trivial to configure what
> function is used for ordering the candidate results.  That
> matters far more that the details of the default match /
> order choice, because it allows easy innovation over time.
>
> PPS: the best modern tools seem to be derived from the
> problem of genome sequence matching, but heuristics are
> definitely helpful too.  Again, fzf is the best version of
> that I have found.

All good info; thanks.  +1 for (1) emphasizing the cost
in general/naive cases and for (2) saying "make it trivial
to configure" the sort order (function).

João's (first) reply to you, saying that an interactive
Emacs context (e.g. completion) has needs that can be a
bit different, is also relevant.

FWIW, here is how Icicles uses (2 kinds of) Levenshtein
matching:

https://www.emacswiki.org/emacs/Icicles_-_Completion_Methods_and_Styles#LevenshteinCompletion

And here is how it uses a Jaro-Winkler matching:

https://www.emacswiki.org/emacs/Icicles_-_Completion_Methods_and_Styles#JaroWinklerMatchCompletion



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

* Re: new-flex-completion-style
  2019-02-14 16:34                         ` new-flex-completion-style Drew Adams
@ 2019-02-14 17:03                           ` João Távora
  2019-02-14 17:49                             ` new-flex-completion-style Drew Adams
  0 siblings, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-14 17:03 UTC (permalink / raw)
  To: Drew Adams; +Cc: Daniel Pittman, Stefan Monnier, emacs-devel

On Thu, Feb 14, 2019 at 4:34 PM Drew Adams <drew.adams@oracle.com> wrote:
> João's (first) reply to you, saying that an interactive
> Emacs context (e.g. completion) has needs that can be a
> bit different, is also relevant.
>
> FWIW, here is how Icicles uses (2 kinds of) Levenshtein
> matching:
>
> https://www.emacswiki.org/emacs/Icicles_-_Completion_Methods_and_Styles#LevenshteinCompletion
>
> And here is how it uses a Jaro-Winkler matching:
>
> https://www.emacswiki.org/emacs/Icicles_-_Completion_Methods_and_Styles#JaroWinklerMatchCompletion

Earlier, I forgot to tell you that I had visited your page (this is
where I learned the "scatter" alias) and for the record I'm
(re)implementing your "Scatter-Match (Flex) Completion" thing:

  https://www.emacswiki.org/emacs/Icicles_-_Completion_Methods_and_Styles#toc8

Tho the equivalent regexp I'm using here is ".*a.*b.*c.*" not "a.*b.*c"
as your page states.  Anyway, what kind of scoring, if any, do you
use for sorting the matches to that particular completion style?

João









-- 
João Távora



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

* RE: new-flex-completion-style
  2019-02-14 17:03                           ` new-flex-completion-style João Távora
@ 2019-02-14 17:49                             ` Drew Adams
  2019-02-14 18:30                               ` new-flex-completion-style João Távora
  0 siblings, 1 reply; 71+ messages in thread
From: Drew Adams @ 2019-02-14 17:49 UTC (permalink / raw)
  To: João Távora; +Cc: Daniel Pittman, Stefan Monnier, emacs-devel

> Earlier, I forgot to tell you that I had visited your page (this is
> where I learned the "scatter" alias) and for the record I'm
> (re)implementing your "Scatter-Match (Flex) Completion" thing:
> 
>   https://urldefense.proofpoint.com/v2/url?u=https-
> 3A__www.emacswiki.org_emacs_Icicles-5F-2D-5FCompletion-5FMethods-5Fand-
> 5FStyles-
> 23toc8&d=DwIFaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=kI3P6lj
> Gv6CTHIKju0jqInF6AOwMCYRDQUmqX22rJ98&m=27ypntXsw7g-l7Nfe2JaeDgtsetIas-
> Qq30T2GdC_58&s=C4LaFFUPksrZ2l6B04Ovt4T-kt8Tz4xwZN2EO-z8iuk&e=
> 
> Tho the equivalent regexp I'm using here is ".*a.*b.*c.*" not "a.*b.*c"
> as your page states.

With Icicles regexp matching for completion you don't need the
initial `.*'.

> Anyway, what kind of scoring, if any, do you use for sorting
> the matches to that particular completion style?

I don't use any scoring for scatter matching.

Icicle users usually have a bunch of sort orders they can use
(which set can depend on the particular command and on user
preferences).  One of them is "by flx score", which uses a
score provided by `flx.el'.  With scatter matching users can
use any sort order allowed for the given command.

This page has a list of most of the sort orders available
by default:

https://www.emacswiki.org/emacs/Icicles_-_Sorting_Candidates

When completing, in the mode-line of `*Completions*' you see
the number of matching candidates (e.g. 925), the match
method (e.g. `scatter completion'), and the sort order (e.g.
`by flx score').

---

[The two Icicles matchings using (1) `fuzzy-match.el' and
(2) Swank fuzzy matching each impose a sort order - users
can't switch sort orders when they use these two kinds of
matching.

These two are the kinds of fuzzy matching available for
"prefix" Icicles completion, i.e., using `TAB'.  The others,
such as scatter and levenshtein, are available for "apropos"
completion, i.e., using `S-TAB'.]





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

* Re: new-flex-completion-style
  2019-02-14 17:49                             ` new-flex-completion-style Drew Adams
@ 2019-02-14 18:30                               ` João Távora
  2019-02-14 19:20                                 ` new-flex-completion-style Drew Adams
  0 siblings, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-14 18:30 UTC (permalink / raw)
  To: Drew Adams; +Cc: Daniel Pittman, Stefan Monnier, emacs-devel

On Thu, Feb 14, 2019 at 5:49 PM Drew Adams <drew.adams@oracle.com> wrote:
> > Tho the equivalent regexp I'm using here is ".*a.*b.*c.*" not "a.*b.*c"
> > as your page states.
> With Icicles regexp matching for completion you don't need the
> initial `.*'.

Let me state it another way.  Does your system match "foo"
to "barfoobaz" or does it fail?  If so, then I think your
_equivalent_ regexp is probably .*f.*o.*o.*

> I don't use any scoring for scatter matching.
> Icicle users usually have a bunch of sort orders they can use

Right. Which one do you use, when you use scatter-matching?

João



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

* RE: new-flex-completion-style
  2019-02-14 18:30                               ` new-flex-completion-style João Távora
@ 2019-02-14 19:20                                 ` Drew Adams
  2019-02-14 20:54                                   ` new-flex-completion-style João Távora
  0 siblings, 1 reply; 71+ messages in thread
From: Drew Adams @ 2019-02-14 19:20 UTC (permalink / raw)
  To: João Távora; +Cc: Daniel Pittman, Stefan Monnier, emacs-devel

> > > Tho the equivalent regexp I'm using here is ".*a.*b.*c.*" not
> > > "a.*b.*c" as your page states.
> >
> > With Icicles regexp matching for completion you don't need the
> > initial `.*'.

And you don't need the final `.*', I should have added
(didn't notice it in your pattern).

It sounds like you're always trying to match all chars
in a line.  I'm not.  I'm not dealing with lines, in
general.  I'm matching a pattern against a string, in
general.
 
> Let me state it another way.  Does your system match "foo"
> to "barfoobaz" or does it fail?

It matches.

> If so, then I think your _equivalent_ regexp is probably .*f.*o.*o.*

(string-match-p "f.*o.*o" "barfoobaz") => 3

Scatter-matching is used with "apropos" completion.
It's just regexp completion, using the substituted
regexp.  Substituting regexp `f.*o.*o' for input
`foo' just does the above `string-match-p'.

> > I don't use any scoring for scatter matching.
> > Icicle users usually have a bunch of sort orders they can use
> 
> Right. Which one do you use, when you use scatter-matching?

Any of them.  Depends on what I'm doing and what I want.
Scatter-matching is typically not specific to particular
contexts, and thus to any context-specific sort orders.

Can you see that some of the following predefined orders
might be advantageous in particular contexts/use cases?
Can you see that whether matching is scatter, regexp,
basic prefix, or others, any of the following can be
useful?

(As I said, there are a couple of fuzzy-match methods
that impose their own sort order, but most do not.
Similarly, a few commands impose their own sort order -
they don't allow re-sorting.)

some of the Icicles sort orders that exist by default:

General:

 alphabetical
 case-insensitive
 by last use as input
 by previous use alphabetically

Color completion:

 by color name (colors)
 by hue (colors)
 by purity/saturation (colors)
 by brightness/value/luminance (colors)
 by all HSV components, in order (colors)
 by HSV distance from a base color (colors)
 by amount of red (colors)
 by amount of green (colors)
 by amount of blue (colors)
 by all RGB components, in order (colors)
 by RGB distance from a base color (colors)

Key completion:

 by key name, prefix keys first (keys)
 by key name, local bindings first (keys)

Command completion:

 by command name (commands)
 by abbrev frequency (commands)

Buffer-name completion:

 by buffer size (buffer names)
 *…* buffers last (buffer names)
 by major mode name (buffer names)
 by mode-line mode name (buffer names)
 by file/process name (buffer names)

File-name completion:

 by last file modification time (file names)
 by file type (extension) (file names)
 by directories first or last (file names)

Other:

 in book order (Info)
 special candidates first
 proxy candidates first
 extra candidates first
 by second multi-completion part (multi-completions)

 turned OFF (does not sort at all) 




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

* Re: new-flex-completion-style
  2019-02-14 19:20                                 ` new-flex-completion-style Drew Adams
@ 2019-02-14 20:54                                   ` João Távora
  2019-02-14 22:03                                     ` new-flex-completion-style Drew Adams
  0 siblings, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-14 20:54 UTC (permalink / raw)
  To: Drew Adams; +Cc: Daniel Pittman, Stefan Monnier, emacs-devel

On Thu, Feb 14, 2019 at 7:20 PM Drew Adams <drew.adams@oracle.com> wrote:

> > If so, then I think your _equivalent_ regexp is probably .*f.*o.*o.*
> (string-match-p "f.*o.*o" "barfoobaz") => 3

Right, sorry for the confusion.

> Can you see that some of the following predefined orders
> might be advantageous in particular contexts/use cases?
> Can you see that whether matching is scatter, regexp,
> basic prefix, or others, any of the following can be
> useful?

No, I can't. That's probably input for the style vs category vs table
vs UI debate, where I'd rather, like Stefan, go for the path of
least redesign which seems to plug sorting to a style.

Perhaps I'll change my opinion with specific use cases where
using my proposed sorting function with flex isn't a good
solution.

Thanks anyway,
João

João Távora



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

* RE: new-flex-completion-style
  2019-02-14 20:54                                   ` new-flex-completion-style João Távora
@ 2019-02-14 22:03                                     ` Drew Adams
  2019-02-14 22:06                                       ` new-flex-completion-style João Távora
  2019-02-14 22:22                                       ` new-flex-completion-style Stefan Monnier
  0 siblings, 2 replies; 71+ messages in thread
From: Drew Adams @ 2019-02-14 22:03 UTC (permalink / raw)
  To: João Távora; +Cc: Daniel Pittman, Stefan Monnier, emacs-devel

> > Can you see that some of the following predefined orders
> > might be advantageous in particular contexts/use cases?
> > Can you see that whether matching is scatter, regexp,
> > basic prefix, or others, any of the following can be
> > useful?
> 
> No, I can't.

Seriously?  You can't imagine that someone completing
buffer names might want to (sometimes) put more
recently used buffer names before others for better
visibility or for quicker cycling access?

You can't imagine anyone ever wanting a different
order of candidates than what you would define based
on match scores?

Match scores are tightly linked to sort order only
for certain kinds of matching.  And even then such
an ordering is typically "all other things being
equal", i.e., for lack of any more meaningful sort.

What you say sounds bizarre to me.  Different contexts
can call for different sort orders.  And different
commands provide different contexts, as do different
user preferences.

Take Info nodes for `g', for instance.  Can't you
imagine that sometimes you might want to see completion
matches in book order, and other times in order of the
dates of your past visits, and other times in order of
the number of your visits, and other times in
alphabetical order?

And even for, say, number of visits, can you imagine
that sometimes you want to visit nodes that you've
visited a lot, and other times you might want to visit
nodes that you've never visited?

Do you really feel that one size (one order) fits all?

> That's probably input for the style vs category vs table
> vs UI debate, where I'd rather, like Stefan, go for the path of
> least redesign which seems to plug sorting to a style.

My own opinion on that is that what's important is that
a user be able to control such things on the fly.  Sort
order, for example: be able to immediately change it by
hitting a key while completing.

AFAIK (I could be wrong; I don't bother following this
evolution), vanilla Emacs doesn't even give users a way
to change completion styles on the fly.  Adding a sort
order or a category or whatever else to a style definition
doesn't help if a user can't turn on a dime, switching
to a different style.

What's more: As long as accommodation is attempted by
_combining_ such (pretty independent) things: sort order,
match method, categories, users will lose.

Why?  Because even if you give them a way to quickly
switch styles they can't switch parts of a style.  With
3 axes (order, matching, category) and with, say, 4
choices per axis, that's a lot of possible combinations.

To allow a user to pick any of those combinations s?he'd
need a style for each combination!  And then s?he'd have
to be able to remember them all and keep track of them.

No, the right approach, I think, is to let users move
at will, fluidly, along any such axis, to get any
combination anytime.  All a user needs to remember in
that case is a key to choose something on a given axis.

But no, I'm not trying to design or redesign vanilla
Emacs completion.  I tried to communicate all of this
long ago, and several times.  No takers.  So be it.
Been there; done that.  (I have, however, seen several
of the ideas picked up by other completion systems:
Helm, Ivy, even Ido and Icomplete in some cases.)

> Perhaps I'll change my opinion with specific use cases where
> using my proposed sorting function with flex isn't a good
> solution.

You should be able to change from, or to, it on the fly,
when you find that useful.  Then, being a believer in
your thing, you would set it as your preferred default
behavior.  But you'd still be able to pop out of the
box when you felt like it, and _without_ customizing
some preference and then starting over.



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

* Re: new-flex-completion-style
  2019-02-14 22:03                                     ` new-flex-completion-style Drew Adams
@ 2019-02-14 22:06                                       ` João Távora
  2019-02-14 22:22                                       ` new-flex-completion-style Stefan Monnier
  1 sibling, 0 replies; 71+ messages in thread
From: João Távora @ 2019-02-14 22:06 UTC (permalink / raw)
  To: Drew Adams; +Cc: Daniel Pittman, Stefan Monnier, emacs-devel

On Thu, Feb 14, 2019 at 10:04 PM Drew Adams <drew.adams@oracle.com> wrote:
> > > Can you see that some of the following predefined orders
> > No, I can't.
> Seriously?

Yes.


João Távora



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

* Re: new-flex-completion-style
  2019-02-14 22:03                                     ` new-flex-completion-style Drew Adams
  2019-02-14 22:06                                       ` new-flex-completion-style João Távora
@ 2019-02-14 22:22                                       ` Stefan Monnier
  2019-02-15  0:54                                         ` new-flex-completion-style Drew Adams
  1 sibling, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2019-02-14 22:22 UTC (permalink / raw)
  To: Drew Adams; +Cc: Daniel Pittman, João Távora, emacs-devel

>> > Can you see that some of the following predefined orders
>> > might be advantageous in particular contexts/use cases?
>> > Can you see that whether matching is scatter, regexp,
>> > basic prefix, or others, any of the following can be
>> > useful?
>> No, I can't.
> Seriously?

All the examples you give are non-specific to the completion-style used,
whereas the `flx` scoring seems more directly related to the
completion style.

I guess one could consider `flx` scoring as just another kind of
sorting, but I'm pretty sure that it can give odd results when used
with (say) regexp-style completion.

So maybe, another way to look at it is that there are several sorting
choices, one of them being provided by the completion-style.


        Stefan



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

* RE: new-flex-completion-style
  2019-02-14 22:22                                       ` new-flex-completion-style Stefan Monnier
@ 2019-02-15  0:54                                         ` Drew Adams
  2019-02-15  4:50                                           ` new-flex-completion-style Stefan Monnier
  0 siblings, 1 reply; 71+ messages in thread
From: Drew Adams @ 2019-02-15  0:54 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Daniel Pittman, João Távora, emacs-devel

> >> > Can you see that some of the following predefined orders
> >> > might be advantageous in particular contexts/use cases?
> >> > Can you see that whether matching is scatter, regexp,
> >> > basic prefix, or others, any of the following can be
> >> > useful?
> >> No, I can't.
> > Seriously?
> 
> All the examples you give are non-specific to the completion-style used,
> whereas the `flx` scoring seems more directly related to the
> completion style.

The sort order that a user might want in any
given context can depend on any number of things.

Some completion styles might be context-related
(i.e., more suited to some kinds of completion,
e.g. file names, than to other kinds).  But for
the most part they are not.  Categories bring us
closer to use contexts/cases than styles, I guess.

But actually, I did mention two fuzzy-matching
methods that impose the sort order used - they
give you no other sort choice.  In particular,
they can't give you a sort order that is
especially useful for a certain context.

I don't see scatter-matching as limiting in
that way.  You can use it with the sort orders
I listed.  That's not the case for
`fuzzy-match.el' matching or Swank fuzzy symbol
matching.

> I guess one could consider `flx` scoring as just another kind of
> sorting, but I'm pretty sure that it can give odd results when used
> with (say) regexp-style completion.

Depends on the regexp.  But sure, you wouldn't
want to sort based on scoring that privileges
substring match length for input that is a wild
regexp.

FWIW, Icicles uses `flx' _only_ for sorting (by
`flx-score'), not for matching.  And yes, it's
just another sorting method.  I could have
included it in the list I showed.  And yes, it's
not context-specific (though it's likely more
useful with some contexts than with others).

> So maybe, another way to look at it is that there are several sorting
> choices, one of them being provided by the completion-style.

That goes back to my point about coupling such
things together (matching and sorting) versus
decoupling and so letting a user mix & match
(modulo the rare exception).

If a user specifies a particular sort order
in a completion style then s?he can't also
use the rest of that style without that sort
order, or vice versa - not without defining
additional completion styles that provide
those other possibilities.

Sure, allowing a style to include a sort can
be handy if you want to use that combination
a lot.  It can also be limiting.

Why didn't you just include categories, not
as separately specifiable, but only as part
of styles?

Surely you saw an advantage in being able to
mix & match.  Same thing applies to sorting,
in general (i.e. modulo some exceptions, as
mentioned).

Being able to include a sort order in a style
is one thing.  Having to do that, to be able
to choose a sort order, is another thing.



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

* Re: new-flex-completion-style
  2019-02-15  0:54                                         ` new-flex-completion-style Drew Adams
@ 2019-02-15  4:50                                           ` Stefan Monnier
  2019-02-15  5:52                                             ` new-flex-completion-style Dmitry Gutov
  2019-02-15  6:32                                             ` new-flex-completion-style Drew Adams
  0 siblings, 2 replies; 71+ messages in thread
From: Stefan Monnier @ 2019-02-15  4:50 UTC (permalink / raw)
  To: emacs-devel

>> I guess one could consider `flx` scoring as just another kind of
>> sorting, but I'm pretty sure that it can give odd results when used
>> with (say) regexp-style completion.
> Depends on the regexp.  But sure, you wouldn't
> want to sort based on scoring that privileges
> substring match length for input that is a wild
> regexp.

My point is that flx scoring is usually based on the idea that the
candidate does match using flx matching, whereas that might not be the
case is the matching was done some other way.  So the scoring result can
be completely meaningless (or it could even signal an error).

IOW matching and scoring can be intimately linked because the scoring is
based on *how* the candidate matched the input.


        Stefan




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

* Re: new-flex-completion-style
  2019-02-15  4:50                                           ` new-flex-completion-style Stefan Monnier
@ 2019-02-15  5:52                                             ` Dmitry Gutov
  2019-02-15  6:32                                             ` new-flex-completion-style Drew Adams
  1 sibling, 0 replies; 71+ messages in thread
From: Dmitry Gutov @ 2019-02-15  5:52 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

On 15.02.2019 07:50, Stefan Monnier wrote:
> My point is that flx scoring is usually based on the idea that the
> candidate does match using flx matching, whereas that might not be the
> case is the matching was done some other way.  So the scoring result can
> be completely meaningless (or it could even signal an error).

Scoring is already performed by the style. That doesn't necessarily mean 
that sorting must be, too. Especially if the score is stored in a 
neutrally-named text property.



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

* RE: new-flex-completion-style
  2019-02-15  4:50                                           ` new-flex-completion-style Stefan Monnier
  2019-02-15  5:52                                             ` new-flex-completion-style Dmitry Gutov
@ 2019-02-15  6:32                                             ` Drew Adams
  1 sibling, 0 replies; 71+ messages in thread
From: Drew Adams @ 2019-02-15  6:32 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

> >> I guess one could consider `flx` scoring as just another kind of
> >> sorting, but I'm pretty sure that it can give odd results when used
> >> with (say) regexp-style completion.
> > Depends on the regexp.  But sure, you wouldn't
> > want to sort based on scoring that privileges
> > substring match length for input that is a wild regexp.
> 
> My point is that flx scoring is usually based on the idea that the
> candidate does match using flx matching, whereas that might not be the
> case i[f] the matching was done some other way.  So the scoring result can
> be completely meaningless (or it could even signal an error).
> 
> IOW matching and scoring can be intimately linked because the scoring is
> based on *how* the candidate matched the input.

Yes.  And regexp matching is an outlier.  My point
about regexp matching was that for completion many
actual uses of regexp matching are substring matches
or close to it.  (`foobar' is a regexp.)

And besides this being the case for perhaps most
regexp-input matches (for completion), most other
match methods involve input chars that are also in
the candidates, so flx scoring even with non-flx
matching is generally not outlandish.

I think flx-score sorting is probably more useful
when you've typed relatively little and there are
many matches.  In a way it privileges, by sorting
(and hence for access by, e.g., cycling), candidates
that might match in two different ways, the optional
one being flx.

And yes, again, flx scoring is no doubt more useful
with some match methods than with others.  Finally,
I can't tell you how useful it might really be.
YMMV.  I can say that it's another sort order. ;-)

FWIW, the predicate I actually use for sorting by
`flx-score' just does alphabetical comparison if
the input doesn't return a `flx-score' for each of
the two candidates (i.e., if at least one does not
flx-match your input).

(defun icicle-flx-score-greater-p (s1 s2)
  "Non-nil means the `flx-score' of S1 is greater than that of S2.
That is, the cars of the `flx-score' values are compared.

If `flx-score' returns nil for either argument, then they are compared
using `icicle-case-string-less-p'.

This function requires library `flx.el'."
  (let* ((input   (if (and (icicle-file-name-input-p)
                           insert-default-directory)
                      (file-name-nondirectory
                        icicle-current-input)
                    icicle-current-input))
         (score1  (flx-score s1 input))
         (score2  (flx-score s2 input)))
    (if (and score1  score2)
        (> (car score1) (car score2))
      (icicle-case-string-less-p s1 s2))))




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

* Re: new-flex-completion-style
  2019-02-12 14:08       ` new-flex-completion-style Stefan Monnier
  2019-02-12 22:17         ` new-flex-completion-style João Távora
@ 2019-02-18 20:46         ` João Távora
  2019-02-18 23:35           ` new-flex-completion-style Stefan Monnier
  1 sibling, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-18 20:46 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

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

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> How 'bout we change the buffer name completion table so it specifies its
> own cycle-sort-function which uses buffer-list, then.  It seems like it
> would be a clear win (the buffer-list order is a much better heuristic
> than the length).

Hi again,

Here are two patches: the first does exactly what you propose above, the
second goes a little bit further, but I still think it's the right
thing...

Lightly tested stuff...

João


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-switch-to-buffer-s-completion-table-uses-its-own-sor.patch --]
[-- Type: text/x-diff, Size: 1387 bytes --]

From f170e728c1c1ac426bb73c63cc54ba2ae30afd1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= <joaotavora@gmail.com>
Date: Mon, 18 Feb 2019 20:32:38 +0000
Subject: [PATCH 1/2] switch-to-buffer's completion table uses its own sorting

* src/minibuf.c (Finternal_complete_buffer): Add
Qcycle_sort_function to completion table's metadata.
(syms_of_minibuf): New symbol Qcycle_sort_function.
---
 src/minibuf.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/minibuf.c b/src/minibuf.c
index 321fda1ba8..b23e24c4bd 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -1801,7 +1801,9 @@ If FLAG is nil, invoke `try-completion'; if it is t, invoke
   else if (EQ (flag, Qlambda))
     return Ftest_completion (string, Vbuffer_alist, predicate);
   else if (EQ (flag, Qmetadata))
-    return list2 (Qmetadata, Fcons (Qcategory, Qbuffer));
+    return list3 (Qmetadata,
+                  Fcons (Qcategory, Qbuffer),
+                  Fcons (Qcycle_sort_function, Qidentity));
   else
     return Qnil;
 }
@@ -1922,6 +1924,8 @@ syms_of_minibuf (void)
   DEFSYM (Qactivate_input_method, "activate-input-method");
   DEFSYM (Qcase_fold_search, "case-fold-search");
   DEFSYM (Qmetadata, "metadata");
+  DEFSYM (Qcycle_sort_function, "cycle-sort-function");
+
   /* A frame parameter.  */
   DEFSYM (Qminibuffer_exit, "minibuffer-exit");
 
-- 
2.20.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-cycle-sort-function-prevails-in-completion-all-sorte.patch --]
[-- Type: text/x-diff, Size: 2328 bytes --]

From f8ce65482d86a136f1320dac89e71662256c2168 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= <joaotavora@gmail.com>
Date: Mon, 18 Feb 2019 20:41:09 +0000
Subject: [PATCH 2/2] cycle-sort-function prevails in
 completion-all-sorted-completions

* lisp/minibuffer.el (completion-all-sorted-completions): Don't
re-sort if completion table has cycle-sort-function.
---
 lisp/minibuffer.el | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 7413be42eb..cc87ffaced 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1246,20 +1246,23 @@ completion-all-sorted-completions
           (setq all (delete-dups all))
           (setq last (last all))
 
-          (setq all (if sort-fun (funcall sort-fun all)
-                      ;; Prefer shorter completions, by default.
-                      (sort all (lambda (c1 c2) (< (length c1) (length c2))))))
-          ;; Prefer recently used completions and put the default, if
-          ;; it exists, on top.
-          (when (minibufferp)
-            (let ((hist (symbol-value minibuffer-history-variable)))
-              (setq all (sort all
+          (cond
+           (sort-fun
+            (setq all (funcall sort-fun all)))
+           (t
+            ;; Prefer shorter completions, by default.
+            (setq all (sort all (lambda (c1 c2) (< (length c1) (length c2)))))
+            (when (minibufferp)
+              ;; Prefer recently used completions and put the default, if
+              ;; it exists, on top.
+              (let ((hist (symbol-value minibuffer-history-variable)))
+                (setq all
+                      (sort all
                             (lambda (c1 c2)
                               (cond ((equal c1 minibuffer-default) t)
                                     ((equal c2 minibuffer-default) nil)
                                     (t (> (length (member c1 hist))
-                                          (length (member c2 hist))))))))))
+                                          (length (member c2 hist))))))))))))
           ;; Cache the result.  This is not just for speed, but also so that
           ;; repeated calls to minibuffer-force-complete can cycle through
           ;; all possibilities.
-- 
2.20.0


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

* Re: new-flex-completion-style
  2019-02-18 20:46         ` new-flex-completion-style João Távora
@ 2019-02-18 23:35           ` Stefan Monnier
  2019-02-19  9:16             ` new-flex-completion-style João Távora
  0 siblings, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2019-02-18 23:35 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

> @@ -1801,7 +1801,9 @@ If FLAG is nil, invoke `try-completion'; if it is t, invoke
>    else if (EQ (flag, Qlambda))
>      return Ftest_completion (string, Vbuffer_alist, predicate);
>    else if (EQ (flag, Qmetadata))
> -    return list2 (Qmetadata, Fcons (Qcategory, Qbuffer));
> +    return list3 (Qmetadata,
> +                  Fcons (Qcategory, Qbuffer),
> +                  Fcons (Qcycle_sort_function, Qidentity));
>    else
>      return Qnil;
>  }

That easy, huh?

> * lisp/minibuffer.el (completion-all-sorted-completions): Don't
> re-sort if completion table has cycle-sort-function.

I think a more precise description would be that cycle-sort-function now
also overrides the use of minibuffer-history-variable.
[ "Don't re-sort" sounds like a mere optimization rather than a change
  of semantics.  ]

Other than that, LGTM,


        Stefan



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

* Re: new-flex-completion-style
  2019-02-18 23:35           ` new-flex-completion-style Stefan Monnier
@ 2019-02-19  9:16             ` João Távora
  2019-02-19 12:54               ` new-flex-completion-style Stefan Monnier
  0 siblings, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-19  9:16 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

On Mon, Feb 18, 2019 at 11:35 PM Stefan Monnier
<monnier@iro.umontreal.ca> wrote:
> > +                  Fcons (Qcategory, Qbuffer),
> > +                  Fcons (Qcycle_sort_function, Qidentity));
> >    else
> >      return Qnil;
> >  }
> That easy, huh?

Yep, and does the right thing default-wise, too.  If I'm not mistaken,
I'd say it behaves exactly like ido-switch-to-buffer now, which doesn't
use score-based sorting, when icomplete-mode is used with the
new flex completion style.

BTW, has the council of completion elders reached any sort of
white-smoke decision vis-à-vis where to score-sort?

> I think a more precise description would be that cycle-sort-function now
> also overrides the use of minibuffer-history-variable.

That's in the commit message's subject line, but OK I've changed it.



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

* Re: new-flex-completion-style
  2019-02-19  9:16             ` new-flex-completion-style João Távora
@ 2019-02-19 12:54               ` Stefan Monnier
  2019-02-19 13:01                 ` new-flex-completion-style João Távora
  0 siblings, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2019-02-19 12:54 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

> Yep, and does the right thing default-wise, too.  If I'm not mistaken,
> I'd say it behaves exactly like ido-switch-to-buffer now, which doesn't
> use score-based sorting, when icomplete-mode is used with the
> new flex completion style.

;-)

> BTW, has the council of completion elders reached any sort of
> white-smoke decision vis-à-vis where to score-sort?

It's been too foggy around here lately to see much smoke, sorry.

>> I think a more precise description would be that cycle-sort-function now
>> also overrides the use of minibuffer-history-variable.
> That's in the commit message's subject line, but OK I've changed it.

Who reads the first line anyway?
[ After reading that first line: ] but that didn't make it clear that
the change is about the use of minibuffer-history-variable (the only
part which used to prevail over cycle-sort-function, AFAICT).


        Stefan



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

* Re: new-flex-completion-style
  2019-02-19 12:54               ` new-flex-completion-style Stefan Monnier
@ 2019-02-19 13:01                 ` João Távora
  2019-02-19 13:32                   ` new-flex-completion-style Stefan Monnier
  0 siblings, 1 reply; 71+ messages in thread
From: João Távora @ 2019-02-19 13:01 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

On Tue, Feb 19, 2019 at 12:54 PM Stefan Monnier
<monnier@iro.umontreal.ca> wrote:
> >> I think a more precise description would be that cycle-sort-function now
> >> also overrides the use of minibuffer-history-variable.
> > That's in the commit message's subject line, but OK I've changed it.
>
> Who reads the first line anyway?
> [ After reading that first line: ] but that didn't make it clear that
> the change is about the use of minibuffer-history-variable (the only
> part which used to prevail over cycle-sort-function, AFAICT).

Because of my other change to that function, it now also
prevails over minibuffer-default. This is why I didn't specifically
mention minibuffer-history-variable. That and writing commit
messages is hard.

Take care,
João



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

* Re: new-flex-completion-style
  2019-02-19 13:01                 ` new-flex-completion-style João Távora
@ 2019-02-19 13:32                   ` Stefan Monnier
  0 siblings, 0 replies; 71+ messages in thread
From: Stefan Monnier @ 2019-02-19 13:32 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

> Because of my other change to that function, it now also
> prevails over minibuffer-default.  This is why I didn't specifically
> mention minibuffer-history-variable.  That and writing commit
> messages is hard.

The upside is that nitpicking is easy,


        Stefan



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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-14  1:33                   ` Dmitry Gutov
@ 2019-02-19 16:10                     ` Stefan Monnier
  2019-02-24  0:03                       ` Dmitry Gutov
  0 siblings, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2019-02-19 16:10 UTC (permalink / raw)
  To: emacs-devel

>> So, not only it will only work with some completion tables, but for that
>> you'll need to introduce "wrong" code in those completion tables.
> Since we seem to want to redo completion tables in a major way anyway,

That's no guarantee that it will happen soon or at all, and it will have
to provide some backward compatibility.  And the more hacks we see using
the current system, the more difficult backward compatibility may become.

> I wouldn't worry about that too much, as long as the result is functional.

It'd be OK if it's indispensable, but I think there are better
alternatives that are easy to install right away.

>> I'd rather we extend the infrastructure so that completion styles can do
>> their own sorting.
> That's one option. Another option, which I've mentioned before, is to create
> an indirection for sorting functions via the completion table's
> category.  Similar to the one that completions styles have.

But those are orthogonal: the completion style can offer one kind of
sorting and that should work for all completion tables.
Completion tables can also offer their own kind of sorting (and it
should work with all completion styles).

How 'bout:

- Add global sorting config var(s?), to choose which kind of sorting to
  use, which would default to sorting based on "scores first and
  alphabetical after that".
- Let completion-category-overrides specify other choices.

This leaves some questions unanswered, tho:

- What about the distinction between cycle-sort and display-sort?
- Should the new var and new entries in completion-category-overrides
  contain directly sorting functions, or should they contain just the
  name of "sorting styles" with a separate table mapping those styles to
  actual functions (e.g. because a given style like `date` might be
  implemented differently for different completion tables?).
- Should we allow completion tables to offer several sorting choices?

In any case, in the mean time we can probably just introduce the new
sorting based on "scores first and alphabetical after that" and use it
by default.

> The category-based approach should circumvent that problem.
> With this approach, completion styles don't indicate sorting, and whatever
> entity did set up the completion style to be used (the user, a configuration
> package, etc) would need to set up both completion styles and sorting
> functions to match.

I think it'd be annoying for users to have to not only add `flex` to
their completion-styles but also change some sorting option at the same
time before that completion style becomes usable (in most cases, the
current alphabetical sorting works really poorly for `flex`).

> I think text properties are fine here.

It has its downsides, but I agree it seems like the better choice.


        Stefan




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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-19 16:10                     ` Stefan Monnier
@ 2019-02-24  0:03                       ` Dmitry Gutov
  2019-02-27 17:12                         ` Stefan Monnier
  0 siblings, 1 reply; 71+ messages in thread
From: Dmitry Gutov @ 2019-02-24  0:03 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

On 19.02.2019 19:10, Stefan Monnier wrote:
>>> So, not only it will only work with some completion tables, but for that
>>> you'll need to introduce "wrong" code in those completion tables.
>> Since we seem to want to redo completion tables in a major way anyway,
> 
> That's no guarantee that it will happen soon or at all, and it will have
> to provide some backward compatibility.  And the more hacks we see using
> the current system, the more difficult backward compatibility may become.

Very well.

This may be off topic now, but to the best of my recollection this 
discussion started from the question of the ability to add flex matching 
to particular completion tables. So that's where I was coming from, FWIW.

> But those are orthogonal: the completion style can offer one kind of
> sorting and that should work for all completion tables.

Orthogonal indeed, but it should be easier, implementation-wise, to only 
have one way that defines sorting logic. And also easier to port to the 
"new system", whenever that comes.

Also also, combining the flex sorting with most other kinds will most 
likely make the flex sorting hard to notice.

But please don't take this as a strong disagreement. Just an opinion.

> Completion tables can also offer their own kind of sorting (and it
> should work with all completion styles).
> 
> How 'bout:
> 
> - Add global sorting config var(s?), to choose which kind of sorting to
>    use, which would default to sorting based on "scores first and
>    alphabetical after that".

Put those defaults into completion-category-defaults, and you basically 
have my proposal, isn't that right?

> - Let completion-category-overrides specify other choices.
> 
> This leaves some questions unanswered, tho:
> 
> - What about the distinction between cycle-sort and display-sort?

TBH, I still don't know what's the difference between these. Meanwhile, 
company-capf has not support for the former, company has different kinds 
of paging through the popup, and it's working okay.

> - Should the new var and new entries in completion-category-overrides
>    contain directly sorting functions, or should they contain just the
>    name of "sorting styles" with a separate table mapping those styles to
>    actual functions (e.g. because a given style like `date` might be
>    implemented differently for different completion tables?).

Erm, I'd try the simpler approach first.

If the tables A and B are supposed to be sorted differently, couldn't 
they return different (but similarly sounding) category names?

Or if that's not generally feasible, what else would the sorting styles 
dispatch on? The tables themselves?

> - Should we allow completion tables to offer several sorting choices?

You mean different completion scores?

If you just mean other kinds of orderings, I think the user will choose 
via completion-category-overrides.

> In any case, in the mean time we can probably just introduce the new
> sorting based on "scores first and alphabetical after that" and use it
> by default.

*thumbsup*

> I think it'd be annoying for users to have to not only add `flex` to
> their completion-styles but also change some sorting option at the same
> time before that completion style becomes usable (in most cases, the
> current alphabetical sorting works really poorly for `flex`).

Apparently you're proposing to fix that by making the default sorting 
function to be flex-compatible. That sounds okay.



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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-24  0:03                       ` Dmitry Gutov
@ 2019-02-27 17:12                         ` Stefan Monnier
  2019-03-11  0:17                           ` Dmitry Gutov
  0 siblings, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2019-02-27 17:12 UTC (permalink / raw)
  To: emacs-devel

> This may be off topic now, but to the best of my recollection this
> discussion started from the question of the ability to add flex matching to
> particular completion tables. So that's where I was coming from, FWIW.

I see.  I was taking the point of view of a generic `flex` method for
use anywhere you like (I think the original motivation was to use it in
conjunction with `icomplete-mode` to more closely match to `ido`
behavior).

> Also also, combining the flex sorting with most other kinds will most likely
> make the flex sorting hard to notice.

Depends on the ordering (see below).

>> - Add global sorting config var(s?), to choose which kind of sorting to
>>    use, which would default to sorting based on "scores first and
>>    alphabetical after that".
>
> Put those defaults into completion-category-defaults, and you basically have
> my proposal, isn't that right?

completion-category-defaults is an alist providing extra settings for
specific categories, so it's not "global" in the sense I meant above
because can't be used to choose the sorting used for categories not
mentioned in completion-category-defaults.

>> - What about the distinction between cycle-sort and display-sort?
> TBH, I still don't know what's the difference between these.

display-sort is the sorting used when displaying the candidates in
a list like *Completions* whereas cycle-sort is the sorting used when
your TAB cycles through possible candidates (and it's also used in
icomplete-mode).

In display-sort we currently sort alphabetically whereas in cycle-sort
we want to use a heuristic that puts more likely choices first.

Maybe we should drop this distinction and just use the same sorting
everywhere (which would have to be the cycle-sort by default I think,
because the alphabetical sort is really a poor choice when cycling in
my experience).

The downside of the heuristic sort of cycle-sort is that sometimes/often
the heuristic is poor (by default it's just based on string
length ;-( ), so the *Completions* buffer would look "unsorted".

>> In any case, in the mean time we can probably just introduce the new
>> sorting based on "scores first and alphabetical after that" and use it
>> by default.
> *thumbsup*

OK, let's go with that for now.


        Stefan




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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-02-27 17:12                         ` Stefan Monnier
@ 2019-03-11  0:17                           ` Dmitry Gutov
  2019-03-11  1:15                             ` Stefan Monnier
  2019-03-11  8:47                             ` João Távora
  0 siblings, 2 replies; 71+ messages in thread
From: Dmitry Gutov @ 2019-03-11  0:17 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

On 27.02.2019 19:12, Stefan Monnier wrote:

> I see.  I was taking the point of view of a generic `flex` method for
> use anywhere you like (I think the original motivation was to use it in
> conjunction with `icomplete-mode` to more closely match to `ido`
> behavior).

That's a worthy goal as well, of course. Not sure it will be ideal for 
e.g. eglot's completion table, but that's a separate discussion, I guess.

>> Also also, combining the flex sorting with most other kinds will most likely
>> make the flex sorting hard to notice.
> 
> Depends on the ordering (see below).

With most helpful/meaningful kinds, then?

>>> - Add global sorting config var(s?), to choose which kind of sorting to
>>>     use, which would default to sorting based on "scores first and
>>>     alphabetical after that".
>>
>> Put those defaults into completion-category-defaults, and you basically have
>> my proposal, isn't that right?
> 
> completion-category-defaults is an alist providing extra settings for
> specific categories, so it's not "global" in the sense I meant above
> because can't be used to choose the sorting used for categories not
> mentioned in completion-category-defaults.

You mean it can't be used to change settings for the "other" categories, 
the defaults, right? Why don't we use the key 't' for this (with the 
corresponding tiny code change somewhere else)?

I think this will fit the name of the variable, as well as the way it is 
used. The function completion--category-override could use a rename in 
this case, though.

This will also let us set the completion style defaults for the "other" 
categories (and the user too, if completion-category-overrides supports 
the same).

> display-sort is the sorting used when displaying the candidates in
> a list like *Completions* whereas cycle-sort is the sorting used when
> your TAB cycles through possible candidates (and it's also used in
> icomplete-mode).

I see, thanks.

> In display-sort we currently sort alphabetically whereas in cycle-sort
> we want to use a heuristic that puts more likely choices first.
> 
> Maybe we should drop this distinction and just use the same sorting
> everywhere (which would have to be the cycle-sort by default I think,
> because the alphabetical sort is really a poor choice when cycling in
> my experience).

Yeah, I do believe we'd prefer the most likely choices at the top in the 
display-sort case as well (or for company-capf, at least).

> The downside of the heuristic sort of cycle-sort is that sometimes/often
> the heuristic is poor (by default it's just based on string
> length ;-( ), so the *Completions* buffer would look "unsorted".

Improving the heuristics should also help, of course. But it can be left 
for later.



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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-03-11  0:17                           ` Dmitry Gutov
@ 2019-03-11  1:15                             ` Stefan Monnier
  2019-03-11 22:54                               ` Dmitry Gutov
  2019-03-11  8:47                             ` João Távora
  1 sibling, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2019-03-11  1:15 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: emacs-devel

>>> Also also, combining the flex sorting with most other kinds will most likely
>>> make the flex sorting hard to notice.
>> Depends on the ordering (see below).
> With most helpful/meaningful kinds, then?

With such sorting where most candidates get a different score, it's
difficult to combine the sorting indeed: depending on the precedence we
give to each type of score either the flex sorting will be unnoticeable
or the other one will be unnoticeable.

Of course, if we're careful we can try and tune the weighting of the
types of scores so that both scoring have a visible impact, but I have
the impression that it's going to require too careful tuning to be
usable in practice.

> You mean it can't be used to change settings for the "other" categories, the
> defaults, right? Why don't we use the key 't' for this (with the
> corresponding tiny code change somewhere else)?

Ah, we could yes.  That's equivalent to using another global var, indeed.
Currently we use global vars (completion-styles and
completion-cycle-threshold) for that purpose, mostly by accident.

>> The downside of the heuristic sort of cycle-sort is that sometimes/often
>> the heuristic is poor (by default it's just based on string
>> length ;-( ), so the *Completions* buffer would look "unsorted".
> Improving the heuristics should also help, of course. But it can be left
> for later.

I'm afraid that if we drop the display-sort and use cycle-sort
everywhere, there's going to be a very strong reaction from users not
appreciating the change.  Even more so if the heuristic is poor.


        Stefan



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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-03-11  0:17                           ` Dmitry Gutov
  2019-03-11  1:15                             ` Stefan Monnier
@ 2019-03-11  8:47                             ` João Távora
  2019-03-11 22:57                               ` Dmitry Gutov
  1 sibling, 1 reply; 71+ messages in thread
From: João Távora @ 2019-03-11  8:47 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Stefan Monnier, emacs-devel

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

On Mon, Mar 11, 2019, 00:18 Dmitry Gutov <dgutov@yandex.ru> wrote:

> On 27.02.2019 19:12, Stefan Monnier wrote:
>
> > I see.  I was taking the point of view of a generic `flex` method for
> > use anywhere you like (I think the original motivation was to use it in
> > conjunction with `icomplete-mode` to more closely match to `ido`
> > behavior).
>
> That's a worthy goal as well, of course. Not sure it will be ideal for
> e.g. eglot's completion table, but that's a separate discussion, I guess.
>

I've been very busy and just caught up with this discussion. I can't
contribute much more right now other than confirming Stefan's intuition for
the original motivation. I wanted, and want, icomplete to be as usable as
ido.el (with the added advantage of being well behaved). But I also want
eglot.el and elisp's completion-at-point to be able to flex-match like,
i.e. Sly does. So basically I want to be able to flex match everywhere.

Regarding sorting, after using it  in icomplete, C-x b, C-x f, M-x for a
while now, I can say this: There seems to be no case where I wouldn't like
flex's scoring to be the dominant, but I haven't turned it on right now
(mostly because there's no easy way yet due to this analysis-paralysis),
and the table's scoring for those three seems sufficient in a reasonable
number of the situations. When completing larger sets, such as
company-completing all elisp symbols for writing code, flex scoring becomes
indispensable, because the secondary sorting there is lexicographic.

Not sure what you can make of this, but if you can, make something :), and
thanks very much for working on this.

João

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

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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-03-11  1:15                             ` Stefan Monnier
@ 2019-03-11 22:54                               ` Dmitry Gutov
  2019-03-12  1:10                                 ` Drew Adams
  0 siblings, 1 reply; 71+ messages in thread
From: Dmitry Gutov @ 2019-03-11 22:54 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

On 11.03.2019 03:15, Stefan Monnier wrote:
> Of course, if we're careful we can try and tune the weighting of the
> types of scores so that both scoring have a visible impact, but I have
> the impression that it's going to require too careful tuning to be
> usable in practice.

While possible, I think in practice it will require using just one 
combined sorting function, instead of passing the list of completions 
though several independent sorting functions. Although please feel free 
to prove me wrong, because I like the list-of-functions approach.

> Ah, we could yes.  That's equivalent to using another global var, indeed.
> Currently we use global vars (completion-styles and
> completion-cycle-threshold) for that purpose, mostly by accident.

Fair enough.

completion-sort-functions, then?

> I'm afraid that if we drop the display-sort and use cycle-sort
> everywhere, there's going to be a very strong reaction from users not
> appreciating the change.  Even more so if the heuristic is poor.

In that case I'd suggest dropping cycle-sort and, for now, keeping 
display-sort behavior as is. But make additional sorting configurable 
like we've been discussing, via completion-sort-functions, as well as 
package/user overrides in completion-category-*.



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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-03-11  8:47                             ` João Távora
@ 2019-03-11 22:57                               ` Dmitry Gutov
  0 siblings, 0 replies; 71+ messages in thread
From: Dmitry Gutov @ 2019-03-11 22:57 UTC (permalink / raw)
  To: João Távora; +Cc: Stefan Monnier, emacs-devel

On 11.03.2019 10:47, João Távora wrote:
> But I also want eglot.el and elisp's completion-at-point to be able to 
> flex-match like, i.e. Sly does. So basically I want to be able to flex 
> match everywhere.

I'm referring to the distinction that eglot uses LSP which supposedly 
has the option of fuzzy matching in the external process. Which we 
probably want to use.

And to take advantage of that possibility, the completion styles would 
have to be somewhat different.



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

* RE: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-03-11 22:54                               ` Dmitry Gutov
@ 2019-03-12  1:10                                 ` Drew Adams
  2019-03-12 22:25                                   ` Dmitry Gutov
  0 siblings, 1 reply; 71+ messages in thread
From: Drew Adams @ 2019-03-12  1:10 UTC (permalink / raw)
  To: Dmitry Gutov, Stefan Monnier; +Cc: emacs-devel

> While possible, I think in practice it will require using just one
> combined sorting function, instead of passing the list of completions
> though several independent sorting functions. Although please feel free
> to prove me wrong, because I like the list-of-functions approach.

(Caveat: I haven't been following this thread.)

Just thought I'd mention how I like to handle a
suite of sorting predicates for dealing with things,
including completion candidates, that may or may not
be comparable to varying degrees or in different ways.

When two such cannot be compared using the preferred
sorting predicate then the next-preferred predicate
is tried, and so on.

This page explains the approach:

https://www.emacswiki.org/emacs/ApplesAndOranges

The basic idea is to allow the use of both ordinary
two-valued (true/false) predicates and three-valued
(true/false/dunno) predicates, combining the latter
in a chain.

I use this in Bookmark+, for example, to sort
candidates that are bookmarks of different kinds.

Different kinds of bookmarks have different things
in common - fields that can be compared, for example.
They can also have fields that might not be comparable.

Depending on the purpose of a given sort, users can
want to use different comparison-predicate suites,
that is, apply different sets of predicates in
different orders of priority.

Variable `bmkp-sort-comparer' holds the current
comparison suite, which is used for sorting.

The variable value is one of the following:

* `nil', meaning no sorting;
* an ordinary 2-valued predicate; or
* a list of 3-valued predicates, optionally followed
  by a single 2-valued "fallback" predicate.

If the first 3-valued predicate in the list can
compare the two given bookmarks then it decides.  If
not then the second 3-valued predicate is tried, and
so on.  If none of the 3-valued predicates can decide
then the fallback, 2-valued predicate decides.

It's easy to combine 3-valued predicates  They
decide, themselves, whether they are applicable
to their two given arguments.  If not, they just
opt out of the deciding.

Variable `bkmp-sort-comparer' is described here:

https://www.emacswiki.org/emacs/ApplesAndOranges#BmkpSortComparer



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

* Re: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-03-12  1:10                                 ` Drew Adams
@ 2019-03-12 22:25                                   ` Dmitry Gutov
  2019-03-12 23:12                                     ` Drew Adams
  0 siblings, 1 reply; 71+ messages in thread
From: Dmitry Gutov @ 2019-03-12 22:25 UTC (permalink / raw)
  To: Drew Adams, Stefan Monnier; +Cc: emacs-devel

On 12.03.2019 03:10, Drew Adams wrote:
> The basic idea is to allow the use of both ordinary
> two-valued (true/false) predicates and three-valued
> (true/false/dunno) predicates, combining the latter
> in a chain.
> 
> I use this in Bookmark+, for example, to sort
> candidates that are bookmarks of different kinds.

That's a pretty cute idea.

I don't know if having a heterogeneous set of candidates is going to be 
a significant use case, though.



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

* RE: [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness
  2019-03-12 22:25                                   ` Dmitry Gutov
@ 2019-03-12 23:12                                     ` Drew Adams
  0 siblings, 0 replies; 71+ messages in thread
From: Drew Adams @ 2019-03-12 23:12 UTC (permalink / raw)
  To: Dmitry Gutov, Stefan Monnier; +Cc: emacs-devel

> > The basic idea is to allow the use of both ordinary
> > two-valued (true/false) predicates and three-valued
> > (true/false/dunno) predicates, combining the latter
> > in a chain.
> >
> > I use this in Bookmark+, for example, to sort
> > candidates that are bookmarks of different kinds.
> 
> That's a pretty cute idea.
> 
> I don't know if having a heterogeneous set of candidates is going to be
> a significant use case, though.

If different kinds of scores can be more meaningful
for some candidates than for others, or not available
for some candidates, then you have heterogeneous data
to compare, and multiple comparators can be relevant.

I got the impression that such was the case, but as
I said, I haven't really followed this thread.



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

end of thread, other threads:[~2019-03-12 23:12 UTC | newest]

Thread overview: 71+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20190202232827.27331.87300@vcs0.savannah.gnu.org>
     [not found] ` <20190202232828.4AE452159A@vcs0.savannah.gnu.org>
2019-02-06  3:11   ` [Emacs-diffs] scratch/new-flex-completion-style 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness Dmitry Gutov
2019-02-06 10:09     ` João Távora
2019-02-06 18:54       ` Dmitry Gutov
2019-02-06 19:47         ` João Távora
2019-02-12  0:25           ` Dmitry Gutov
2019-02-12 13:19             ` Stefan Monnier
2019-02-12 22:55               ` Dmitry Gutov
2019-02-13 16:00                 ` Stefan Monnier
2019-02-14  1:33                   ` Dmitry Gutov
2019-02-19 16:10                     ` Stefan Monnier
2019-02-24  0:03                       ` Dmitry Gutov
2019-02-27 17:12                         ` Stefan Monnier
2019-03-11  0:17                           ` Dmitry Gutov
2019-03-11  1:15                             ` Stefan Monnier
2019-03-11 22:54                               ` Dmitry Gutov
2019-03-12  1:10                                 ` Drew Adams
2019-03-12 22:25                                   ` Dmitry Gutov
2019-03-12 23:12                                     ` Drew Adams
2019-03-11  8:47                             ` João Távora
2019-03-11 22:57                               ` Dmitry Gutov
2019-02-12 17:21             ` João Távora
2019-02-12 23:47               ` Dmitry Gutov
2019-02-11 21:10   ` new-flex-completion-style (was: [Emacs-diffs] scratch/ 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness) Stefan Monnier
2019-02-11 22:16     ` new-flex-completion-style João Távora
2019-02-11 23:02       ` new-flex-completion-style Dmitry Gutov
2019-02-11 23:11         ` new-flex-completion-style João Távora
2019-02-12  0:10           ` new-flex-completion-style Dmitry Gutov
2019-02-12  0:16       ` new-flex-completion-style Óscar Fuentes
2019-02-12 22:04         ` new-flex-completion-style João Távora
2019-02-13  0:28           ` new-flex-completion-style Óscar Fuentes
2019-02-13 11:20             ` new-flex-completion-style João Távora
2019-02-13 14:23               ` new-flex-completion-style Óscar Fuentes
2019-02-13 14:38                 ` new-flex-completion-style Drew Adams
2019-02-13 15:24               ` new-flex-completion-style Stefan Monnier
2019-02-13 15:33                 ` new-flex-completion-style Drew Adams
2019-02-13 15:40                 ` new-flex-completion-style Óscar Fuentes
2019-02-13 17:34                   ` new-flex-completion-style Daniel Pittman
2019-02-12 14:08       ` new-flex-completion-style Stefan Monnier
2019-02-12 22:17         ` new-flex-completion-style João Távora
2019-02-13 17:29           ` new-flex-completion-style João Távora
2019-02-13 18:54             ` new-flex-completion-style Stefan Monnier
2019-02-13 19:13               ` new-flex-completion-style João Távora
2019-02-14 13:36                 ` new-flex-completion-style Stefan Monnier
2019-02-14 13:55                   ` new-flex-completion-style João Távora
2019-02-14 14:59                     ` new-flex-completion-style João Távora
2019-02-14 15:28                       ` new-flex-completion-style Óscar Fuentes
2019-02-14 15:44                         ` new-flex-completion-style Drew Adams
2019-02-14 16:21                         ` new-flex-completion-style João Távora
2019-02-14 15:35                       ` new-flex-completion-style Daniel Pittman
2019-02-14 16:12                         ` new-flex-completion-style João Távora
2019-02-14 16:16                           ` new-flex-completion-style João Távora
2019-02-14 16:34                         ` new-flex-completion-style Drew Adams
2019-02-14 17:03                           ` new-flex-completion-style João Távora
2019-02-14 17:49                             ` new-flex-completion-style Drew Adams
2019-02-14 18:30                               ` new-flex-completion-style João Távora
2019-02-14 19:20                                 ` new-flex-completion-style Drew Adams
2019-02-14 20:54                                   ` new-flex-completion-style João Távora
2019-02-14 22:03                                     ` new-flex-completion-style Drew Adams
2019-02-14 22:06                                       ` new-flex-completion-style João Távora
2019-02-14 22:22                                       ` new-flex-completion-style Stefan Monnier
2019-02-15  0:54                                         ` new-flex-completion-style Drew Adams
2019-02-15  4:50                                           ` new-flex-completion-style Stefan Monnier
2019-02-15  5:52                                             ` new-flex-completion-style Dmitry Gutov
2019-02-15  6:32                                             ` new-flex-completion-style Drew Adams
2019-02-18 20:46         ` new-flex-completion-style João Távora
2019-02-18 23:35           ` new-flex-completion-style Stefan Monnier
2019-02-19  9:16             ` new-flex-completion-style João Távora
2019-02-19 12:54               ` new-flex-completion-style Stefan Monnier
2019-02-19 13:01                 ` new-flex-completion-style João Távora
2019-02-19 13:32                   ` new-flex-completion-style Stefan Monnier
2019-02-11 22:57     ` new-flex-completion-style (was: [Emacs-diffs] scratch/ 2c75775 2/2: Score, sort and annotate flex-style completions according to match tightness) Drew Adams

Code repositories for project(s) associated with this external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.