aboutsummaryrefslogtreecommitdiff
path: root/.config/emacs/lisp/minadstack/orderless.el
diff options
context:
space:
mode:
Diffstat (limited to '.config/emacs/lisp/minadstack/orderless.el')
-rw-r--r--.config/emacs/lisp/minadstack/orderless.el672
1 files changed, 672 insertions, 0 deletions
diff --git a/.config/emacs/lisp/minadstack/orderless.el b/.config/emacs/lisp/minadstack/orderless.el
new file mode 100644
index 0000000..7cee5c8
--- /dev/null
+++ b/.config/emacs/lisp/minadstack/orderless.el
@@ -0,0 +1,672 @@
+;;; orderless.el --- Completion style for matching regexps in any order -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2026 Free Software Foundation, Inc.
+
+;; Author: Omar Antolín Camarena <omar@matem.unam.mx>
+;; Maintainer: Omar Antolín Camarena <omar@matem.unam.mx>, Daniel Mendler <mail@daniel-mendler.de>
+;; Keywords: matching, completion
+;; Version: 1.6
+;; URL: https://github.com/oantolin/orderless
+;; Package-Requires: ((emacs "27.1") (compat "30"))
+
+;; This file is part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package provides an `orderless' completion style that divides
+;; the pattern into components (space-separated by default), and
+;; matches candidates that match all of the components in any order.
+
+;; Completion styles are used as entries in the variables
+;; `completion-styles' and `completion-category-overrides', see their
+;; documentation.
+
+;; To use this completion style you can use the following minimal
+;; configuration:
+
+;; (setq completion-styles '(orderless basic))
+
+;; You can customize the `orderless-component-separator' to decide how
+;; the input pattern is split into component regexps. The default
+;; splits on spaces. You might want to add hyphens and slashes, for
+;; example, to ease completion of symbols and file paths,
+;; respectively.
+
+;; Each component can match in any one of several matching styles:
+;; 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-matching-styles' lists the
+;; matching styles to be used for components, by default it allows
+;; literal and regexp matching.
+
+;;; Code:
+
+(require 'compat)
+(eval-when-compile (require 'cl-lib))
+
+(defgroup orderless nil
+ "Completion method that matches space-separated regexps in any order."
+ :link '(info-link :tag "Info Manual" "(orderless)")
+ :link '(url-link :tag "Website" "https://github.com/oantolin/orderless")
+ :link '(emacs-library-link :tag "Library Source" "orderless.el")
+ :group 'minibuffer)
+
+(defface orderless-match-face-0
+ '((default :weight bold)
+ (((class color) (min-colors 88) (background dark)) :foreground "#72a4ff")
+ (((class color) (min-colors 88) (background light)) :foreground "#223fbf")
+ (t :foreground "blue"))
+ "Face for matches of components numbered 0 mod 4.")
+
+(defface orderless-match-face-1
+ '((default :weight bold)
+ (((class color) (min-colors 88) (background dark)) :foreground "#ed92f8")
+ (((class color) (min-colors 88) (background light)) :foreground "#8f0075")
+ (t :foreground "magenta"))
+ "Face for matches of components numbered 1 mod 4.")
+
+(defface orderless-match-face-2
+ '((default :weight bold)
+ (((class color) (min-colors 88) (background dark)) :foreground "#90d800")
+ (((class color) (min-colors 88) (background light)) :foreground "#145a00")
+ (t :foreground "green"))
+ "Face for matches of components numbered 2 mod 4.")
+
+(defface orderless-match-face-3
+ '((default :weight bold)
+ (((class color) (min-colors 88) (background dark)) :foreground "#f0ce43")
+ (((class color) (min-colors 88) (background light)) :foreground "#804000")
+ (t :foreground "yellow"))
+ "Face for matches of components numbered 3 mod 4.")
+
+(defcustom orderless-component-separator #'orderless-escapable-split-on-space
+ "Component separators for orderless completion.
+This can either be a string, which is passed to `split-string',
+or a function of a single string argument."
+ :type `(choice (const :tag "Spaces" " +")
+ (const :tag "Spaces, hyphen or slash" " +\\|[-/]")
+ (const :tag "Escapable space"
+ ,#'orderless-escapable-split-on-space)
+ (const :tag "Quotable spaces" ,#'split-string-and-unquote)
+ (regexp :tag "Custom regexp")
+ (function :tag "Custom function")))
+
+(defcustom orderless-match-faces
+ [orderless-match-face-0
+ orderless-match-face-1
+ orderless-match-face-2
+ orderless-match-face-3]
+ "Vector of faces used (cyclically) for component matches."
+ :type '(vector face))
+
+(defcustom orderless-matching-styles
+ (list #'orderless-literal #'orderless-regexp)
+ "List of component matching styles.
+If this variable is nil, regexp matching is assumed.
+
+A matching style is simply a function from strings to regexps.
+The returned regexps can be either strings or s-expressions in
+`rx' syntax. 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."
+ :type '(repeat function)
+ :options (list #'orderless-regexp
+ #'orderless-literal
+ #'orderless-initialism
+ #'orderless-prefixes
+ #'orderless-flex))
+
+(defcustom orderless-affix-dispatch-alist
+ `((?% . ,#'char-fold-to-regexp)
+ (?! . ,#'orderless-not)
+ (?& . ,#'orderless-annotation)
+ (?, . ,#'orderless-initialism)
+ (?= . ,#'orderless-literal)
+ (?^ . ,#'orderless-literal-prefix)
+ (?~ . ,#'orderless-flex))
+ "Alist associating characters to matching styles.
+The function `orderless-affix-dispatch' uses this list to
+determine how to match a pattern component: if the component
+either starts or ends with a character used as a key in this
+alist, the character is removed from the component and the rest is
+matched according the style associated to it."
+ :type `(alist
+ :key-type character
+ :value-type (choice
+ (const :tag "Annotation" ,#'orderless-annotation)
+ (const :tag "Literal" ,#'orderless-literal)
+ (const :tag "Without literal" ,#'orderless-without-literal)
+ (const :tag "Literal prefix" ,#'orderless-literal-prefix)
+ (const :tag "Regexp" ,#'orderless-regexp)
+ (const :tag "Not" ,#'orderless-not)
+ (const :tag "Flex" ,#'orderless-flex)
+ (const :tag "Initialism" ,#'orderless-initialism)
+ (const :tag "Prefixes" ,#'orderless-prefixes)
+ (const :tag "Ignore diacritics" ,#'char-fold-to-regexp)
+ (function :tag "Custom matching style"))))
+
+(defun orderless-affix-dispatch (component _index _total)
+ "Match COMPONENT according to the styles in `orderless-affix-dispatch-alist'.
+If the COMPONENT starts or ends with one of the characters used
+as a key in `orderless-affix-dispatch-alist', then that character
+is removed and the remainder of the COMPONENT is matched in the
+style associated to the character."
+ (let ((len (length component))
+ (alist orderless-affix-dispatch-alist))
+ (when (> len 0)
+ (cond
+ ;; Ignore single dispatcher character
+ ((and (= len 1) (alist-get (aref component 0) alist)) #'ignore)
+ ;; Prefix
+ ((when-let* ((style (alist-get (aref component 0) alist)))
+ (cons style (substring component 1))))
+ ;; Suffix
+ ((when-let* ((style (alist-get (aref component (1- len)) alist)))
+ (cons style (substring component 0 -1))))))))
+
+(defcustom orderless-style-dispatchers (list #'orderless-affix-dispatch)
+ "List of style dispatchers.
+Style dispatchers are used to override 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 decide what matching styles to use for the
+component and optionally 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. See
+`orderless-affix-dispatch' and `orderless-affix-dispatch-alist'
+for such a configuration. For more information on how this
+variable is used, see `orderless-compile'."
+ :type '(repeat function))
+
+(defcustom orderless-smart-case t
+ "Whether to use smart case.
+If this variable is t, then case-sensitivity is decided as
+follows: if any component contains upper case letters, the
+matches are case sensitive; otherwise case-insensitive. This
+is like the behavior of `isearch' when `search-upper-case' is
+non-nil.
+
+On the other hand, if this variable is nil, then case-sensitivity
+is determined by the values of `completion-ignore-case',
+`read-file-name-completion-ignore-case' and
+`read-buffer-completion-ignore-case', as usual for completion."
+ :type 'boolean)
+
+(defcustom orderless-expand-substring 'prefix
+ "Whether to perform literal substring expansion.
+This configuration option affects the behavior of some completion
+interfaces when pressing TAB. If enabled `orderless-try-completion'
+will first attempt literal substring expansion. If disabled,
+expansion is only performed for single unique matches. For
+performance reasons only `prefix' expansion is enabled by default.
+Set the variable to `substring' for full substring expansion."
+ :type '(choice (const :tag "No expansion" nil)
+ (const :tag "Substring" substring)
+ (const :tag "Prefix (efficient)" prefix)))
+
+;;; Matching styles
+
+(defun orderless-regexp (component)
+ "Match COMPONENT as a regexp."
+ (condition-case nil
+ (progn (string-match-p component "") component)
+ (invalid-regexp nil)))
+
+(defun orderless-literal (component)
+ "Match COMPONENT as a literal string."
+ ;; Do not use (literal component) here, such that `delete-dups' in
+ ;; `orderless--compile-component' has a chance to delete duplicates for
+ ;; literal input. The default configuration of `orderless-matching-styles'
+ ;; with `orderless-regexp' and `orderless-literal' leads to duplicates.
+ (regexp-quote component))
+
+(defun orderless-literal-prefix (component)
+ "Match COMPONENT as a literal prefix string."
+ `(seq bos (literal ,component)))
+
+(defun orderless--separated-by (sep rxs &optional before after)
+ "Return a regexp to match the rx-regexps RXS with SEP in between.
+If BEFORE is specified, add it to the beginning of the rx
+sequence. If AFTER is specified, add it to the end of the rx
+sequence."
+ (declare (indent 1))
+ `(seq
+ ,(or before "")
+ ,@(cl-loop for (sexp . more) on rxs
+ collect `(group ,sexp)
+ when more collect sep)
+ ,(or after "")))
+
+(defun orderless-flex (component)
+ "Match a component in flex style.
+This means the characters in COMPONENT must occur in the
+candidate in that order, but not necessarily consecutively."
+ `(seq
+ ,@(cdr (cl-loop for char across component
+ append `((zero-or-more (not ,char)) (group ,char))))))
+
+(defun orderless-initialism (component)
+ "Match a component as an initialism.
+This means the characters in COMPONENT must occur in the
+candidate, in that order, at the beginning of words."
+ (orderless--separated-by '(zero-or-more nonl)
+ (cl-loop for char across component collect `(seq word-start ,char))))
+
+(defun orderless-prefixes (component)
+ "Match a component as multiple word prefixes.
+The COMPONENT is split at word endings, and each piece must match
+at a word boundary in the candidate. This is similar to the
+`partial-completion' completion style."
+ (orderless--separated-by '(zero-or-more nonl)
+ (cl-loop for prefix in (split-string component "\\>")
+ collect `(seq word-boundary ,prefix))))
+
+(defun orderless-without-literal (component)
+ "Match strings that do *not* contain COMPONENT as a literal match.
+You may prefer to use the more general `orderless-not' instead
+which can invert any predicate or regexp."
+ `(seq
+ (group string-start) ; highlight nothing!
+ (zero-or-more
+ (or ,@(cl-loop for i below (length component)
+ collect `(seq ,(substring component 0 i)
+ (or (not (any ,(aref component i)))
+ string-end)))))
+ string-end))
+
+(defsubst orderless--match-p (pred regexp str)
+ "Return t if STR matches PRED and REGEXP."
+ (and str
+ (or (not pred) (funcall pred str))
+ (or (not regexp)
+ (let ((case-fold-search completion-ignore-case))
+ (string-match-p regexp str)))))
+
+(defun orderless-not (pred regexp)
+ "Match strings that do *not* match PRED and REGEXP."
+ (lambda (str)
+ (not (orderless--match-p pred regexp str))))
+
+(defun orderless--metadata ()
+ "Return completion metadata iff inside minibuffer."
+ (when-let* (((minibufferp))
+ (table minibuffer-completion-table))
+ ;; Return non-nil metadata iff inside minibuffer
+ (or (completion-metadata (buffer-substring-no-properties
+ (minibuffer-prompt-end) (point))
+ table minibuffer-completion-predicate)
+ '((nil . nil)))))
+
+(defun orderless-annotation (pred regexp)
+ "Match candidates where the annotation matches PRED and REGEXP."
+ (let ((md (orderless--metadata)))
+ (if-let* ((fun (compat-call completion-metadata-get md 'affixation-function)))
+ (lambda (str)
+ (cl-loop for s in (cdar (funcall fun (list str)))
+ thereis (orderless--match-p pred regexp s)))
+ (when-let* ((fun (compat-call completion-metadata-get md 'annotation-function)))
+ (lambda (str) (orderless--match-p pred regexp (funcall fun str)))))))
+
+;;; Highlighting matches
+
+(defun orderless--highlight (regexps ignore-case string)
+ "Destructively propertize STRING to highlight a match of each of the REGEXPS.
+The search is case insensitive if IGNORE-CASE is non-nil."
+ (cl-loop with case-fold-search = ignore-case
+ with n = (length orderless-match-faces)
+ for regexp in regexps and i from 0
+ when (string-match regexp string) do
+ (cl-loop
+ for (x y) on (let ((m (match-data))) (or (cddr m) m)) by #'cddr
+ when x do
+ (add-face-text-property
+ x y
+ (aref orderless-match-faces (mod i n))
+ nil string)))
+ string)
+
+(defun orderless-highlight-matches (regexps strings)
+ "Highlight a match of each of the REGEXPS in each of the STRINGS.
+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-matching-styles'."
+ (when (stringp regexps)
+ (setq regexps (cdr (orderless-compile regexps))))
+ (cl-loop with ignore-case = (orderless--ignore-case-p regexps)
+ for str in strings
+ collect (orderless--highlight regexps ignore-case (substring str))))
+
+;;; Compiling patterns to lists of regexps
+
+(defun orderless-escapable-split-on-space (string)
+ "Split STRING on spaces, which can be escaped with backslash."
+ (mapcar
+ (lambda (piece) (replace-regexp-in-string (string 0) " " piece))
+ (split-string (replace-regexp-in-string
+ "\\\\\\\\\\|\\\\ "
+ (lambda (x) (if (equal x "\\ ") (string 0) x))
+ string 'fixedcase 'literal)
+ " +")))
+
+(defun orderless--dispatch (dispatchers default string index total)
+ "Run DISPATCHERS to compute matching styles for STRING.
+
+A style dispatcher is a function that takes a STRING, component
+INDEX and the TOTAL number of components. It should either
+return (a) nil to indicate the dispatcher will not handle the
+string, (b) a new string to replace the current string and
+continue dispatch, or (c) the matching styles to use and, if
+needed, a new string to use in place of the current one (for
+example, a dispatcher can decide which style to use based on a
+suffix of the string and then it must also return the component
+stripped of the suffix).
+
+More precisely, the return value of a style dispatcher can be of
+one of the following forms:
+
+- nil (to continue dispatching)
+
+- a string (to replace the component and continue dispatching),
+
+- a matching style or non-empty list of matching styles to
+ return,
+
+- a `cons' whose `car' is either as in the previous case or
+ nil (to request returning the DEFAULT matching styles), and
+ whose `cdr' is a string (to replace the current one).
+
+This function tries all DISPATCHERS in sequence until one returns
+a list of styles. When that happens it returns a `cons' of the
+list of styles and the possibly updated STRING. If none of the
+DISPATCHERS returns a list of styles, the return value will use
+DEFAULT as the list of styles."
+ (cl-loop for dispatcher in dispatchers
+ for result = (funcall dispatcher string index total)
+ if (stringp result)
+ do (setq string result result nil)
+ else if (and (consp result) (null (car result)))
+ do (setf (car result) default)
+ else if (and (consp result) (stringp (cdr result)))
+ do (setq string (cdr result) result (car result))
+ when result return (cons result string)
+ finally (return (cons default string))))
+
+(defun orderless--compile-component (component index total styles dispatchers)
+ "Compile COMPONENT at INDEX of TOTAL components with STYLES and DISPATCHERS."
+ (cl-loop
+ with pred = nil
+ with (newsty . newcomp) = (orderless--dispatch dispatchers styles
+ component index total)
+ for style in (if (functionp newsty) (list newsty) newsty)
+ for res = (condition-case nil
+ (funcall style newcomp)
+ (wrong-number-of-arguments
+ (when-let* ((res (orderless--compile-component
+ newcomp index total styles dispatchers)))
+ (funcall style (car res) (cdr res)))))
+ if (functionp res) do (cl-callf orderless--predicate-and pred res)
+ else if res collect (if (stringp res) `(regexp ,res) res) into regexps
+ finally return
+ (when (or pred regexps)
+ (cons pred (and regexps (rx-to-string `(or ,@(delete-dups regexps)) t))))))
+
+(defun orderless-compile (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. 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 STYLES default to `orderless-matching-styles', and the
+DISPATCHERS default to `orderless-dipatchers'. Since nil gets
+you the default, if you want no dispatchers to be run, use
+\\='(ignore) as the value of DISPATCHERS.
+
+The return value is a pair of a predicate function and a list of
+regexps. The predicate function can also be nil. It takes a
+string as argument."
+ (unless styles (setq styles orderless-matching-styles))
+ (unless dispatchers (setq dispatchers orderless-style-dispatchers))
+ (cl-loop
+ with predicate = nil
+ with temp = (if (functionp orderless-component-separator)
+ (funcall orderless-component-separator pattern)
+ (split-string pattern orderless-component-separator))
+ with components = (if (equal (car (last temp)) "") (nbutlast temp) temp)
+ with total = (length components)
+ for comp in components and index from 0
+ for (pred . regexp) = (orderless--compile-component
+ comp index total styles dispatchers)
+ when regexp collect regexp into regexps
+ when pred do (cl-callf orderless--predicate-and predicate pred)
+ finally return (cons predicate regexps)))
+
+;;; Completion style implementation
+
+(defun orderless--predicate-normalized-and (p q)
+ "Combine two predicate functions P and Q with `and'.
+The first function P is a completion predicate which can receive
+up to two arguments. The second function Q always receives a
+normalized string as argument."
+ (cond
+ ((and p q)
+ (lambda (k &rest v) ;; v for hash table
+ (when (if v (funcall p k (car v)) (funcall p k))
+ (setq k (if (consp k) (car k) k)) ;; alist
+ (funcall q (if (symbolp k) (symbol-name k) k)))))
+ (q
+ (lambda (k &optional _) ;; _ for hash table
+ (setq k (if (consp k) (car k) k)) ;; alist
+ (funcall q (if (symbolp k) (symbol-name k) k))))
+ (p)))
+
+(defun orderless--predicate-and (p q)
+ "Combine two predicate functions P and Q with `and'."
+ (or (and p q (lambda (x) (and (funcall p x) (funcall q x)))) p q))
+
+(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 regexps (orderless--ignore-case-p pattern)
+ (orderless--predicate-normalized-and pred fun))))
+
+;; Thanks to @jakanakaevangeli for writing a version of this function:
+;; https://github.com/oantolin/orderless/issues/79#issuecomment-916073526
+(defun orderless--literal-prefix-p (regexp)
+ "Determine if REGEXP is a quoted regexp anchored at the beginning.
+If REGEXP is of the form \"\\`q\" for q = (regexp-quote u),
+then return (cons REGEXP u); else return nil."
+ (when (and (string-prefix-p "\\`" regexp)
+ (not (string-match-p "[$*+.?[\\^]"
+ (replace-regexp-in-string
+ "\\\\[$*+.?[\\^]" "" regexp
+ 'fixedcase 'literal nil 2))))
+ (cons regexp
+ (replace-regexp-in-string "\\\\\\([$*+.?[\\^]\\)" "\\1"
+ regexp 'fixedcase nil nil 2))))
+
+(defun orderless--ignore-case-p (regexps)
+ "Return non-nil if case should be ignored for REGEXPS."
+ (if orderless-smart-case
+ (cl-loop for regexp in (ensure-list regexps)
+ always (isearch-no-upper-case-p regexp t))
+ completion-ignore-case))
+
+(defun orderless--filter (prefix regexps ignore-case table pred)
+ "Filter TABLE by PREFIX, REGEXPS and PRED.
+The matching should be case-insensitive if IGNORE-CASE is non-nil."
+ ;; If there is a regexp of the form \`quoted-regexp then
+ ;; remove the first such and add the unquoted form to the prefix.
+ (pcase (cl-loop for r in regexps
+ thereis (orderless--literal-prefix-p r))
+ (`(,regexp . ,literal)
+ (setq prefix (concat prefix literal)
+ regexps (remove regexp regexps))))
+ (let ((completion-regexp-list regexps)
+ (completion-ignore-case ignore-case))
+ (all-completions prefix table pred)))
+
+(defun orderless-filter (string table &optional pred)
+ "Split STRING into components and find entries TABLE matching all.
+The predicate PRED is used to constrain the entries in TABLE."
+ (pcase-let ((`(,prefix ,regexps ,ignore-case ,pred)
+ (orderless--compile string table pred)))
+ (orderless--filter prefix regexps ignore-case table pred)))
+
+;;;###autoload
+(defun orderless-all-completions (string table pred _point)
+ "Split STRING into components and find entries TABLE matching all.
+The predicate PRED is used to constrain the entries in TABLE. The
+matching portions of each candidate are highlighted.
+This function is part of the `orderless' completion style."
+ (pcase-let ((`(,prefix ,regexps ,ignore-case ,pred)
+ (orderless--compile string table pred)))
+ (when-let* ((completions (orderless--filter prefix regexps ignore-case table pred)))
+ (if completion-lazy-hilit
+ (setq completion-lazy-hilit-fn
+ (apply-partially #'orderless--highlight regexps ignore-case))
+ (cl-loop for str in-ref completions do
+ (setf str (orderless--highlight regexps ignore-case (substring str)))))
+ (nconc completions (length prefix)))))
+
+;;;###autoload
+(defun orderless-try-completion (string table pred point)
+ "Complete STRING to unique matching entry in TABLE.
+This uses `orderless-all-completions' to find matches for STRING
+in TABLE among entries satisfying PRED. If there is only one
+match, it completes to that match. If there are no matches, it
+returns nil. In any other case it \"completes\" STRING to
+itself, without moving POINT.
+This function is part of the `orderless' completion style."
+ (or
+ (pcase orderless-expand-substring
+ ('nil nil)
+ ('prefix (completion-emacs21-try-completion string table pred point))
+ (_ (completion-substring-try-completion string table pred point)))
+ (catch 'orderless--many
+ (pcase-let ((`(,prefix ,regexps ,ignore-case ,pred)
+ (orderless--compile string table pred))
+ (one nil))
+ ;; Abuse all-completions/orderless--filter as a fast search loop.
+ ;; Should be almost allocation-free since our "predicate" is not
+ ;; called more than two times.
+ (orderless--filter
+ prefix regexps ignore-case table
+ (orderless--predicate-normalized-and
+ pred
+ (lambda (arg)
+ ;; Check if there is more than a single match (= many).
+ (when (and one (not (equal one arg)))
+ (throw 'orderless--many (cons string point)))
+ (setq one arg)
+ t)))
+ (when one
+ ;; Prepend prefix if the candidate does not already have the same
+ ;; prefix. This workaround is needed since the predicate may either
+ ;; receive an unprefixed or a prefixed candidate as argument. Most
+ ;; completion tables consistently call the predicate with unprefixed
+ ;; candidates, for example `completion-file-name-table'. In contrast,
+ ;; `completion-table-with-context' calls the predicate with prefixed
+ ;; candidates. This could be an unintended bug or oversight in
+ ;; `completion-table-with-context'.
+ (unless (or (equal prefix "")
+ (and (string-prefix-p prefix one)
+ (test-completion one table pred)))
+ (setq one (concat prefix one)))
+ (or (equal string one) ;; Return t for unique exact match
+ (cons one (length one))))))))
+
+;;;###autoload
+(add-to-list 'completion-styles-alist
+ '(orderless
+ orderless-try-completion orderless-all-completions
+ "Completion of multiple components, in any order."))
+
+(defmacro orderless-define-completion-style
+ (name &optional docstring &rest configuration)
+ "Define an orderless completion style with given CONFIGURATION.
+The CONFIGURATION should be a list of bindings that you could use
+with `let' to configure orderless. You can include bindings for
+`orderless-matching-styles' and `orderless-style-dispatchers',
+for example.
+
+The completion style consists of two functions that this macro
+defines for you, NAME-try-completion and NAME-all-completions.
+This macro registers those in `completion-styles-alist' as
+forming the completion style NAME.
+
+The optional DOCSTRING argument is used as the documentation
+string for the completion style."
+ (declare (doc-string 2) (indent 1))
+ (unless (stringp docstring)
+ (push docstring configuration)
+ (setq docstring nil))
+ (let* ((fn-name (lambda (string) (intern (concat (symbol-name name) string))))
+ (try-completion (funcall fn-name "-try-completion"))
+ (all-completions (funcall fn-name "-all-completions"))
+ (doc-fmt "`%s' function for the %s style.
+This function delegates to `orderless-%s'.
+The orderless configuration is locally modified
+specifically for the %s style.")
+ (fn-doc (lambda (fn) (format doc-fmt fn name fn name name))))
+ `(progn
+ (defun ,try-completion (string table pred point)
+ ,(funcall fn-doc "try-completion")
+ (let ,configuration
+ (orderless-try-completion string table pred point)))
+ (defun ,all-completions (string table pred point)
+ ,(funcall fn-doc "all-completions")
+ (let ,configuration
+ (orderless-all-completions string table pred point)))
+ (add-to-list 'completion-styles-alist
+ '(,name ,try-completion ,all-completions ,docstring)))))
+
+;;; Ivy integration
+
+;;;###autoload
+(defun orderless-ivy-re-builder (str)
+ "Convert STR into regexps for use with ivy.
+This function is for integration of orderless with ivy, use it as
+a value in `ivy-re-builders-alist'."
+ (or (mapcar (lambda (x) (cons x t)) (cdr (orderless-compile str))) ""))
+
+(defvar ivy-regex)
+(defun orderless-ivy-highlight (str)
+ "Highlight a match in STR of each regexp in `ivy-regex'.
+This function is for integration of orderless with ivy."
+ (orderless--highlight (mapcar #'car ivy-regex) t str) str)
+
+(provide 'orderless)
+;;; orderless.el ends here