;;; +orderless.el --- Mostly from minad -*- lexical-binding: t; -*-

;;; Commentary:

;; See https://github.com/minad/consult/wiki#minads-orderless-configuration

;;; Code:

(require 'orderless)

;;; Dispataching

(defvar +orderless-dispatch-alist '((?% . char-fold-to-regexp)
                                    (?! . orderless-without-literal)
                                    (?` . orderless-initialism)
                                    (?= . orderless-literal)
                                    (?~ . orderless-flex))
  "Charcters to dispatch styles on orderless segments.")

(defun +orderless-dispatch (pattern index _total)
  "Dispatch orderless segments of a search string.
Dispatchers are taken from `+orderless-dispatch-alist', and added
to the following defaults:

- regexp$ :: matches REGEXP at the end of the pattern.
- .ext    :: matches EXT (at end of pattern)

Dispatch characters can be added at the beginning or ending of a
segment to make that segment match accordingly."
  (cond
   ;; Ensure that $ works with Consult commands, which add disambiguation
   ;; suffixes
   ((string-suffix-p "$" pattern)
    (cons 'orderless-regexp
          (concat (substring pattern 0 -1) "[\x100000-\x10FFFD]*$")))
   ;; File extensions
   ((and
     ;; Completing filename or eshell
     (or minibuffer-completing-file-name
         (derived-mode-p 'eshell-mode))
     ;; File extension
     (string-match-p "\\`\\.." pattern))
    (cons 'orderless-regexp
          (concat "\\." (substring pattern 1) "[\x100000-\x10FFFD]*$")))
   ;; Ignore single !
   ((string= "!" pattern) `(orderless-literal . ""))
   ;; Prefix and suffix
   ((if-let (x (assq (aref pattern 0) +orderless-dispatch-alist))
        (cons (cdr x) (substring pattern 1))
      (when-let (x (assq (aref pattern (1- (length pattern)))
                         +orderless-dispatch-alist))
        (cons (cdr x) (substring pattern 0 -1)))))))

(orderless-define-completion-style +orderless-with-initialism
  (orderless-matching-styles '(orderless-initialism
                               orderless-literal
                               orderless-regexp)))

(provide '+orderless)
;;; +orderless.el ends here
