oantolin / orderless

Emacs completion style that matches multiple regexps in any order
GNU General Public License v3.0
776 stars 27 forks source link

Questions about annotation matching #170

Closed hmelman closed 7 months ago

hmelman commented 8 months ago

Sorry this is a little unfocused, I ran into this issue and think it belongs here. I'm using orderless, vertico, consult and marginalia. I'm also using helpful but I think this applies to the builtin describe- commands as well.

I ran helpful-callable (or describe-function) and wanted to narrow to just commands. Marginalia shows a nice column and marks each candidate as f or c (and several other things), I wanted just the c. My consult-narrow-key is set to "|" as that reminds me of shell pipeline filters, maybe that's a bad choice. At first I tried typing "|c" to narrow to commands, the way I would with consult commands, but now I think that doesn't work. Is that true? Narrowing only works with consult command that enable it and not with something like describe-function?

I now think that's what orderless annotation matching is meant to enable. But I'm not sure what the annotation is. Is it all columns marginalia shows for each candidate? It seems to be, and that does make sense to me. Is there a way to limit it to some marginalia columns? The "groupings" marginalia shows would be useful to match on, but since they're all one character and there's often a docstring or something, matching all the lines with a c in them isn't helpful.

Or maybe I'm looking in the wrong place for this and I need something else. Maybe a consult-describe-function or an addition to helpful to enable narrowing? Thanks for any pointers.

minad commented 8 months ago

First, let me clarify how annotation matching operates. For example run M-x describe-function and then type consult &M- to narrow to allow Consult commands with a meta key binding. Note the ampersand prefix, which is needed to tell Orderless to match the rest of the word against the annotations. The prefix can be easily remembered with the mnemonic an(d)notation.

Right now annotation matching always matches against the full annotation string, and there does not exist a possibility to restrict the matching to a certain Marginalia column. (As a possible extension we could consider restricting to columns, e.g., &1&f would only match against the first column, but I am not sure if we need this given the newly added orderless-kwd dispatcher.)

Instead of restricting to Marginalia columns, Orderless provides a keyword dispatcher which let's you explicitly filter against certain candidate properties by keyword. First add orderless-kwd-dispatch to the orderless-style-dispatchers list variable. Then in C-x b the input :mod:org will filter buffers where the major-mode contains the string "org". Or in M-x, the input :on will filter enabled minor modes. (This does not exist yet, but we could also add another keyword :typ, such that :typ:c which would filter commands.)

hmelman commented 8 months ago

Thanks, that helps a lot. I hadn't seen about the brand new orderless keyword support. I like that the keywords you've chosen are drawn from marginalia terminology. Though it seems like you're using marginalia face terms since you suggested :typ for marginalia-type face, as opposed to the underlying implementation terminology like :cla for class since it's generated from marginalia--symbol-class. I think I agree with that.

So I'm correct that to use narrowing in my example would require some consult integration. In these cases, since function and variable candidate lists are so long, would you expect a significant performance difference between a consult solution vs an orderless one?

minad commented 8 months ago

Though it seems like you're using marginalia face terms since you suggested :typ for marginalia-type face, as opposed to the underlying implementation terminology like :cla for class since it's generated from marginalia--symbol-class. I think I agree with that.

Note that we don't have a :typ or :cls keyword implemented yet.

So I'm correct that to use narrowing in my example would require some consult integration. This these cases, since function and variable candidate lists are so long, would you expect a significant performance difference between a consult solution vs an orderless one?

You confuse the Orderless functionality with Consult narrow keys. They are unrelated, but the underlying filtering technology is the same. Both use completion predicates to filter out candidates. The difference is that Consult narrowing is triggered via an extra key. In retrospect the Consult narrow key functionality is mostly redundant and I think Orderless filters are almost always preferable. The only advantages of Consult narrowing are that it works independently of the completion styles and that it can be triggered quickly with two key presses (otoh one could implement the same with an extra key in Orderless, e.g., the input |b would filter to buffers in consult-buffer).

hmelman commented 8 months ago

Note that we don't have a :typ or :cls keyword implemented yet.

Yes I understand. I was commenting on your proposed type keyword.

You confuse the Orderless functionality with Consult narrow keys.

I'm not. I understand the different implementations, (though I haven't looked into orderless internals). But as a user, particularly in my example, the functionality is same.

They are unrelated, but the underlying filtering technology is the same. Both use completion predicates to filter out candidates. The difference is that Consult narrowing is triggered via an extra key. In retrospect the Consult narrow key functionality is mostly redundant and I think Orderless filters are almost always preferable. The only advantages of Consult narrowing are that it works independently of the completion styles and that it can be triggered quickly with two key presses (otoh one could implement the same with an extra key in Orderless, e.g., the input |b would filter to buffers in consult-buffer).

Good to know the performance should be similar.

Rather than consult narrowing being independent of the completion styles, I have tended to think about it the other way around. In the Iceberg suite 😉, it was Marginalia, Consult, and Embark that had code to handle the underlying specifics of different kinds of candidates and Vertico, Corfu, and Orderless were agnostic to them. Now orderless keywords would gain that knowledge.

So yes, I think orderless keywords sounds interesting and I would have a real use of a :typ keyword. I have my own style-dispatcher and will probably try to use | as a prefix for keywords, but I understand that's my own customization.

minad commented 7 months ago

@hmelman It seems we can close this or are there still open questions?