mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	feat(lsp): completion opts support custom item conversion (#30060)
Problem: Some items of completion results include function signatures that can cause the pum to be very long when a function has many params, because pum scales with the longest word/abbr. Solution: add custom covert function that can customise abbr to remove params.
This commit is contained in:
		| @@ -1630,6 +1630,9 @@ Lua module: vim.lsp.completion                                *lsp-completion* | |||||||
|     Fields: ~ |     Fields: ~ | ||||||
|       • {autotrigger}?  (`boolean`) Whether to trigger completion |       • {autotrigger}?  (`boolean`) Whether to trigger completion | ||||||
|                         automatically. Default: false |                         automatically. Default: false | ||||||
|  |       • {convert}?      (`fun(item: lsp.CompletionItem): table`) An optional | ||||||
|  |                         function used to customize the transformation of an | ||||||
|  |                         LSP CompletionItem to |complete-items|. | ||||||
|  |  | ||||||
|  |  | ||||||
|                                                  *vim.lsp.completion.enable()* |                                                  *vim.lsp.completion.enable()* | ||||||
|   | |||||||
| @@ -65,7 +65,9 @@ EVENTS | |||||||
|  |  | ||||||
| LSP | LSP | ||||||
|  |  | ||||||
| • TODO | • Add convert field in |vim.lsp.completion.BufferOpts| of | ||||||
|  |   |vim.lsp.completion.enable()| an optional function used to customize the | ||||||
|  |   transformation of an Lsp CompletionItem to |complete-items|. | ||||||
|  |  | ||||||
| LUA | LUA | ||||||
|  |  | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ local ns_to_ms = 0.000001 | |||||||
| --- @class vim.lsp.completion.BufHandle | --- @class vim.lsp.completion.BufHandle | ||||||
| --- @field clients table<integer, vim.lsp.Client> | --- @field clients table<integer, vim.lsp.Client> | ||||||
| --- @field triggers table<string, vim.lsp.Client[]> | --- @field triggers table<string, vim.lsp.Client[]> | ||||||
|  | --- @field convert? fun(item: lsp.CompletionItem): table | ||||||
|  |  | ||||||
| --- @type table<integer, vim.lsp.completion.BufHandle> | --- @type table<integer, vim.lsp.completion.BufHandle> | ||||||
| local buf_handles = {} | local buf_handles = {} | ||||||
| @@ -250,6 +251,8 @@ function M._lsp_to_complete_items(result, prefix, client_id) | |||||||
|   end |   end | ||||||
|  |  | ||||||
|   local candidates = {} |   local candidates = {} | ||||||
|  |   local bufnr = api.nvim_get_current_buf() | ||||||
|  |   local user_convert = vim.tbl_get(buf_handles, bufnr, 'convert') | ||||||
|   for _, item in ipairs(items) do |   for _, item in ipairs(items) do | ||||||
|     if matches(item) then |     if matches(item) then | ||||||
|       local word = get_completion_word(item) |       local word = get_completion_word(item) | ||||||
| @@ -260,7 +263,7 @@ function M._lsp_to_complete_items(result, prefix, client_id) | |||||||
|       then |       then | ||||||
|         hl_group = 'DiagnosticDeprecated' |         hl_group = 'DiagnosticDeprecated' | ||||||
|       end |       end | ||||||
|       table.insert(candidates, { |       local completion_item = { | ||||||
|         word = word, |         word = word, | ||||||
|         abbr = item.label, |         abbr = item.label, | ||||||
|         kind = protocol.CompletionItemKind[item.kind] or 'Unknown', |         kind = protocol.CompletionItemKind[item.kind] or 'Unknown', | ||||||
| @@ -278,7 +281,11 @@ function M._lsp_to_complete_items(result, prefix, client_id) | |||||||
|             }, |             }, | ||||||
|           }, |           }, | ||||||
|         }, |         }, | ||||||
|       }) |       } | ||||||
|  |       if user_convert then | ||||||
|  |         completion_item = vim.tbl_extend('keep', user_convert(item), completion_item) | ||||||
|  |       end | ||||||
|  |       table.insert(candidates, completion_item) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|   ---@diagnostic disable-next-line: no-unknown |   ---@diagnostic disable-next-line: no-unknown | ||||||
| @@ -590,14 +597,15 @@ end | |||||||
|  |  | ||||||
| --- @class vim.lsp.completion.BufferOpts | --- @class vim.lsp.completion.BufferOpts | ||||||
| --- @field autotrigger? boolean Whether to trigger completion automatically. Default: false | --- @field autotrigger? boolean Whether to trigger completion automatically. Default: false | ||||||
|  | --- @field convert? fun(item: lsp.CompletionItem): table An optional function used to customize the transformation of an LSP CompletionItem to |complete-items|. | ||||||
|  |  | ||||||
| --- @param client_id integer | ---@param client_id integer | ||||||
| ---@param bufnr integer | ---@param bufnr integer | ||||||
| ---@param opts vim.lsp.completion.BufferOpts | ---@param opts vim.lsp.completion.BufferOpts | ||||||
| local function enable_completions(client_id, bufnr, opts) | local function enable_completions(client_id, bufnr, opts) | ||||||
|   local buf_handle = buf_handles[bufnr] |   local buf_handle = buf_handles[bufnr] | ||||||
|   if not buf_handle then |   if not buf_handle then | ||||||
|     buf_handle = { clients = {}, triggers = {} } |     buf_handle = { clients = {}, triggers = {}, convert = opts.convert } | ||||||
|     buf_handles[bufnr] = buf_handle |     buf_handles[bufnr] = buf_handle | ||||||
|  |  | ||||||
|     -- Attach to buffer events. |     -- Attach to buffer events. | ||||||
|   | |||||||
| @@ -495,7 +495,9 @@ describe('vim.lsp.completion: protocol', function() | |||||||
|       bufnr = vim.api.nvim_get_current_buf() |       bufnr = vim.api.nvim_get_current_buf() | ||||||
|       vim.api.nvim_win_set_buf(0, bufnr) |       vim.api.nvim_win_set_buf(0, bufnr) | ||||||
|       return vim.lsp.start({ name = 'dummy', cmd = server.cmd, on_attach = function(client, bufnr) |       return vim.lsp.start({ name = 'dummy', cmd = server.cmd, on_attach = function(client, bufnr) | ||||||
|         vim.lsp.completion.enable(true, client.id, bufnr) |         vim.lsp.completion.enable(true, client.id, bufnr, { convert = function(item) | ||||||
|  |           return { abbr = item.label:gsub('%b()', '')} | ||||||
|  |         end}) | ||||||
|       end}) |       end}) | ||||||
|     ]], |     ]], | ||||||
|       completion_result |       completion_result | ||||||
| @@ -700,4 +702,21 @@ describe('vim.lsp.completion: protocol', function() | |||||||
|       eq(true, exec_lua('return _G.called')) |       eq(true, exec_lua('return _G.called')) | ||||||
|     end) |     end) | ||||||
|   end) |   end) | ||||||
|  |  | ||||||
|  |   it('custom word/abbar format', function() | ||||||
|  |     create_server({ | ||||||
|  |       isIncomplete = false, | ||||||
|  |       items = { | ||||||
|  |         { | ||||||
|  |           label = 'foo(bar)', | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     }) | ||||||
|  |  | ||||||
|  |     feed('ifo') | ||||||
|  |     trigger_at_pos({ 1, 1 }) | ||||||
|  |     assert_matches(function(matches) | ||||||
|  |       eq('foo', matches[1].abbr) | ||||||
|  |     end) | ||||||
|  |   end) | ||||||
| end) | end) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 glepnir
					glepnir