From 7d963b7321e277b87a09fc2cc38d6d1bc82206ff Mon Sep 17 00:00:00 2001 From: neo451 <412444506@qq.com> Date: Wed, 15 Apr 2026 17:14:30 +0100 Subject: [PATCH] feat(completion): support lsp completion item.command --- lua/mini/completion.lua | 15 +++++++++++++-- tests/test_completion.lua | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/lua/mini/completion.lua b/lua/mini/completion.lua index 3b6034ab..c8aa91a4 100644 --- a/lua/mini/completion.lua +++ b/lua/mini/completion.lua @@ -1342,7 +1342,7 @@ H.make_lsp_extra_actions = function(lsp_data) -- Prefer resolved item over the one from 'textDocument/completion' local item = H.completion.lsp.resolved[lsp_data.item_id] or lsp_data.item - if item.additionalTextEdits == nil and not lsp_data.needs_snippet_insert then return end + if item.additionalTextEdits == nil and not lsp_data.needs_snippet_insert and item.command == nil then return end local snippet = lsp_data.needs_snippet_insert and H.get_completion_word(item) or nil -- Make extra actions not only after an explicit `` (accept completed @@ -1370,7 +1370,11 @@ H.make_lsp_extra_actions = function(lsp_data) end -- Try to only apply additional text edits for non-snippet items - if snippet == nil then return H.apply_text_edits(item.client_id, item.additionalTextEdits) end + if snippet == nil then + H.apply_text_edits(item.client_id, item.additionalTextEdits) + H.exec_command(item.client_id, item.command) + return + end -- Revert to initial completion state to respect text edit coordinates local init_base = H.completion.init_base @@ -1416,6 +1420,13 @@ H.apply_text_edits = function(client_id, text_edits) vim.lsp.util.apply_text_edits(text_edits, vim.api.nvim_get_current_buf(), offset_encoding) end +H.exec_command = function(client_id, command) + if command == nil then return end + local client = client_id ~= nil and vim.lsp.get_client_by_id(client_id) + if client == nil then return end + client:exec_cmd(command) +end + H.apply_tracked_text_edits = function(client_id, text_edits, from, to) if text_edits == nil then return from, to end diff --git a/tests/test_completion.lua b/tests/test_completion.lua index 6c2c75b0..23a22746 100644 --- a/tests/test_completion.lua +++ b/tests/test_completion.lua @@ -1078,6 +1078,28 @@ T['Manual completion']['applies `additionalTextEdits` from "completionItem/resol eq(get_lines(), { 'January' }) end +T['Manual completion']['executes `command` from completion item'] = function() + local command = { title = 'Add import', command = 'add_import', arguments = { 'months' } } + + mock_lsp_items({ { label = 'Hello', command = command } }) + + child.lua([[ + _G.exec_cmd_log = {} + local client = vim.lsp.get_client_by_id(_G.months_lsp_client_id) + local orig = client.exec_cmd + client.exec_cmd = function(self, cmd, ...) + table.insert(_G.exec_cmd_log, vim.deepcopy(cmd)) + return orig(self, cmd, ...) + end + ]]) + + set_lines({}) + type_keys('i', '', '', '') + eq(get_lines(), { 'Hello' }) + eq(child.lua_get('#_G.exec_cmd_log'), 1) + eq(child.lua_get('_G.exec_cmd_log[1].command'), 'add_import') +end + T['Manual completion']['prefers completion range from LSP response'] = function() set_lines({}) type_keys('i', 'months.')