oantolin / orderless

Emacs completion style that matches multiple regexps in any order

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Document `(orderless basic)` as recommended configuration

minad opened this issue · comments

I use this configuration for a long time now in my configuration and it seems to work for almost every completion table. basic is only needed as fallback for completion-table-dynamic and other dynamic completion tables. I documented this in https://github.com/minad/vertico#completion-table-dynamic and updated the Vertico and Corfu READMEs accordingly to use (setq completion-styles '(orderless basic)) everywhere. See also https://github.com/minad/consult/wiki#minads-orderless-configuration. What do you think?

I assume that this setting works around most of the issues in #24, #45, #68, #79, #89, #108. For example #68 is not fixed completely since if you enter a space only you still don't see the hidden buffers, but as soon as you enter more input, e.g., *Echo, the hidden buffers are completed, which is not the case with orderless only. Anyway I think (orderless basic) seems a better default than (orderless) only, so I would recommend that as default.

Maybe (basic orderless) is even better, because people like it when TAB lengthens the candidate without reducing the matches.

Also #24 only gets fixed if basic comes first.

So I've been using just orderless since I wrote orderless and don't think I've run into any trouble. What's a common case that does come up? I'm guessing maybe something like LSP or python.el completion querying the interpreter, I think those tend to have a bug where the completion says, "the empty string? NOTHING has the empty string as a prefix!".

Also maybe I don't run into trouble because I use ^prefix and that has sent the prefix to the completion to the completion table for a while now. For example for #68, ^\ works just fine to match hidden buffers if you have escapeable spaces.

Maybe (basic orderless) is even better, because people like it when TAB lengthens the candidate without reducing the matches.

Well, it is a trade off. I think (basic orderless) is worse since it "disables" Orderless. If you type something you may get few prefix matches first until there is more input and the more flexible Orderless takes over. But we should probably document both approaches, since both are valid and it depends on preference.

  1. (orderless basic) - basic is only used as fallback for dynamic completion tables. No TAB prefix completion however. My recommendation since it keeps Orderless fully intact.
  2. (basic orderless) - basic takes over first - imo it takes over too often. Obviously fixes dynamic completion tables and TAB completion.
  3. (substring orderless basic) - This option sits somehow between the 1 and 2 extremes.

See https://github.com/minad/vertico/#completion-table-dynamic for an example which works with (orderless basic) and obviously (basic orderless) but not (orderless) only. #24 is an edge case, you can always construct scenarios which require basic to come first, see for example https://github.com/minad/vertico/#tramp-hostname-completion.

So I've been using just orderless since I wrote orderless and don't think I've run into any trouble. What's a common case that does come up? I'm guessing maybe something like LSP or python.el completion querying the interpreter, I think those tend to have a bug where the completion says, "the empty string? NOTHING has the empty string as a prefix!".

Yes, one could say it is a bug in those completion functions/tables. But I am pragmatic here. I prefer to recommend a configuration which covers more cases, even if they are not strictly correct. It is not unreasonable to use completion-table-dynamic to generate candidates by talking to an external process.

Also maybe I don't run into trouble because I use ^prefix and that has sent the prefix to the completion to the completion table for a while now. For example for #68, ^\ works just fine to match hidden buffers if you have escapeable spaces.

Yes, if one uses ^prefix the optimization #68 mitigates the problem. However this is not something which is obvious. If you enter a literal "prefix" with a completion-table-dynamic you won't get any output at all with (orderless) only.

Of course one can discuss how widespread these issues are. They are not very widespread, however there have been reports here as I listed above. (orderless basic) seems to be strictly better than (orderless) only (without any downsides?). Therefore I would recommend that. I did some more investigation of such issues of dynamic completion tables (because of Vertico and Corfu), looked around for open Ivy issues and I document problematic completion tables in the Vertico README.

Yes, one could say it is a bug in those completion functions/tables. But I am pragmatic here.

Oh, I agree with the pragmatic approach to this. In fact, my opinion is that while returning nil for the empty string is clearly a bug in those tables, it is a sensible bug that reasonable can WONTFIX or even implement on purpose for perfomance reasons. Maybe it's weird for a mathematician to say this, but correctness isn't always the best choice.

https://github.com/minad/vertico/#tramp-hostname-completion.

I hadn't noticed the problem with hostname completion since I bookmark all the hosts I need and always enter those paths with consult-dir (or, before consult-dir existed, my toy version of it that only used bookmarks as a source of paths)! Maybe this specific problem should be mentioned in the orderless readme too.

On balance, I think recommending (orderless basic) is strictly better than (orderless), so I'll happily merge the PR. Maybe the TRAMP issue should be discussed and something like (setq completion-category-overrides '((file (styles basic orderless)))) could be recommended too.

Maybe the TRAMP issue should be discussed and something like (setq completion-category-overrides '((file (styles basic orderless)))) could be recommended too.

Okay, added in 7d704c0.

Hi, currently I use (basic orderless) as I need TAB to complete the common part of the candidates,

Maybe (basic orderless) is even better, because people like it when TAB lengthens the candidate without reducing the matches.

How could I use only orderless for minibuffer completion? For example, when I execute describe-variable and type in feature, there goes only one candidate features, and I have to type in another space in order to search for the variables which does not begin with feature. I tried (add-to-list 'completion-category-overrides '(minibuffer (style orderless))) but no success on that.

@wang1zhen That's exactly the problem. You cannot have both Orderless behavior and TAB prefix completion at the same time. My preference is to have Orderless behavior since I find TAB completion pretty much useless. Therefore (orderless basic) is the best default.

As a compromise you can use (substring orderless basic). This will give you TAB completion and almost-Orderless behavior until you enter a space. It will be equivalent to (orderless basic) as long as the first word is a literal string.

(substring orderless basic) does not seem to give TAB completion in most cases. As completion-style-alist indicates, substring would consider candidates *foo*bar* for foo_bar, and as long as there are candidates like afoo, the TAB prefix completion would not work as they do not share the same prefix foo.

Good to know. You could also try to mix basic with orderless as follows:

(add-to-list 'completion-styles-alist
             '(orderless+basic
               completion-basic-try-completion
               orderless-all-completions
               "Unholy mix of Orderless and Basic."))

(setq completion-styles '(orderless+basic orderless basic)
      completion-category-defaults nil
      completion-category-overrides nil)

EDIT: A better variant is probably this:

(defun orderless+basic-all (str table pred point)
  (or (orderless-all-completions str table pred point)
      (completion-basic-all-completions str table pred point)))

(defun orderless+basic-try (str table pred point)
  (or (completion-basic-try-completion str table pred point)
      (orderless-try-completion str table pred point)))

(add-to-list 'completion-styles-alist
             '(orderless+basic
               orderless+basic-try
               orderless+basic-all
               "Unholy mix of Orderless and Basic."))

(setq completion-styles '(orderless+basic)
      completion-category-defaults nil
      completion-category-overrides nil)

Couldn't one use the wonderful orderless dispatcher to "turn orderless into a prefix matcher" for term 1? I use the dispatcher to let each and every LSP completion candidate though on the first term (unless it gets changed), by returning "". This is because LSP already has its own matching heuristics.

I admit I don't understand the issue with completion-table-dynamic though. Why does orderless have trouble with those, and could the dispatcher solve it?

@jdtsmith Sure one could turn the first word into a prefix. See #49, #79 and #81 for previous discussions. I experimented with this for a while but it is not a nice setup, since the Orderless behavior is lost. I don't want the first word to always be treated as prefix only. You can of course use it as a special setup for certain completion categories or even only for a few special completion tables. This issue about (orderless basic) was about a setup which makes sense as default configuration.

I admit I don't understand the issue with completion-table-dynamic though. Why does orderless have trouble with those, and could the dispatcher solve it?

It's exactly the same issue as with LSP: the functions people pass to completion-table-dynamic expect an actual prefix to construct the completions. So yes, a ^-prepending dispatcher should also fix those.

But I agree with @minad, I don't want the first component to always be special, and as a recommendation for most users it's easier to say "use orderless and basic" than to explain the whole dispatcher solution.

I see, thanks. So it's not an intrinsic problem with completion-table-dynamic, but more a general problem with the types of functions passed to it, which often insist on a non-empty prefix to return anything. For a mode I'm working on I simply ignore the empty probe strings that orderless and others provide, and return the same set of cached completions I computed on the initial call to the completion table function (with a non-empty probe). Just like in the LSP case, I don't have a way to ask the underlying completion engine to give me "every completion conceivably possible here". But I can tell orderless and others "here's everything I've got, you sort it out". What this means in practice is that where completion begins matters. With corfu's new :separator semantics it's easy: want full orderless power? Insert a separator with M-SPC.