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: ~ | ||||
|       • {autotrigger}?  (`boolean`) Whether to trigger completion | ||||
|                         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()* | ||||
|   | ||||
| @@ -65,7 +65,9 @@ EVENTS | ||||
|  | ||||
| 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 | ||||
|  | ||||
|   | ||||
| @@ -23,6 +23,7 @@ local ns_to_ms = 0.000001 | ||||
| --- @class vim.lsp.completion.BufHandle | ||||
| --- @field clients table<integer, vim.lsp.Client> | ||||
| --- @field triggers table<string, vim.lsp.Client[]> | ||||
| --- @field convert? fun(item: lsp.CompletionItem): table | ||||
|  | ||||
| --- @type table<integer, vim.lsp.completion.BufHandle> | ||||
| local buf_handles = {} | ||||
| @@ -250,6 +251,8 @@ function M._lsp_to_complete_items(result, prefix, client_id) | ||||
|   end | ||||
|  | ||||
|   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 | ||||
|     if matches(item) then | ||||
|       local word = get_completion_word(item) | ||||
| @@ -260,7 +263,7 @@ function M._lsp_to_complete_items(result, prefix, client_id) | ||||
|       then | ||||
|         hl_group = 'DiagnosticDeprecated' | ||||
|       end | ||||
|       table.insert(candidates, { | ||||
|       local completion_item = { | ||||
|         word = word, | ||||
|         abbr = item.label, | ||||
|         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 | ||||
|   ---@diagnostic disable-next-line: no-unknown | ||||
| @@ -590,6 +597,7 @@ end | ||||
|  | ||||
| --- @class vim.lsp.completion.BufferOpts | ||||
| --- @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 bufnr integer | ||||
| @@ -597,7 +605,7 @@ end | ||||
| local function enable_completions(client_id, bufnr, opts) | ||||
|   local buf_handle = buf_handles[bufnr] | ||||
|   if not buf_handle then | ||||
|     buf_handle = { clients = {}, triggers = {} } | ||||
|     buf_handle = { clients = {}, triggers = {}, convert = opts.convert } | ||||
|     buf_handles[bufnr] = buf_handle | ||||
|  | ||||
|     -- Attach to buffer events. | ||||
|   | ||||
| @@ -495,7 +495,9 @@ describe('vim.lsp.completion: protocol', function() | ||||
|       bufnr = vim.api.nvim_get_current_buf() | ||||
|       vim.api.nvim_win_set_buf(0, 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}) | ||||
|     ]], | ||||
|       completion_result | ||||
| @@ -700,4 +702,21 @@ describe('vim.lsp.completion: protocol', function() | ||||
|       eq(true, exec_lua('return _G.called')) | ||||
|     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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 glepnir
					glepnir