oantolin / orderless

Emacs completion style that matches multiple regexps in any order

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add simple affix dispatcher

minad opened this issue · comments

Hi @oantolin,

I have the following dispatcher in my configuration:

(defvar orderless-default-dispatch-alist
  `((?% . ,#'char-fold-to-regexp)
    (?! . ,#'orderless-without-literal)
    (?, . ,#'orderless-initialism)
    (?= . ,#'orderless-literal)
    (?~ . ,#'orderless-flex))
  "Prefix and suffix characters corresponding to an Orderless style.")

(defun orderless-default-dispatch (word _index _total)
  (cond
   ;; Ignore single without literal dispatcher
   ((and
     (length= word 1)
     (equal (aref word 0)
            (car (rassq #'orderless-without-literal orderless-default-dispatch-alist))))
    '(orderless-literal . ""))
   ;; Prefix and suffix
   ((when-let ((style (alist-get (aref word 0) orderless-default-dispatch-alist)))
      (cons style (substring word 1))))
   ((when-let ((style (alist-get (aref word (1- (length word))) orderless-default-dispatch-alist)))
      (cons style (substring word 0 -1))))))

I wonder if it makes sense to add this to Orderless by default. One could either leave the orderless-default-dispatch-alist empty or not register orderless-default-dispatch with orderless-style-dispatchers by default in order to preserve the current behavior.

How would you feel about this addition? Maybe it is wiki material? On the other hand, it is not much code and the code here is generic and reusable. Orderless is comparatively difficult to configure, since you have to write Elisp. With this addition, the user would have to only adjust orderless-default-dispatch-alist via the customize interface. See also #83.

One could also make the dispatcher slightly more general with a configuration which allows you to configure prefix and suffix separately:

(defvar orderless-default-dispatch-affixes
  `((?%  ?%  ,#'char-fold-to-regexp)
    (?!  nil ,#'orderless-without-literal)
    (?,  ?,  ,#'orderless-initialism)
    (nil ?=  ,#'orderless-literal)
    (nil ?~  ,#'orderless-flex)))

But that's probably overdoing it and users who want such special behavior can always write their own dispatcher. The goal here is to provide a simple dispatcher which would work for 90% of the users, in particular beginners starting with Orderless/Vertico etc.

Sure, I'll add it. I see no harm in adding such a dispatcher, it won't mess up the configuration of people who already have dispatchers set up (unless they add them to orderless-style-dispatchers rather than setting the variable, but that seems very unlikely). I just need to document it and give orderless-default-dispatch-alist a nice custom type.

Okay, great. I also think that the addition is not harmful, since it does not add much code. It should also resolve #83. The only thing which remains is the bikeshedding discussion regarding the name of the dispatcher.

  • orderless-affix-dispatcher
  • orderless-char-dispatcher
  • orderless-simple-dispatcher
  • orderless-default-dispatcher
  • ...

What do you think?

I guess orderless-affix-dispatcher is the most descriptive.

Editing the title to reflect the status of the discussion ;)

Done. Please take a look at the docstring and changes to the manual, if you can, to see if things are clear.

@oantolin Thanks, looks good, except for two small details. I commented directly in the commit. Please take a look.

Thanks for pointing those out!

Btw, regarding length= what do you think about using Compat? It won't be useful for Orderless, but it may make sense to take advantage of it in Embark. I use it in all my packages (including the smaller ones), but that's of course my personal bias.

It is used by the current development version of Magit (and other packages by Jonas). It will likely be used by Org too in the future, see https://lists.gnu.org/archive/html/emacs-orgmode/2023-01/msg00919.html. At this point the flood gates are open and Compat will be like an established standard library which is around anyway. This also makes sense given that Compat just implements parts of the standard library.

EDIT: Forgot to mention, I already added Compat to Marginalia.

I've been thinking about using it for Embark and maybe removing the embark-define-keymap macro in favor of defvar-keymap.

I've been thinking about using it for Embark and maybe removing the embark-define-keymap macro in favor of defvar-keymap.

Yes, it is good idea to get rid of this macro (better sooner than later). In retrospect it was a mistake to make this public. I've seen many downstream packages which integrated Embark support to start depending on Embark solely because of embark-define-keymap. In all these cases I had to intercept when the packages got proposed for MELPA. Iirc it happened basically for every single package at their first Embark integration attempt. :-P

Multiple packages integrate with Embark now in the correct way, via only a few lines of with-eval-after-load and without depending on Embark. See for example Prot's TMR, where I added support:

https://github.com/protesilaos/tmr/blob/9db3306908dbbeed948438c8a04445e98e684f68/tmr.el#L480-L505