diff options
| author | Omar Antolín <omar.antolin@gmail.com> | 2020-05-02 14:20:10 -0500 |
|---|---|---|
| committer | Omar Antolín <omar.antolin@gmail.com> | 2020-05-02 14:20:10 -0500 |
| commit | 42bca066b975561bfbe87a6c0df81110dea32eeb (patch) | |
| tree | 0fd8348ce85b62708a431f474a52244df79f90bd | |
| parent | 5618c349a651dd43ea48f6c2edc023bd6e9b43a6 (diff) | |
Split dispatchers into their own variabledispatcher
| -rw-r--r-- | README.org | 86 | ||||
| -rw-r--r-- | orderless.el | 227 |
2 files changed, 137 insertions, 176 deletions
@@ -133,22 +133,15 @@ define new matching styles. The predefined ones are: For example, =re-re= matches =query-replace-regexp=, =recode-region= and =magit-remote-list-refs=; =f-d.t= matches =final-draft.txt=. -The variable =orderless-component-matching-styles= can be set to a list -of the desired matching styles to use. By default it enables the -regexp and initialism styles. - -That variable, in addition to matching styles, can contain dispatchers -that can change which styles are used depending on the actual input -string. +The variable =orderless-matching-styles= can be set to a list of the +desired matching styles to use. By default it enables the regexp and +initialism styles. *** Style dispatchers 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 also specified in the variable - =orderless-component-matching-styles= whose full syntax is: - - =(= /matching-styles/... =:dispatchers= /style-dispatchers/... =)= + each component of the input string, you can customize the variable + =orderless-style-dispatchers=. Style dispatchers are functions which take a component, its index in the list of components (starting from 0), and the total number of @@ -180,8 +173,8 @@ string. (defun first-initialism (pattern index _total) (if (= index 0) 'orderless-initialism)) - (setq orderless-component-matching-styles - '(orderless-regexp :dispatchers first-initialism flex-if-twiddle)) + (setq orderless-matching-styles '(orderless-regexp) + orderless-style-dispatchers '(first-initialism flex-if-twiddle)) #+end_src ** Component separator regexp @@ -197,16 +190,6 @@ If you are implementing a command for which you know you want a different separator for the components, bind =orderless-component-separator= in a =let= form. -The package also provides a command -=orderless-temporarily-change-separator= to change it for the rest of -the current completion session. If you want to use it, bind it to a -key in a keymap that will be active during your completion session: - -- Icomplete users should bind it in =icomplete-minibuffer-map=. -- Users of the default completion should bind it in both - =minibuffer-local-completion-map= and - =minibuffer-local-filename-completion-map=. - ** Faces for component matches The portions of a candidate matching each component get highlighted in @@ -223,15 +206,14 @@ completion is the one that ends up being used, of course. ** Pattern compiler 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. 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=. +regexps to match against, configured using =orderless-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. You might find it convenient to use +=orderless-default-pattern-compiler= as a subroutine in your own pattern +compiler, it conveniently accepts optional arguments that specify +lists to use instead of =orderless-matching-styles=. ** Interactively changing the configuration @@ -244,23 +226,25 @@ for one of them, popup a [[https://github.com/abo-abo/hydra][hydra]] to choose a Rather than include commands for any of those on-the-fly configuration changes, =orderless= provides a general mechanism to make it easy to -write such commands yourself. There are two "override" variables: - -- =orderless-transient-matching-styles= which, if non-nil, overrides - =orderless-component-matching-styles=, and -- =orderless-transient-component-separator= which, if non-nil, - overrides =orderless-component-separator=. - -You can write your own commands to set these transient variable to the -desired value without clobbering the value of the variables they -override. To set them to =nil= again after each completion session, use -the following configuration: +write such commands yourself. For each variable you might to +temporarily change there is a corresponding /transient/ variable that +overrides it when the transient variable is non-nil. You can write +your own commands to set these transient variable to the desired value +without clobbering the value of the variables they override. To reset +the transient variables to =nil= again after each completion session, +use the following configuration: #+begin_src emacs-lisp (add-hook 'minibuffer-exit-hook #'orderless-remove-transient-configuration) #+end_src +The transient variables provided are: + +- =orderless-transient-component-separator= +- =orderless-transient-matching-styles= +- =orderless-transient-style-dispatchers= + For example, say you want to use the keybinding =C-l= to make all components match literally. You could use the following configuration: @@ -268,8 +252,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 :dispatchers))) + (setq orderless-transient-matching-styles '(orderless-literal) + orderless-transient-style-dispatchers nil)) (add-hook 'minibuffer-exit-hook #'orderless-remove-transient-configuration) @@ -278,12 +262,10 @@ 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. +Note that we also set =orderless-transient-style-dispatchers= to =nil=, to +ensure the literal matching does not get overridden. You may want to +allow dispatcher overrides, in which case you'd simply remove that +assignment. * Related packages diff --git a/orderless.el b/orderless.el index 4b42c7b..bdb8c93 100644 --- a/orderless.el +++ b/orderless.el @@ -46,8 +46,8 @@ ;; literally, as a regexp, as an initialism, in the flex style, or as ;; word prefixes. It is easy to add new styles: they are functions ;; from strings to strings that map a component to a regexp to match -;; against. The variable `orderless-component-matching-styles' lists -;; the matching styles to be used for components, by default it allows +;; against. The variable `orderless-matching-styles' lists the +;; matching styles to be used for components, by default it allows ;; regexp and initialism matching. ;;; Code: @@ -100,13 +100,12 @@ component regexps." :group 'orderless) (defcustom orderless-transient-component-separator nil - "Override for `orderless-component-separator'. -This variable should be either nil or a regexp, when it is a -regexp it overrides `orderless-component-separator'. It is meant -to be set by commands that interactively change the separator. -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 + "Component separator regexp override. +This variabel, if non-nil, overrides `orderless-component-separator'. +It is meant to be set by commands that interactively change the +separator. 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'." @@ -122,16 +121,13 @@ function `orderless-remove-transient-configuration' to the :type '(vector 'face) :group 'orderless) -(defcustom orderless-component-matching-styles - '(orderless-regexp orderless-initialism) - "Component matching style configuration. -This 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. +(define-obsolete-variable-alias + 'orderless-component-matching-styles 'orderless-matching-styles + "20200502") +(defcustom orderless-matching-styles + '(orderless-regexp orderless-initialism) + "List of component matching styles. If this variable is nil, regexp matching is assumed. A matching style is simply a function from strings to strings @@ -139,52 +135,66 @@ 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. 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 +a list of them." + :type 'hook + :options '(orderless-regexp + orderless-literal + orderless-initialism + orderless-strict-initialism + orderless-strict-leading-initialism + orderless-strict-full-initialism + orderless-prefixes + orderless-flex) + :group 'orderless) + +(defcustom orderless-style-dispatchers nil + "List of style dispatchers. +Style dispatchers are used to override to the matching styles +based on the actual component and its place in the list of +components. A style dispatcher is a function that takes a string +and two integers as arguments, it gets called with a component, +the 0-based index of the component and the total number of +components. It can decides what matching styles to use for the +component and otionally replace the component with a different +string, or it can decline to handle the component leaving it for +future dispatchers. For details see `orderless-dispatch'. + +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) - (const :tag "Initialism" orderless-initialism) - (const :tag "Strict initialism" orderless-strict-initialism) - (const :tag "Strict leading initialism" - orderless-strict-leading-initialism) - (const :tag "Strict full initialism" - orderless-strict-full-initialism) - (const :tag "Flex" orderless-flex) - (const :tag "Prefixes" orderless-prefixes) - (const :tag "Start dispatchers" :dispatchers) - (function :tag "Custom function")) + :type 'hook :group 'orderless) (defcustom orderless-transient-matching-styles nil - "Component matching style configuration override. -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 + "Component matching styles override. +This variable, if non-nil, overrides `orderless-matching-styles'. +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'." + :type 'hook + :group 'orderless) + +(defcustom orderless-transient-style-dispatchers nil + "Component style dispatchers override. +This variable, if non-nil, overrides `orderless-style-dispatchers'. +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'." + :type 'hook :group 'orderless) (defcustom orderless-pattern-compiler #'orderless-default-pattern-compiler @@ -196,10 +206,10 @@ the candidate to be considered a completion of the pattern. The default pattern compiler is probably flexible enough for most users. See `orderless-default-pattern-compiler' for details. -The documentation for `orderless-component-matching-styles' is -written assuming the default pattern compiler is used, if you -change the pattern compiler it can, of course, do anything and -need not consult this variable at all." +The documentation for `orderless-matching-styles' is written +assuming the default pattern compiler is used, if you change the +pattern compiler it can, of course, do anything and need not +consult this variable at all." :type 'function :group 'orderless) @@ -309,7 +319,7 @@ Warning: only use this if you know all REGEXPs match!" Warning: only use this if you know all REGEXPs match all STRINGS! For the user's convenience, if REGEXPS is a string, it is converted to a list of regexps according to the value of -`orderless-component-matching-styles'." +`orderless-matching-styles'." (when (stringp regexps) (setq regexps (funcall orderless-pattern-compiler regexps))) (cl-loop for original in strings @@ -324,23 +334,6 @@ Meant to be added to `exit-minibuffer-hook'." (setq orderless-transient-matching-styles nil orderless-transient-component-separator nil)) -(defun orderless--styles+dispatchers (configuration) - "Parse a matching styles CONFIGURATION. -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. @@ -384,62 +377,48 @@ DEFAULT as the list of styles." when result return (cons result string) finally (return (cons default string)))) -(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) +(defun orderless-default-pattern-compiler (pattern &optional styles dispatchers) "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 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. +matching styles for each component. For each component the style +DISPATCHERS are run to determine the matching styles to be used; +they are called with arguments the component, the 0-based index +of the component and the total number of components. If the +DISPATCHERS decline to handle the component, then the list of +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: +The STYLES default to `orderless-matching-styles', and the +DISPATCHERS default to `orderless-dipatchers'. Since nil gets you +the default, if want to no dispatchers to be run, use '(ignore) +as the value of DISPATCHERS. -\(orderless-inherit-defaults `orderless-transient-matching-styles'). +The `orderless-transient-*' variables, when non-nil, override the +corresponding value among `orderless-component-separator', STYLES +and DISPATCHERS. 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)) + (unless styles (setq styles orderless-matching-styles)) + (setq styles (or orderless-transient-matching-styles styles)) + (unless dispatchers (setq dispatchers orderless-style-dispatchers)) + (setq dispatchers (or orderless-transient-style-dispatchers dispatchers)) (cl-loop - with (matching-styles . style-dispatchers) = - (orderless--styles+dispatchers config) - with components = (split-string pattern orderless-component-separator) + with components = (split-string + pattern + (or orderless-transient-component-separator + orderless-component-separator)) with total = (length components) for component in components and index from 0 - for (styles . newcomp) = (orderless-dispatch - style-dispatchers matching-styles - component index total) + for (newstyles . newcomp) = (orderless-dispatch + dispatchers styles component index total) collect - (if (functionp styles) - (funcall styles newcomp) + (if (functionp newstyles) + (funcall newstyles newcomp) (rx-to-string `(or - ,@(cl-loop for style in styles + ,@(cl-loop for style in newstyles collect `(regexp ,(funcall style newcomp)))))))) ;;; Completion style implementation |
