Skip to content

Fuzzy matching prioritizes internal match to prefix match #17531

Description

@lifepillar

Steps to reproduce

Execute:

echo matchfuzzy(['BindTerminal', 'terminal'], 'term')

The output is ['BindTerminal', 'terminal']. Or, in the command line:

  1. vim --clean
  2. set wildoptions=fuzzy
  3. :command BindTerminal :<cr>
  4. :trm<TAB>

The command line is expanded to BindTerminal. This behaviour has started with patch v9.1.1046.

Expected behaviour

In the examples above, I would expect that terminal is the first match, as it matches a prefix of the text (case-sensitively, btw).

Even ignoring the position of the match, term or trm is intuitively “more similar” (e.g., in terms of edit distance) to terminal than to BindTerminal.

Version of Vim

9.1.1455

Environment

macOS
Apple Terminal
xterm-256color
ZSH 5.9

Logs and stack traces

Activity

  1. habamax commented on Jun 12, 2025

    @habamax
    Contributor

    Try to turn off camelcase option, however would only work for a function.

  2. habamax commented on Jun 12, 2025

    @habamax
    Contributor

    see #16797

  3. habamax commented on Jun 12, 2025

    @habamax
    Contributor

    It would be nice to have CamelCase prioritization turned off for command-line complete...

  4. habamax commented on Jun 12, 2025

    @habamax
    Contributor

    Oh, I missed that patch back then 9dfc7e5

    Without camelcase preference enhancement it was more predictable and natural. :(

  5. habamax commented on Jun 12, 2025

    @habamax
    Contributor

    Just a thought... If we are too late to revert CamelCase prioritization, maybe we can have extended fuzzy settings:

    set completeopt+=fuzzy:nocamel
    set wildoptions+=fuzzy:nocamel
    

    ?

  6. girishji commented on Jun 18, 2025

    @girishji
    Contributor

    What’s the correct scoring approach for matching?

    Would the following be a good solution?

    • If the search pattern contains an uppercase letter, then case-sensitive matches should receive a score boost; otherwise, case-sensitive matches could be penalized slightly.
    • If the match occurs at the start of the string, it should also receive a higher score.

    Regarding the "camel case" option — it feels unnecessary or unintuitive. A well-designed scoring algorithm should naturally account for uppercase letters and camelCase structure without requiring a separate option.

  7. habamax commented on Jun 18, 2025

    @habamax
    Contributor

    Regarding the "camel case" option — it feels unnecessary or unintuitive. A well-designed scoring algorithm should naturally account for uppercase letters and camelCase structure without requiring a separate option.

    I agree, however last try to tinker with it wasn't quite successful #16797

  8. girishji commented on Jun 18, 2025

    @girishji
    Contributor

    Looks like it is already supposed to do what I proposed:

    vim/src/search.c

    Line 4294 in 4829511

    * Fuzzy string matching

    Maybe some more tweaking is needed.

    There is also this algorithm: https://github.com/junegunn/fzf/blob/master/src/algo/algo.go

  9. habamax commented on Jun 19, 2025

    @habamax
    Contributor

    maybe the patch that introduced enhanced camelcase could be tweaked?

    9dfc7e5

  10. habamax commented on Jun 20, 2025

    @habamax
    Contributor

    I wonder if reverting is an option, @chrisbra ?

    Hmm, I guess it wouldn't be that simple/easy to do.

  11. girishji commented on Jun 20, 2025

    @girishji
    Contributor

    I wonder if reverting is an option, @chrisbra ?

    Hmm, I guess it wouldn't be that simple/easy to do.

    I'll take a closer look when I get a chance. Based on the algorithm's description, it should have handled all those basic cases—including camelCase—without requiring such significant "tweaks".

  12. habamax commented on Jun 20, 2025

    @habamax
    Contributor

    see also #17581

  13. girishji commented on Jul 24, 2025

    @girishji
    Contributor

    I've looked into this — the current fuzzy matching algorithm isn't very accurate. It struggles with CamelCase and often fails to prioritize matches at the beginning of a string over those in the middle. You can see this in action on the author's own demo app (type into the box): reverse_engineering_sublime_texts_fuzzy_match/

    The original author clearly optimized for performance over accuracy, and I suspect whoever integrated this into Vim was aware of that tradeoff.

    Fuzzy scoring is inherently heuristic-based and imprecise. Accuracy and performance are often at odds, and this algorithm leans heavily toward performance.

    The PRs from the author you mentioned introduced regressions (e.g., this issue and #17576) likely because he/she misunderstood the limitations and tradeoffs of the existing algorithm. Those "tweaks" are a net-negative.

    If the project is interested in improving fuzzy search, there are several better alternatives:

    1. fzy – A relatively simple C implementation with ~3k GitHub stars. MIT license. It can act as a drop-in replacement.

    2. VSCode – A more sophisticated algorithm written in TypeScript, but portable to C. It features richer scoring.

    Both account for non-contiguous matches, case sensitivity, CamelCase, and word boundaries. I have not tested them for performance, but given the reputation I assume they made the right tradeoffs.

    Other options worth noting:

  14. habamax commented on Jul 24, 2025

    @habamax
    Contributor

    I (for myself) would love to see improvements here (specifically see how fzy algorithm would fit vim).

  15. 1 remaining item

  16. habamax commented on Jul 26, 2025

    @habamax
    Contributor

    Sounds good!

  17. lifepillar commented on Jul 26, 2025

    @lifepillar
    ContributorAuthor

    How does this relate to #17581? AFAICT, @glepnir has implemented essentially the same algorithm (modulo details). Can the efforts be aggregated into a single PR?

  18. habamax commented on Jul 27, 2025

    @habamax
    Contributor

    I like the idea of "drop-in replacement" taking an advantage of using existing established project's code. But ultimately it will depend on @chrisbra and the team to choose "better fit" implementation.

  19. glepnir commented on Jul 27, 2025

    @glepnir
    Member

    implemented essentially the same algorithm (modulo details)

    17581 implementation of the full three-matrix gaps simthwaterman fzf uses a single matrix. I have used fzy in telescope but I have not read the details of its algorithm. helix uses 2 matrices. fuzzy completion in helix works well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions