diff options
author | glepnir <glephunter@gmail.com> | 2024-12-27 14:23:06 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-27 14:23:06 +0800 |
commit | 46c7faa00b165a1ad1b7cef8245df30d3dc3ef56 (patch) | |
tree | 39de7d7bf73bc67684769a8ec4d385bc81abedd0 | |
parent | 557f2d970044b04a364134ec45060b21b0f0b108 (diff) | |
download | rneovim-46c7faa00b165a1ad1b7cef8245df30d3dc3ef56.tar.gz rneovim-46c7faa00b165a1ad1b7cef8245df30d3dc3ef56.tar.bz2 rneovim-46c7faa00b165a1ad1b7cef8245df30d3dc3ef56.zip |
vim-patch:9.1.0963: fuzzy-matching does not prefer full match (#31741)
Problem: fuzzy-matching does not prefer full match
(Maxim Kim)
Solution: add additional score for a full match
(glepnir)
fixes: vim/vim#15654
closes: vim/vim#16300
https://github.com/vim/vim/commit/5a04999a7402201cf1b47ff10bc474dd1cdc24f4
-rw-r--r-- | runtime/doc/pattern.txt | 1 | ||||
-rw-r--r-- | src/nvim/search.c | 9 | ||||
-rw-r--r-- | test/old/testdir/test_matchfuzzy.vim | 6 |
3 files changed, 14 insertions, 2 deletions
diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt index 7f0938be05..be913e941e 100644 --- a/runtime/doc/pattern.txt +++ b/runtime/doc/pattern.txt @@ -1485,6 +1485,7 @@ criteria: - Matches at a camel case character (e.g. Case in CamelCase) - Matches after a path separator or a hyphen. - The number of unmatched characters in a string. + - A full/exact match is preferred. The matching string with the highest score is returned first. For example, when you search for the "get pat" string using fuzzy matching, it diff --git a/src/nvim/search.c b/src/nvim/search.c index faa14dfaf4..5a53122739 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -2995,6 +2995,7 @@ static int fuzzy_match_compute_score(const char *const str, const int strSz, assert(numMatches > 0); // suppress clang "result of operation is garbage" // Initialize score int score = 100; + bool is_exact_match = true; // Apply leading letter penalty int penalty = LEADING_LETTER_PENALTY * (int)matches[0]; @@ -3048,6 +3049,14 @@ static int fuzzy_match_compute_score(const char *const str, const int strSz, // First letter score += FIRST_LETTER_BONUS; } + // Check exact match condition + if (currIdx != (uint32_t)i) { + is_exact_match = false; + } + } + // Boost score for exact matches + if (is_exact_match && numMatches == strSz) { + score += 100; } return score; } diff --git a/test/old/testdir/test_matchfuzzy.vim b/test/old/testdir/test_matchfuzzy.vim index 90f3366b23..c2dc07ed10 100644 --- a/test/old/testdir/test_matchfuzzy.vim +++ b/test/old/testdir/test_matchfuzzy.vim @@ -23,6 +23,8 @@ func Test_matchfuzzy() call assert_equal(['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'], matchfuzzy(['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'], 'aa')) call assert_equal(256, matchfuzzy([repeat('a', 256)], repeat('a', 256))[0]->len()) call assert_equal([], matchfuzzy([repeat('a', 300)], repeat('a', 257))) + " full match has highest score + call assert_equal(['Cursor', 'lCursor'], matchfuzzy(["hello", "lCursor", "Cursor"], "Cursor")) " matches with same score should not be reordered let l = ['abc1', 'abc2', 'abc3'] call assert_equal(l, l->matchfuzzy('abc')) @@ -101,7 +103,7 @@ func Test_matchfuzzypos() call assert_equal([['curl', 'world'], [[2,3], [2,3]], [128, 127]], matchfuzzypos(['world', 'curl'], 'rl')) call assert_equal([['curl', 'world'], [[2,3], [2,3]], [128, 127]], matchfuzzypos(['world', 'one', 'curl'], 'rl')) call assert_equal([['hello', 'hello world hello world'], - \ [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]], [275, 257]], + \ [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]], [375, 257]], \ matchfuzzypos(['hello world hello world', 'hello', 'world'], 'hello')) call assert_equal([['aaaaaaa'], [[0, 1, 2]], [191]], matchfuzzypos(['aaaaaaa'], 'aaa')) call assert_equal([['a b'], [[0, 3]], [219]], matchfuzzypos(['a b'], 'a b')) @@ -136,7 +138,7 @@ func Test_matchfuzzypos() call assert_equal([['foo bar baz'], [[0, 1, 2, 3, 4, 5, 10]], [326]], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('foo baz', {'matchseq': 1})) call assert_equal([[], [], []], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('one two')) call assert_equal([[], [], []], ['foo bar']->matchfuzzypos(" \t ")) - call assert_equal([['grace'], [[1, 2, 3, 4, 2, 3, 4, 0, 1, 2, 3, 4]], [657]], ['grace']->matchfuzzypos('race ace grace')) + call assert_equal([['grace'], [[1, 2, 3, 4, 2, 3, 4, 0, 1, 2, 3, 4]], [757]], ['grace']->matchfuzzypos('race ace grace')) let l = [{'id' : 5, 'val' : 'crayon'}, {'id' : 6, 'val' : 'camera'}] call assert_equal([[{'id' : 6, 'val' : 'camera'}], [[0, 1, 2]], [192]], |