Skip to content

Commit 101e3c9

Browse files
committed
feat(fuzzy)!: treat empty word as matching any candidate
Details: - This behavior is usually more useful in practice.
1 parent 53f27fe commit 101e3c9

File tree

4 files changed

+17
-9
lines changed

4 files changed

+17
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
## mini.fuzzy
5353

5454
- BREAKING: update `process_lsp_items()` to only use `filterText` and `label` item fields during fuzzy matching (instead of `textEdit.newText`, `insertText`, and `label` as before). This is more aligned with LSP specification.
55+
- BREAKING: treat empty `word` as matching any candidate (matched positions is empty array and score is -1). This behavior is usually more useful in practice.
5556

5657
## mini.hues
5758

doc/mini-fuzzy.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ See |mini.nvim-buffer-local-config| for more details.
4343
General design uses only width of found match and index of first letter
4444
match. No special characters or positions (like in fzy and fzf) are used.
4545

46-
Given input `word` and target `candidate`:
46+
Given non-empty input `word` and target `candidate`:
4747
- The goal is to find matching between `word`'s letters and letters in
4848
`candidate` which minimizes certain score. It is assumed that order of
4949
letters in `word` and those matched in `candidate` should be the same.
@@ -108,9 +108,10 @@ Parameters ~
108108
Return ~
109109
`(table)` Matching information:
110110
- <positions> `(table|nil)` - array with letter indexes inside `candidate`
111-
which matched to corresponding letters in `word`. It is `nil` if no match.
111+
which matched to corresponding letters in `word`. It is empty array if
112+
`word` is empty string and `nil` if no match.
112113
- <score> `number` - positive number representing how good the match is
113-
(lower is better). It is `-1` if no match.
114+
(lower is better). It is `-1` if no match or word is empty string.
114115

115116
------------------------------------------------------------------------------
116117
*MiniFuzzy.filtersort()*

lua/mini/fuzzy.lua

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
--- General design uses only width of found match and index of first letter
4242
--- match. No special characters or positions (like in fzy and fzf) are used.
4343
---
44-
--- Given input `word` and target `candidate`:
44+
--- Given non-empty input `word` and target `candidate`:
4545
--- - The goal is to find matching between `word`'s letters and letters in
4646
--- `candidate` which minimizes certain score. It is assumed that order of
4747
--- letters in `word` and those matched in `candidate` should be the same.
@@ -111,9 +111,10 @@ MiniFuzzy.config = {
111111
---
112112
---@return table Matching information:
113113
--- - <positions> `(table|nil)` - array with letter indexes inside `candidate`
114-
--- which matched to corresponding letters in `word`. It is `nil` if no match.
114+
--- which matched to corresponding letters in `word`. It is empty array if
115+
--- `word` is empty string and `nil` if no match.
115116
--- - <score> `number` - positive number representing how good the match is
116-
--- (lower is better). It is `-1` if no match.
117+
--- (lower is better). It is `-1` if no match or word is empty string.
117118
MiniFuzzy.match = function(word, candidate)
118119
-- Use 'smart case'
119120
candidate = word == word:lower() and candidate:lower() or candidate
@@ -236,7 +237,8 @@ end
236237
---@private
237238
H.find_best_positions = function(letters, candidate)
238239
local n_candidate, n_letters = #candidate, #letters
239-
if n_letters == 0 or n_candidate < n_letters then return nil end
240+
if n_letters == 0 then return {} end
241+
if n_candidate < n_letters then return nil end
240242

241243
-- Search forward to find matching positions with left-most last letter match
242244
local pos_last = 0

tests/test_fuzzy.lua

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ T['match()']['handles cases when match is impossible'] = function()
7272
eq(child.lua_get([[MiniFuzzy.match('ab', 'a')]]), { score = -1 })
7373

7474
-- Empty word
75-
eq(child.lua_get([[MiniFuzzy.match('', 'abc')]]), { score = -1 })
75+
eq(child.lua_get([[MiniFuzzy.match('', 'abc')]]), { positions = {}, score = -1 })
7676
end
7777

7878
local validate_match = function(word, candidate, positions)
@@ -189,7 +189,7 @@ T['filtersort()']['preserves original order with equal matching score'] = functi
189189
end
190190

191191
T['filtersort()']['works with empty arguments'] = function()
192-
validate_filtersort('', { 'a', 'b', '_a' }, {})
192+
validate_filtersort('', { 'a', 'b', '_a' }, { 'a', 'b', '_a' })
193193
validate_filtersort('a', {}, {})
194194
end
195195

@@ -205,6 +205,10 @@ T['process_lsp_items()']['works'] = function()
205205
local validate = function(items) eq(process_lsp_items(items, 'a'), { items[3], items[2], items[1] }) end
206206
validate({ new_item('___a'), new_item('__a'), new_item('_a') })
207207
validate({ new_item(nil, '___a'), new_item(nil, '__a'), new_item(nil, '_a') })
208+
209+
-- Should match all as is for empty string `base`
210+
local items = { new_item(nil, '___a'), new_item(nil, '__a'), new_item(nil, '_a') }
211+
eq(process_lsp_items(items, ''), items)
208212
end
209213

210214
T['process_lsp_items()']['correctly extracts candidate from fields'] = function()

0 commit comments

Comments
 (0)