Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

flex-x

flex-x is an Emacs completion style built on the built-in flex completion style.

Features

  • Order-independent flex AND filtering for whitespace-separated terms.
  • Literal matching for completion tables which explicitly preserve candidate order, avoiding noisy fuzzy matches when score sorting is disabled.
  • Sort by minibuffer history, then flex match quality.
  • Respect completion metadata which explicitly disables additional sorting.
  • Highlight matches with standard completion faces.
  • Add a regexp expander for non-ASCII candidates, for example migemo or pyim.

Screenshots

flex-x keeps the standard completion UI while adding flex AND-style filtering for whitespace-separated terms, history-aware ranking, match highlighting, and optional regexp expansion for non-ASCII candidates. These screenshots use the built-in fido-vertical-mode UI and the current commentary theme configuration from init.org; flex-x itself does not depend on either.

Screenshots/flex-x-history-before.png

Screenshots/flex-x-history-after.png

Screenshots/flex-x-migemo.png

Setup

flex-x is available from MELPA. After enabling the MELPA package archive, install and configure it with use-package. The icomplete-minibuffer-setup-hook binding mirrors the current init.org configuration used for the screenshots:

(use-package icomplete
  :ensure nil
  :init
  (fido-vertical-mode))

(use-package flex-x
  :ensure t
  :config
  (add-hook 'icomplete-minibuffer-setup-hook
            (lambda ()
              (setq-local completion-styles '(flex-x basic))))

  (setopt completion-styles '(flex-x basic)))

Some completion categories have built-in completion-category-overrides which can prepend or replace styles for that category. If you want flex-x to be preferred for those categories too, configure category overrides explicitly:

(setopt completion-category-overrides
        '((buffer (styles . (flex-x basic substring)))
          (project-file (styles . (flex-x substring)))))

For migemo-style matching, pass migemo-get-pattern directly:

(with-eval-after-load 'migemo
  (setq flex-x-extra-pattern-function #'migemo-get-pattern))

For pyim-style matching:

(with-eval-after-load 'pyim
  (require 'pyim-cregexp-utils nil t)
  (setq flex-x-extra-pattern-function #'pyim-cregexp-build))

By default, expanded regexp matching is used only for candidates containing non-ASCII characters. Customize flex-x-extra-match-nonascii-only if you want it to run for every candidate.

Every non-empty whitespace-separated term uses built-in flex matching, and every term must match the candidate. Terms may occur in any order. A configured regexp expander is used as an alternative when built-in flex does not match a term. Input containing only whitespace does not filter candidates.

If completion metadata sets a display or cycle sort function to identity, flex-x preserves the candidate order for that sort channel and uses literal matching even before a space is entered. This avoids returning large unsorted fuzzy match sets. The other sort channel continues to use its own metadata function or flex match quality.

In a completion minibuffer, flex-x displays [Fuzzy] or [Literal] immediately after the prompt. The indicator reflects the current matching mode even when there are no matching candidates. It is part of the protected minibuffer prompt, so it does not become part of the completion input.

When minibuffer completion does not provide an explicit sort function, flex-x first sorts by flex match quality and then stably promotes matching candidates from the active minibuffer history. Candidates outside the history keep their flex order. Explicit metadata sort functions and completion outside the minibuffer do not receive this history promotion.

Expanded regexp matching scans up to flex-x-extra-match-candidate-limit raw candidates for the current completion prefix. The default limit is 5000; when it is exceeded, flex-x stops predicate-driven enumeration and skips regexp expansion. Set it to nil if you want migemo or pyim expansion to scan every candidate even in very large completion tables. Ignored filename extensions are filtered after regexp expansion, so an ignored file remains available when it is the only match.

Corfu History Sorting

Corfu normally uses a completion table’s display-sort-function instead of corfu-sort-function. Since flex-x provides a display sort function, enabling corfu-history-mode alone does not combine Corfu history sorting with flex-x sorting. Use the combined sorting configuration from the official Corfu wiki to apply both:

(with-eval-after-load 'corfu
  (corfu-history-mode 1)

  (defun my-corfu-combined-sort (candidates)
    "Sort CANDIDATES using both display and Corfu sort functions."
    (let ((candidates
           (let ((display-sort-function
                  (corfu--metadata-get 'display-sort-function)))
             (if display-sort-function
                 (funcall display-sort-function candidates)
               candidates))))
      (if corfu-sort-function
          (funcall corfu-sort-function candidates)
        candidates)))

  (setopt corfu-sort-override-function #'my-corfu-combined-sort))

This makes Corfu history sorting the final sorting layer. Since corfu-sort-override-function deliberately overrides completion metadata, it also reorders tables whose display-sort-function is identity. Omit this override where preserving the completion table’s exact order is more important than Corfu history sorting.

Regexp Expander

flex-x-extra-pattern-function can be nil, one function, or one function name. The function receives a search term and should return a regexp string or nil.

Examples:

(setq flex-x-extra-pattern-function #'migemo-get-pattern)

Development

FEATURES.md defines the package behavior boundary.

make test
make compile
make check

About

No description, website, or topics provided.

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages