summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mendler <mail@daniel-mendler.de>2024-09-02 16:30:28 +0200
committerDaniel Mendler <mail@daniel-mendler.de>2024-09-05 06:21:17 +0200
commita2eaed8f465a329c61421668f8168d6aaa2a5ebd (patch)
tree855a01ddd19d229ffc53826871301282fe488366
parentafaec1bb0513dd5cebfeb6f3891c69ec93f0c299 (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)
-rw-r--r--orderless.el75
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