Skip to content

Commit cbc9891

Browse files
committed
feat(completion)!: make default LSP item processing to maybe fuzzy match
Details: - Do fuzzy matching (both filter and sort) of LSP completion items (i.e. of 'textDocument/completion' response) if 'completeopt' option contains "fuzzy" flag (requires Neovim>=0.11); use previous `'prefix'` method otherwise. This makes experience more seamless with `completeopt+=fuzzy` and servers which might return `isIncomplete=true`. Using same fuzzy matching algorithm (`:h matchfuzzy()` and `:h fuzzy-matching`) allows typing in common case of "first several `isIncomplete=true` responses followed by built-in candidates matching after a `isIncomplete=false` response" feel the same. One difference is that initial LSP item processing respects both `filterText` and `label` fields while built-in completion menu filtering will respect only `label` (as there is no concept of `filterText` in built-in completion items).
1 parent 644ca2c commit cbc9891

File tree

4 files changed

+9
-4
lines changed

4 files changed

+9
-4
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
- Show `labelDetails` as a part of the popup menu via `menu` completion item field.
4545
- BREAKING: prefer to not use functions as default config values. In particular, for `lsp_completion.process_items` (use `nil` with explicit fallback) and `fallback_action` (use `'<C-n>'`). This should not have any user facing effects and marked as breaking only because a structure of a default config has changed to be more aligned with other modules.
4646
- BREAKING FEATURE: update behavior and capabilities of `default_process_items()`:
47-
- Add `filtersort` option to control how items are filtered and/or sorted.
47+
- Add `filtersort` option to control how items are filtered and/or sorted. Its default value has new (breaking) value: do fuzzy matching if 'completeopt' option contains "fuzzy" entry; same as before otherwise.
4848
- Use `filterText` and `label` item fields during matching (instead of `textEdit.newText`, `insertText`, and `label` as before). This is more aligned with LSP specification.
4949

5050
## mini.doc

doc/mini-completion.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ Parameters ~
361361
- `'fuzzy'` - filter and sort with |matchfuzzy| using `filterText`.
362362
- `'none'` - no filter and no sort.
363363
If callable, should take `items` and `base` arguments and return items array.
364-
Default: `'prefix'`.
364+
Default: `'fuzzy'` if 'completeopt' contains "fuzzy", `'prefix'` otherwise.
365365

366366
Return ~
367367
`(table)` Array of processed items from LSP response.

lua/mini/completion.lua

+2-2
Original file line numberDiff line numberDiff line change
@@ -482,14 +482,14 @@ end
482482
--- - `'fuzzy'` - filter and sort with |matchfuzzy| using `filterText`.
483483
--- - `'none'` - no filter and no sort.
484484
--- If callable, should take `items` and `base` arguments and return items array.
485-
--- Default: `'prefix'`.
485+
--- Default: `'fuzzy'` if 'completeopt' contains "fuzzy", `'prefix'` otherwise.
486486
---
487487
---@return table Array of processed items from LSP response.
488488
MiniCompletion.default_process_items = function(items, base, opts)
489489
opts = opts or {}
490490

491491
-- NOTE: custom filter+sort is important with frequent `isIncomplete`
492-
local fs = opts.filtersort or 'prefix'
492+
local fs = opts.filtersort or (vim.o.completeopt:find('fuzzy') and 'fuzzy' or 'prefix')
493493
if type(fs) == 'string' then fs = H.filtersort_methods[fs] end
494494
if not vim.is_callable(fs) then H.error('`filtersort` should be callable or one of "prefix", "fuzzy", "none"') end
495495
local res = fs(items, base)

tests/test_completion.lua

+5
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,11 @@ local ref_fuzzy_items = {
291291
T['default_process_items()']['works'] = function()
292292
-- Should use 'prefix' filtersort if no 'fuzzy' in 'completeopt'
293293
eq(child.lua_get('MiniCompletion.default_process_items(_G.items, "M")'), ref_prefix_items)
294+
295+
-- Should use 'fuzzy' filtersort if there is 'fuzzy' in 'completeopt'
296+
if child.fn.has('nvim-0.11') == 0 then MiniTest.skip("Only Neovim>=0.11 has 'fuzzy' flag in 'completeopt'") end
297+
child.o.completeopt = 'menuone,noselect,fuzzy'
298+
eq(child.lua_get('MiniCompletion.default_process_items(_G.items, "l")'), ref_fuzzy_items)
294299
end
295300

296301
T['default_process_items()']["highlights LSP kind if 'mini.icons' is enabled"] = function()

0 commit comments

Comments
 (0)