Skip to content

Commit e0e1bd8

Browse files
committed
(mini.completion) FEATURE: Prefer completion start from LSP.
Details: - Resolves #679. - Resolves #306.
1 parent 7c2339f commit e0e1bd8

File tree

3 files changed

+49
-6
lines changed

3 files changed

+49
-6
lines changed

lua/mini/completion.lua

+22-5
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ MiniCompletion.completefunc_lsp = function(findstart, base)
368368
if findstart == 1 then return -3 end
369369
return {}
370370
else
371-
if findstart == 1 then return H.get_completion_start() end
371+
if findstart == 1 then return H.get_completion_start(H.completion.lsp.result) end
372372

373373
local process_items = H.get_config().lsp_completion.process_items
374374
local words = H.process_lsp_response(H.completion.lsp.result, function(response, client_id)
@@ -1285,12 +1285,29 @@ end
12851285

12861286
H.pumvisible = function() return vim.fn.pumvisible() > 0 end
12871287

1288-
H.get_completion_start = function()
1289-
-- Compute start position of latest keyword (as in `vim.lsp.omnifunc`)
1288+
H.get_completion_start = function(lsp_result)
12901289
local pos = vim.api.nvim_win_get_cursor(0)
1290+
1291+
-- Prefer completion start from LSP response(s)
1292+
for _, response_data in pairs(lsp_result or {}) do
1293+
local server_start = H.get_completion_start_server(response_data, pos[1] - 1)
1294+
if server_start ~= nil then return server_start end
1295+
end
1296+
1297+
-- Fall back to start position of latest keyword
12911298
local line = vim.api.nvim_get_current_line()
1292-
local line_to_cursor = line:sub(1, pos[2])
1293-
return vim.fn.match(line_to_cursor, '\\k*$')
1299+
return vim.fn.match(line:sub(1, pos[2]), '\\k*$')
1300+
end
1301+
1302+
H.get_completion_start_server = function(response_data, line_num)
1303+
if response_data.err or type(response_data.result) ~= 'table' then return end
1304+
local items = response_data.result.items or response_data.result
1305+
for _, item in pairs(items) do
1306+
if type(item.textEdit) == 'table' and item.textEdit.range.start.line == line_num then
1307+
-- NOTE: Ignore case when items contain several conflicting starts
1308+
return item.textEdit.range.start.character
1309+
end
1310+
end
12941311
end
12951312

12961313
H.is_whitespace = function(s)

tests/dir-completion/mock-months-lsp.lua

+15-1
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,29 @@ local construct_additionTextEdits = function(id, name)
4444
}
4545
end
4646

47+
local construct_textEdit = function(name)
48+
local pos = _G.mock_textEdit_pos
49+
if pos == nil then return end
50+
return {
51+
newText = '.' .. name,
52+
range = {
53+
start = { line = pos[1] - 1, character = pos[2] - 1 },
54+
['end'] = { line = pos[1] - 1, character = pos[2] },
55+
},
56+
}
57+
end
58+
4759
Months.requests = {
4860
['textDocument/completion'] = function(params)
4961
local items = {}
5062
for i, item in ipairs(Months.items) do
5163
local res = { label = item.name, kind = item.kind, sortText = ('%03d'):format(i) }
52-
-- Mock additionalTextEdits as in `pyright`
64+
-- Mock `additionalTextEdits` as in `pyright`
5365
if vim.tbl_contains({ 'September', 'November' }, item.name) then
5466
res.additionalTextEdits = construct_additionTextEdits('completion', item.name)
5567
end
68+
-- Mock `textEdit` as in `tsserver` when called after `.`
69+
if vim.tbl_contains({ 'April', 'August' }, item.name) then res.textEdit = construct_textEdit(item.name) end
5670
table.insert(items, res)
5771
end
5872

tests/test_completion.lua

+12
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,18 @@ T['Manual completion']['applies `additionalTextEdits` from "completionItem/resol
468468
eq(get_lines(), { 'January' })
469469
end
470470

471+
T['Manual completion']['prefers completion range from LSP response'] = function()
472+
set_lines({})
473+
type_keys('i', 'months.')
474+
child.lua('_G.mock_textEdit_pos = vim.api.nvim_win_get_cursor(0)')
475+
type_keys('<C-space>')
476+
477+
eq(get_completion(), { '.April', '.August' })
478+
type_keys('<C-n>', '<C-y>')
479+
eq(get_lines(), { 'months.April' })
480+
eq(get_cursor(), { 1, 12 })
481+
end
482+
471483
T['Manual completion']['respects `vim.{g,b}.minicompletion_disable`'] = new_set({
472484
parametrize = { { 'g' }, { 'b' } },
473485
}, {

0 commit comments

Comments
 (0)