orderless icon indicating copy to clipboard operation
orderless copied to clipboard

Orderful behavior

Open meedstrom opened this issue 10 months ago • 13 comments

Made an issue on Prescient a long time ago but left it alone to try the orderless way. https://github.com/radian-software/prescient.el/issues/87

Recently had a new discussion and realized that yep, I still want it https://old.reddit.com/r/emacs/comments/1iytdt3/oh_man_i_wish_aboabo_would_actively_maintain_ivy/mexrd7n/

Do you think it would make sense in Orderless to support this behavior? In short, so that every space character is actually interpreted as .*.

At least as long as the first word did not start with any of the chars in orderless-affix-dispatch-alist.

meedstrom avatar Mar 07 '25 12:03 meedstrom

You can configure orderless to do this if you wish. You could set orderless-component-separator to identity so that all input is a single component, and then define a matching style that just turns spaces into .*. Something like:

(defun orderfull (component)
  (string-join (string-join (split-string component) ".*")))

(setq orderless-component-separator #'identity
      orderless-matching-styles '(orderfull))

(I haven't tested that because I'm away from my computer).

I have to say, it is odd to get a request to make orderless into its exact opposite, fully-ordered!

oantolin avatar Mar 08 '25 01:03 oantolin

I have to say, it is odd to get a request to make orderless into its exact opposite, fully-ordered!

It is, isn't it? :)

But I've long been under the impression that it's a name that suggests one reason why someone may want to install it, but your engine is quite general and flexible. (And performant, and low LoC... a piece of art!) Plus it already ships at least one orderful dispatcher, orderless-initialisms.

I'll play with this snippet and report back, thanks for the starting point!

meedstrom avatar Mar 08 '25 07:03 meedstrom

I still haven't test d that code, but just now spotted an error: the separator function is meant to return a list of strings, so it should be list rather than idenity.

oantolin avatar Mar 08 '25 14:03 oantolin

I was thinking (string-to-list component) but that hadn't worked. Changing separator function to list does seem to do the trick!

meedstrom avatar Mar 08 '25 14:03 meedstrom

Great, so that's how you get the default Ivy behavior. Thanks a lot!

Interestingly the S-SPC command from Vertico wiki does not let you match from the beginning of a line again.

meedstrom avatar Mar 08 '25 14:03 meedstrom

By the way, the default Emacs completion system let's you search among completions with isearch, and isearch let's you treat spaces as .*. So if you gave up Vertico and Orderless, this functionality would be easy to get! 😛

oantolin avatar Mar 08 '25 15:03 oantolin

isearch let's you treat spaces as .*

Didn't know that! But still sounds like it'd involve extra keypresses.

In any case, without the ability to narrow with S-SPC on occasion, orderful is not so good. It'd be like using orderless without any of the dispatchers. Or flx only. One needs some ability to "switch style" regardless of what is the default style.

meedstrom avatar Mar 09 '25 19:03 meedstrom

Another option would be to adjust orderless--compile (or maybe orderless-compile) appropriately:

(defvar orderless-orderfull t)

(defun orderless--compile (string table pred)
  "Compile STRING to a prefix and a list of regular expressions.
The predicate PRED is used to constrain the entries in TABLE."
  (pcase-let* ((limit (car (completion-boundaries string table pred "")))
               (prefix (substring string 0 limit))
               (pattern (substring string limit))
               (`(,fun . ,regexps) (orderless-compile pattern)))
    (list prefix
          (if orderless-orderfull
              (list (string-join regexps ".*"))
            regexps)
          (orderless--ignore-case-p pattern)
          (orderless--predicate-normalized-and pred fun))))

@oantolin How would you feel about such an addition? The name orderless-orderfull is a bit awkward. Better suggestions?

minad avatar Mar 17 '25 16:03 minad

I would prefer not to modifiy orderless--compile in this way, @minad. Since @meedstrom wishes to be able to easily switch between the two behaviors, I would recommend choosing two different characters, one for orderless matching and one for ordered matching. For example, let's say we keep SPC for orderless and use ; for ordered matching. Then we only need a simple dispatcher:

(defun orderless-sequential-dispatch (component _index _total)
  "If COMPONENT contains semi-colons, split on them and match sequentially."
  (when (string-match-p ";" component)
    (cons 'orderless-regexp
          (rx-to-string
           (orderless--separated-by '(zero-or-more nonl)
            (string-split component ";"))))))

(This version considers the semi-colon-separated parts to be literals, and wraps each one in a captura grupo so that each gets highlighted a different color.)

oantolin avatar Mar 17 '25 20:03 oantolin

Of course, if we required an initial or final semi-colon, this could be made part of orderless-affix-dispatch. I wrote it differently to have a lighter weight syntax (which is similar to what I use in my personal configuration for orderless-prefixes: I have dispatcher that uses orderless-prefixes if, roughly speaking, the component contains dashes, slashes or dots).

oantolin avatar Mar 18 '25 01:03 oantolin

@oantolin I don't think that dispatchers are the solution since then the orderless-regexp style is fixed and you don't profit from the various other matching styles. It seems to me one has to hook into the compiler, joining the regexps at the very end. I am not saying that we have to add this feature, but if we do, I would provide a fully featured version if it is possible with little code. We can also declare orderfull behaviour out of scope and @meedstrom can use an advice or an alternative completion style. The style is called orderless after all.

minad avatar Mar 18 '25 05:03 minad

Regarding switching of options - this is a general problem which we do not support well in Orderless. Maybe we should invent a mechanism for it, e.g., some control characters at the very beginning. Alternatively what might work as DWIM is the following:

(setq completion-styles '(orderfull orderless basic)

;; with the orderless-orderfull defined above.
(orderless-define-completion-style orderfull
  (orderless-orderfull t))

This way orderfull behavior takes precedence. If no matches are found, orderless takes over.

minad avatar Mar 18 '25 05:03 minad

I don't think people would want this sequential behavior with anything other than literals, @minad. But maybe I'm wrong about that and @meedstrom can correct me. I have only ever wanted the amount of sequential behavior already provided by the orderless-prefixes matching style (and we also have orderless-flex that does sequential matching and which is proof that I don't need to think something is useful to include it in Orderless!).

oantolin avatar Mar 18 '25 15:03 oantolin

This can be closed then, I think?

minad avatar Jul 26 '25 12:07 minad