diff options
| author | Omar Antolín <omar.antolin@gmail.com> | 2020-05-02 03:33:11 -0500 |
|---|---|---|
| committer | Omar Antolín <omar.antolin@gmail.com> | 2020-05-02 03:33:11 -0500 |
| commit | 5618c349a651dd43ea48f6c2edc023bd6e9b43a6 (patch) | |
| tree | bbf07cf378d6d905615ee23ea8a309af84094b12 | |
| parent | 9cebf2fc8cdcf40c89ab6b68b6f94699c9308323 (diff) | |
Remove global dispatchers
| -rw-r--r-- | README.org | 56 | ||||
| -rw-r--r-- | orderless.el | 181 |
2 files changed, 117 insertions, 120 deletions
@@ -10,8 +10,8 @@ any one of several ways: literally, as a regexp, as an initialism, in the flex style, or as multiple word prefixes. By default, regexp and initialism matches are enabled. -A completion style is a backend for completion and is used from a -frontend that provides a completion UI. Any completion style can be +A completion style is a back-end for completion and is used from a +front-end that provides a completion UI. Any completion style can be used with the default Emacs completion UI (sometimes called minibuffer tab completion) or with the built-in Icomplete package (which is similar to the more well-known Ido Mode). To use a completion style in @@ -145,23 +145,15 @@ string. For more fine-grained control on which matching styles to use for each component of the input string, you can add use /style - dispatchers/. These are specificied in the + dispatchers/. These are also specified in the variable =orderless-component-matching-styles= whose full syntax is: - =(= /matching-styles/... - =:global-dispatchers= /global-dispatchers/... - =:component-dispatchers= /component-dispatchers/... =)= + =(= /matching-styles/... =:dispatchers= /style-dispatchers/... =)= - There are two types of style dispatchers: - - - /global style dispatchers/, which are functions that take the entire - input string and are used to determine which matching styles to use - by default for each component; and - - - /component style dispatchers/, which take a component, its index in - the list of components (starting from 0), and the total number of - components, and are used to determine the matching styles used for - that specific component, overriding the default matching styles. + Style dispatchers are functions which take a component, its index in + the list of components (starting from 0), and the total number of + components, and are used to determine the matching styles used for + that specific component, overriding the default matching styles. A style dispatcher can either decline to handle the input string or component, or it can return which matching styles to use. It can @@ -172,9 +164,6 @@ string. As an example, say you wanted the following setup: - you normally want components to match as regexps, - - but if you end the string with =!= you want the default to be that - components (of the string left removing the final =!=) match - literally, - except for the first component, which should always match as an initialism ---this is pretty useful for, say, =execute-extended-command= (=M-x=) or =describe-function= (=C-h f=), @@ -188,20 +177,11 @@ string. (when (string-suffix-p "~" pattern) `(orderless-flex . ,(substring pattern 0 -1)))) - (defun literal-if-bang (pattern) - (when (string-suffix-p "!" pattern) - `(orderless-literal . ,(substring pattern 0 -1)))) - (defun first-initialism (pattern index _total) (if (= index 0) 'orderless-initialism)) (setq orderless-component-matching-styles - '(orderless-regexp orderless-initialism orderless-prefixes)) - - (setq orderless-component-matching-styles - '(orderless-regexp - :global-dispatchers literal-if-bang - :component-dispatchers first-initialism flex-if-twiddle)) + '(orderless-regexp :dispatchers first-initialism flex-if-twiddle)) #+end_src ** Component separator regexp @@ -242,12 +222,16 @@ completion is the one that ends up being used, of course. ** Pattern compiler -The default machanism for turning an input string into a list of +The default mechanism for turning an input string into a list of regexps to match against, configured using =orderless-component-matching-styles=, is probably flexible enough for the vast majority of users. But if you want to completely change the mechanism, customize the =orderless-pattern-compiler=. It's value should -be a function from string to lists of regexps. +be a function from string to lists of regexps. You might find it +convenient to use =orderless-default-pattern-compiler= as a subroutine +in your own pattern compiler, it conveniently accepts an optional +second argument that specifies a list to use instead of +=orderless-component-matching-styles=. ** Interactively changing the configuration @@ -284,7 +268,8 @@ components match literally. You could use the following configuration: (defun my/match-components-literally () "Components match literally for the rest of the session." (interactive) - (setq orderless-transient-matching-styles '(orderless-literal))) + (setq orderless-transient-matching-styles + '(orderless-literal :dispatchers))) (add-hook 'minibuffer-exit-hook #'orderless-remove-transient-configuration) @@ -293,6 +278,13 @@ components match literally. You could use the following configuration: #'my/match-components-literally) #+end_src +Note there is nothing after =:dispatchers= in the above code. This is +different from not including =:dispatchers= at all in the value of +=orderless-transient-matching-styles=: omitting it all together means +inherit the dispatchers from =orderless-component-matching-styles=; +while including =:dispatchers= overrides the list of dispatchers ---in +the example above, setting it to the empty list. + * Related packages ** Ivy and Helm diff --git a/orderless.el b/orderless.el index f3bca28..4b42c7b 100644 --- a/orderless.el +++ b/orderless.el @@ -125,36 +125,31 @@ function `orderless-remove-transient-configuration' to the (defcustom orderless-component-matching-styles '(orderless-regexp orderless-initialism) "Component matching style configuration. -This should be a list of functions optionally with the symbols -`:global-dispatchers' and `:component-dispatcher' used to delimit -portions: +This should be a list of matching styles or a list of the form: -\(matching-styles... - :global-dispatchers global-dispatchers... - :component-dispatcher component-dispatchers...) +\(matching-styles... :dispatchers dispatchers...) -Here matching-styles... denotes a sequence of matching style -functions, and each of the *-dispatcher... denotes a sequence of -style dispatcher functions. The `:global-dispatchers' and -`:component-dispatcher' sections are both optional and can occur -in either order. +containing matching styles, the symbol `:dispatchers', and style +dispatchers. If this variable is nil, regexp matching is assumed. A matching style is simply a function from strings to strings that takes a component to a regexp to match against. If the resulting regexp has no capturing groups, the entire match is -highlighted, otherwise just the captured groups are. - -The list of matching styles at the beginning provides the default -matching styles for components when the global style dispatchers -decline to compute a list of default matching styles. (Even if -those dispatchers do compute a list of matching styles, it is -only the default used for components, and can be overridden for -individual components by the component style dispatchers). - -For information on how the lists of dispatchers are used, see -`orderless-dispatch'." +highlighted, otherwise just the captured groups are. Several are +provided with this package: try customizing this variable to see +a list of them. + +The style dispatchers, if present, are used to override to the +matching styles based on the actual component and its place in +the list of components. For example, a style dispatcher could +arrange for the first component to match as an initialism and +subsequent components to match as literals. As another example, +a style dispatcher could arrange for a component starting with +`?' to match the rest of the component in the `orderless-flex' +style. For more information on how this variable is used see +`orderless-default-pattern-compiler'." :type '(set (const :tag "Regexp" orderless-regexp) (const :tag "Literal" orderless-literal) @@ -166,23 +161,29 @@ For information on how the lists of dispatchers are used, see orderless-strict-full-initialism) (const :tag "Flex" orderless-flex) (const :tag "Prefixes" orderless-prefixes) - (const :tag "Global dispatchers" :global-dispatchers) - (const :tag "Component dispatchers" :component-dispatchers) + (const :tag "Start dispatchers" :dispatchers) (function :tag "Custom function")) :group 'orderless) (defcustom orderless-transient-matching-styles nil "Component matching style configuration override. -This variable has the format and meaning as -`orderless-component-matching-styles' and overrides it when this -one is non-nil. It is meant to be set by commands that -interactively change the matching style configuration. No such -commands are provided with this package, but this variable is -meant to make writing them simple. If you do use this variable -you are likely to want to reset it to nil after every completion -session, which can be achieved by adding the function -`orderless-remove-transient-configuration' to the -`minibuffer-exit-hook'." +This has the format as `orderless-component-matching-styles' and +overrides it when this one is non-nil. It is meant to be set by +commands that interactively change the matching style +configuration. No such commands are provided with this package, +but this variable is meant to make writing them simple. If you +do use this variable you are likely to want to reset it to nil +after every completion session, which can be achieved by adding +the function `orderless-remove-transient-configuration' to the +`minibuffer-exit-hook'. + +If this variable doesn't not include a `:dispatchers' section, +then the dispatchers in `orderless-component-matching-styles' are +used instead. To indicate you want to use no style dispatchers +at all, include an empty dispatchers section, for example: + +\(setq `orderless-transient-matching-styles' + '(orderless-literal :dispatchers))" :type 'sexp :group 'orderless) @@ -323,32 +324,22 @@ Meant to be added to `exit-minibuffer-hook'." (setq orderless-transient-matching-styles nil orderless-transient-component-separator nil)) -(defun orderless--parse-matching-styles (configuration) +(defun orderless--styles+dispatchers (configuration) "Parse a matching styles CONFIGURATION. -The CONFIGURATION argument should be a list of functions -optionally with the symbols `:global-dispatchers' and -`:component-dispatcher' used to delimit portions: - -\(matching-styles... - :global-dispatchers global-dispatchers... - :component-dispatcher component-dispatchers...) - -Here matching-styles... denotes a sequence of matching style -functions, and each of the *-dispatcher... denotes a sequence of -style dispatcher functions. The `:global-dispatchers' and -`:component-dispatcher' sections are both optional and can occur -in either order. - -This function returns a 3-element lists of lists: the styles, the -global dispatchers and the component dispatchers." - (let ((result (vector (list) (list) (list))) - (type 0)) - (dolist (elt configuration) - (pcase elt - (:global-dispatchers (setq type 1)) - (:component-dispatchers (setq type 2)) - (_ (push elt (aref result type))))) - (mapcar #'nreverse result))) +The CONFIGURATION should be a list of matching styles or a list +of the form: + +\(matching-styles... :dispatchers dispatchers...) + +containing matching styles, the symbol `:dispatchers', and style +dispatchers. + +This function returns a `cons' whose `car' is the list of +matching styles, and whose `cdr' is the list of style +dispatchers." + (cons + (cl-loop for x in configuration until (eq x :dispatchers) collect x) + (cdr (memq :dispatchers configuration)))) (defun orderless-dispatch (dispatchers default string &rest args) "Run DISPATCHERS to compute matching styles for STRING. @@ -393,42 +384,56 @@ DEFAULT as the list of styles." when result return (cons result string) finally (return (cons default string)))) -(defun orderless-default-pattern-compiler (pattern) +(defun orderless-inherit-defaults (config) + "Combine CONFIG with `orderless-component-matching-styles'. +If CONFIG is nil, return `orderless-component-matching-styles'. +If CONFIG is non-nil, but does not include `:dispatchers', +inherit them from `orderless-component-matching-styles'. +Otherwise return CONFIG." + (cond + ((null config) + (or orderless-component-matching-styles 'orderless-regexp)) + ((memq :dispatchers config) + config) + (t (append config + (memq :dispatchers orderless-component-matching-styles))))) + +(defun orderless-default-pattern-compiler (pattern &optional config) "Build regexps to match the components of PATTERN. Split PATTERN on `orderless-component-separator' and compute -matching styles for each component. The matching styles are -computed according to `orderless-component-matching-styles', -unless the variable `orderless-transient-matching-styles' is -non-nil, in which case it is used instead. Whichever variable is -used is split into a list of default matching styles, a list of -global dispatchers and a list of component dispatchers. For each -component of the PATTERN, the component dispatchers are run to -determine the matching styles to be used for that component. If -the component dispatchers decline to handle the component, then -the global dispatchers are run on the PATTERN to determine -matching styles. Finally, if the global dispatchers decline to -handle the PATTERN, the list of default matching styles is used. - -See `orderless-dispatch' for details on how the lists of -dispatchers are used. - -This is the default value of `orderless-pattern-compiler'." +matching styles for each component. The matching styles are +computed according to CONFIG (more precisely, by the result of +applying `orderless-inherit-defaults' to CONFIG), which is split +into a list of default matching styles, and a list of style +dispatchers. For each component of the PATTERN, the style +dispatchers are run to determine the matching styles to be used +for that component, they are called with arguments the component, +the 0-based index of the component and the total number of +components. If the component dispatchers decline to handle the +component, then the list of default matching styles is used. See +`orderless-dispatch' for details on dispatchers. + +The CONFIG defaults to `orderless-component-matching-styles', +unless overriden by `orderless-transient-matching-styles'. More +precisely, it defaults to: + +\(orderless-inherit-defaults `orderless-transient-matching-styles'). + +This function is the default for `orderless-pattern-compiler' and +might come in handy as a subroutine to implement other pattern +compilers." + (unless config (setq config orderless-transient-matching-styles)) + (setq config (orderless-inherit-defaults config)) (cl-loop - with (matching-styles global-dispatchers component-dispatchers) = - (orderless--parse-matching-styles - (or orderless-transient-matching-styles - orderless-component-matching-styles)) - with (default . newpat) = (orderless-dispatch - global-dispatchers - (or matching-styles 'orderless-regexp) - pattern) - with components = (split-string newpat orderless-component-separator) + with (matching-styles . style-dispatchers) = + (orderless--styles+dispatchers config) + with components = (split-string pattern orderless-component-separator) with total = (length components) for component in components and index from 0 for (styles . newcomp) = (orderless-dispatch - component-dispatchers - default component index total) + style-dispatchers matching-styles + component index total) collect (if (functionp styles) (funcall styles newcomp) |
