diff options
| author | Daniel Mendler <mail@daniel-mendler.de> | 2024-09-02 16:30:28 +0200 |
|---|---|---|
| committer | Daniel Mendler <mail@daniel-mendler.de> | 2024-09-05 06:21:17 +0200 |
| commit | a2eaed8f465a329c61421668f8168d6aaa2a5ebd (patch) | |
| tree | 855a01ddd19d229ffc53826871301282fe488366 /orderless.el | |
| parent | afaec1bb0513dd5cebfeb6f3891c69ec93f0c299 (diff) | |
Add `orderless-expand-substring` for literal substring expansion
If the customization option `orderless-expand-substring` is set to
t, `orderless-try-completion` first tries to treat the input as
literal substring and tries to expand it. If literal substring
expansion fails, Orderless falls back to its regular behavior, and
checks if there exists a single unique match to expand to. The
option `orderless-expand-substring` is effective in the default
completion UI and Corfu when pressing TAB, but does not affect
Vertico. It makes the transition to Orderless a little friendlier
for users accustomed to the Emacs built-in `basic` and `substring`
completion styles.
As an alternative to `orderless-expand-substring` one could define
an alternative completion style `tab` as follows.
(add-to-list 'completion-styles-alist
'(tab completion-substring-try-completion ignore
"Completion style which provides only TAB completion."))
I've used this `tab` configuration style for a long time in my
personal configuration, but the goal is to improve out of the box
behavior of Orderless and related packages. The following two
configurations are equivalent:
;; NEW: Use orderless-expand-substring
(setq completion-styles '(orderless basic)
orderless-expand-substring t)
;; OLD: Use the tab style from above.
(setq completion-styles '(tab orderless basic)
orderless-expand-substring nil)
Diffstat (limited to 'orderless.el')
| -rw-r--r-- | orderless.el | 75 |
1 files changed, 43 insertions, 32 deletions
diff --git a/orderless.el b/orderless.el index 97911be..187fd38 100644 --- a/orderless.el +++ b/orderless.el @@ -212,6 +212,15 @@ is determined by the values of `completion-ignore-case', `read-buffer-completion-ignore-case', as usual for completion." :type 'boolean) +(defcustom orderless-expand-substring t + "Whether to perform literal substring expansion. +If enabled, `orderless-try-completion' will first attempt literal +substring expansion via `completion-substring-try-completion'. +Otherwise expansion is only performed for single unique matches. +This configuration option affects the behavior of some completion +interfaces when pressing TAB." + :type 'boolean) + ;;; Matching styles (defun orderless-regexp (component) @@ -554,38 +563,40 @@ 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." - (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))))))) + (or (and orderless-expand-substring + (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 |
