aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/completion.lua
Commit message (Collapse)AuthorAge
...
* docs: use "ev" convention in event-handlersJustin M. Keyes2026-03-12
| | | | | | | | | Problem: In autocmd examples, using "args" as the event-object name is vague and may be confused with a user-command. Solution: Use "ev" as the conventional event-object name.
* fix(lsp): ensure augroup before querying autocmds #38254glepnir2026-03-11
|
* docs: api, messages, lsp, trustJustin M. Keyes2026-03-11
| | | | | gen_vimdoc.lua: In prepare for the upcoming release, comment-out the "Experimental" warning for prerelease features.
* feat(lsp): do completionItem/resolve if completeopt=popup #32820glepnir2026-03-11
| | | | | | | | | Problem: No completionItem/resolve handler. Solution: If completeopt=popup is set, invoke completionItem/resolve when a completion item is selected. Show resolved documentation in popup next to the completion menu.
* feat(lsp): show snippet preview if completeopt=popup #32553glepnir2026-03-10
| | | | | | | Problem: LSP completion does not show snippet preview. Solution: Show snippet preview if 'completeopt' includes popup.
* feat(lsp): show color preview in completion items #32138glepnir2026-02-28
| | | | | Problem: Color completion items display as plain text without visual preview Solution: Parse RGB/hex colors from documentation and render with colored symbol ■
* fix(lsp): vim.lsp.completion clean up triggers on client detach (#38009)glepnir2026-02-22
| | | | | Problem: LspDetach didn't clean up stale client refs in triggers table. Solution: create LspDetach autocmd and call disable_completion.
* fix(lsp): use entire line as completion word (#37949)Maria Solano2026-02-18
|
* fix(lsp): error on omnifunc completion (#37790)phanium2026-02-09
| | | | | | | | | | | Problem: After eaacdc9, complete with emmylua_ls error with: runtime/lua/vim/lsp/completion.lua:586: attempt to get length of field 'items' (a nil value) Solution: Result can be CompletionItem[] according the spec: > If a `CompletionItem[]` is provided, it is interpreted to be complete, > so it is the same as `{ isIncomplete: false, items }`
* fix(lsp): ignore empty response on trigger completion #37663Tomasz N2026-02-08
| | | | | | | | Problem: Empty response affects server start boundary computed before. Solution: Ignore empty responses. This is mostly micro-optimization that avoids extending existing results with empty responses.
* fix(lsp): don't empty server start-boundary by next client response #37665Tomasz N2026-02-03
| | | | | | | Problem: Server start boundary can be emptied by response provided by next client. Solution: Don't empty it when extending the result list.
* fix(lsp): use LSP textEdit range for completion start boundary (#37491)Harsh Kapse2026-01-30
| | | | | | | | | | | | | | | Previously, adjust_start_col returned nil when completion items had different start position from lsp textEdit range This caused the completion to fall back to \k*$ which ignores the non-keyword characters Changes: - adjust_start_col: now returns the minimum start postion among all items instead of nil - _lsp_to_complete_items - normalizes the items by adding the gap between current and minimum start Fixes: https://github.com/neovim/neovim/issues/37441
* fix(lsp): sort items when completeopt include fuzzy #36974glepnir2025-12-16
| | | | | | | Problem: When fuzzy is enabled and the prefix is not empty, items are not sorted by fuzzy score before calling fn.complete. Solution: Use matchfuzzypos to get the scores and sort the items by fuzzy score before calling fn.complete.
* fix(lsp): enable insertReplaceSupport for use in adjust_start_col #36569Jeff Martin2025-11-18
| | | | | | | | | | | | | | | | | Problem: With the typescript LSes typescript-language-server and vtsls, omnicompletion on partial tokens for certain types, such as array methods, and functions that are attached as attributes to other functions, either results in no entries populated in the completion menu (typescript-language-server), or an unfiltered completion menu with all array methods included, even if they don't share the same prefix as the partial token being completed (vtsls). Solution: Enable insertReplaceSupport and uses the insert portion of the lsp completion response in adjust_start_col if it's included in the response. Completion results are still filtered client side.
* feat(lsp): user-specified sorting of lsp.completion multi-server results #36401glepnir2025-11-18
| | | | | | Problem: No way to customize completion order across multiple servers. Solution: Add `cmp` function to `vim.lsp.completion.enable()` options for custom sorting logic.
* fix(lsp): deduplicate completion items #36166Till Bungert2025-10-20
| | | | | | | The current implementation has a race condition where items are appended to the completion list twice when a second completion runs while the first is still going. This hotfix just deduplicates the entire list. Co-authored-by: Tomasz N <przepompownia@users.noreply.github.com>
* fix: vim.lsp.omnifunc should not throw away other items #35346Till Bungert2025-10-11
|
* fix(lsp): deprecate `vim.lsp.protocol.Methods` (#35998)Maria Solano2025-10-04
|
* fix(lsp): treat 2-triggers-at-once as "last char wins" #35435Tomasz N2025-09-17
| | | | | | | | | | | | | | Problem: If there are 2 language servers with different trigger chars (`-` and `>`), and a keymap inputs both simultaneously (`->`), then `>` doesn't trigger. We get completion items from server1 only. This happens because the `completion_timer` for the `-` trigger is still pending. Solution: If the next character arrived enough quickly (< 25 ms), replace the existing deferred autotrigger with a new one that matches this later character.
* refactor(lua): consistent use of local aliasesChristian Clason2025-08-28
|
* vim-patch:9.1.1590: cannot perform autocompletion (#35141)zeertzjq2025-08-03
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: cannot perform autocompletion Solution: Add the 'autocomplete' option value (Girish Palya) This change introduces the 'autocomplete' ('ac') boolean option to enable automatic popup menu completion during insert mode. When enabled, Vim shows a completion menu as you type, similar to pressing |i\_CTRL-N| manually. The items are collected from sources defined in the 'complete' option. To ensure responsiveness, this feature uses a time-sliced strategy: - Sources earlier in the 'complete' list are given more time. - If a source exceeds its allocated timeout, it is interrupted. - The next source is then started with a reduced timeout (exponentially decayed). - A small minimum ensures every source still gets a brief chance to contribute. The feature is fully compatible with other |i_CTRL-X| completion modes, which can temporarily suspend automatic completion when triggered. See :help 'autocomplete' and :help ins-autocompletion for more details. To try it out, use :set ac You should see a popup menu appear automatically with suggestions. This works seamlessly across: - Large files (multi-gigabyte size) - Massive codebases (:argadd thousands of .c or .h files) - Large dictionaries via the `k` option - Slow or blocking LSP servers or user-defined 'completefunc' Despite potential slowness in sources, the menu remains fast, responsive, and useful. Compatibility: This mode is fully compatible with existing completion methods. You can still invoke any CTRL-X based completion (e.g., CTRL-X CTRL-F for filenames) at any time (CTRL-X temporarily suspends 'autocomplete'). To specifically use i_CTRL-N, dismiss the current popup by pressing CTRL-E first. --- How it works To keep completion snappy under all conditions, autocompletion uses a decaying time-sliced algorithm: - Starts with an initial timeout (80ms). - If a source does not complete within the timeout, it's interrupted and the timeout is halved for the next source. - This continues recursively until a minimum timeout (5ms) is reached. - All sources are given a chance, but slower ones are de-prioritized quickly. Most of the time, matches are computed well within the initial window. --- Implementation details - Completion logic is mostly triggered in `edit.c` and handled in insexpand.c. - Uses existing inc_compl_check_keys() mechanism, so no new polling hooks are needed. - The completion system already checks for user input periodically; it now also checks for timer expiry. --- Design notes - The menu doesn't continuously update after it's shown to prevent visual distraction (due to resizing) and ensure the internal list stays synchronized with the displayed menu. - The 'complete' option determines priority—sources listed earlier get more time. - The exponential time-decay mechanism prevents indefinite collection, contributing to low CPU usage and a minimal memory footprint. - Timeout values are intentionally not configurable—this system is optimized to "just work" out of the box. If autocompletion feels slow, it typically indicates a deeper performance bottleneck (e.g., a slow custom function not using `complete_check()`) rather than a configuration issue. --- Performance Based on testing, the total roundtrip time for completion is generally under 200ms. For common usage, it often responds in under 50ms on an average laptop, which falls within the "feels instantaneous" category (sub-100ms) for perceived user experience. | Upper Bound (ms) | Perceived UX |----------------- |------------- | <100 ms | Excellent; instantaneous | <200 ms | Good; snappy | >300 ms | Noticeable lag | >500 ms | Sluggish/Broken --- Why this belongs in core: - Minimal and focused implementation, tightly integrated with existing Insert-mode completion logic. - Zero reliance on autocommands and external scripting. - Makes full use of Vim’s highly composable 'complete' infrastructure while avoiding the complexity of plugin-based solutions. - Gives users C native autocompletion with excellent responsiveness and no configuration overhead. - Adds a key UX functionality in a simple, performant, and Vim-like way. closes: vim/vim#17812 https://github.com/vim/vim/commit/af9a7a04f18693eee4400dd134135527f4e8cd5f Co-authored-by: Girish Palya <girishji@gmail.com>
* refactor(lsp): use `vim.lsp.buf_request_all` internally (#34604)Maria José Solano2025-06-23
|
* fix: type fixesLewis Russell2025-06-06
| | | | Type fixes caught by emmylua
* fix(lsp): fix error with InsertReplaceEdit events #33973Evan Hahn2025-05-22
| | | | | | | | | | | | | | | | | | | | | | | | | Problem: Some LSPs cause the following completion error (reformatted slightly): Error executing vim.schedule lua callback: .../runtime/lua/vim/lsp/completion.lua:373 attempt to index field 'range' (a nil value) This is because an internal function assumes edits are either missing or of type `TextEdit`, but there's a third [possibility][0] that's not handled: the `InsertReplaceEdit`. This was previously reported in at least two issues: - https://github.com/neovim/neovim/issues/33142 - https://github.com/neovim/neovim/issues/33224 Solution: Don't assume the edit is a `TextEdit`. This implicitly handles `InsertReplaceEdit`s. Also, add a test case for this, which previously caused an error. [0]: https://github.com/neovim/neovim/blob/2c07428966a74c76003e00e2a37bf98eb8802c93/runtime/lua/vim/lsp/_meta/protocol.lua#L1099
* fix(lsp): improve error completion message #33812glepnir2025-05-04
| | | | | | | problem: Error notifications from LSP responses were difficult to read due to inconsistent formatting and missing critical information like client name and error codes. solution: Implemented a more structured error notification format using pipe separators to clearly display client name, error code (when available), and error message.
* docs(lsp): completion.enable #33063Mathias Fußenegger2025-03-26
|
* docs: news, lsp autocomplete #33047Justin M. Keyes2025-03-26
|
* docs: LSP completion #33006Justin M. Keyes2025-03-21
|
* docs: miscJustin M. Keyes2025-03-17
|
* refactor(lsp)!: rename lsp.completion.trigger() to get() (#32911)Mathias Fußenegger2025-03-16
| | | | | | | | | | | | Problem: `trigger` is a custom word not yet used in APIs. Solution: Use `get` instead because the main effect is that the completion candidates will be collected (and shown by default, but follow-up commits are planned to add an `on_result` callback that allows more general handling). --------- Co-authored-by: Christian Clason <c.clason@uni-graz.at>
* fix(lsp): wrapped ctx in opts before passed to vim.lsp.completion.trigger #32837glepnir2025-03-11
| | | | | Problem: ctx is passed directly to M.trigger. In fact, it is a field of opts. Solution: wrapped in a table and passed to M.trigger.
* feat(lsp): support completion context #32793Maria José Solano2025-03-10
| | | | | | | | | Problem: vim.lsp.completion with "autotrigger" enabled, does not send completion context, even though it has all the necessary info. Solution: Include the context for "autotrigger". trigger() also optionally accepts context when manually invoked.
* docs: misc #31996Justin M. Keyes2025-03-02
|
* fix(lsp): unify get_completion_word for textEdits/insertTextMathias Fussenegger2025-02-22
| | | | | | | | | | | | | | Problem: After https://github.com/neovim/neovim/pull/32377 selecting snippets provided by luals inserted the multi-line text before accepting the candidates. That's inconsistent with servers who provide `textEdit` instead of `insertText` and having lines shift up/down while cycling through the completion candidates is a bit irritating. Solution: Use the logic used for `textEdit` snippets also for `insertText`
* feat(lsp): add support for completionItem.command resolvingMathias Fussenegger2025-02-14
| | | | | | | | `command` was already resolved via a `completionItem/resolve` request but only if `additionalTextEdits` were also present, and the `resolveSupport` capability wasn't listed. Closes https://github.com/neovim/neovim/issues/32406
* fix(lsp): clear word when expand multi-lines word (#32393)glepnir2025-02-13
| | | | | Problem: When expanding a completion item that contains a multi-line word, the word is not deleted correctly. Solution: If the word contains a line break, delete the text from Context.cursor to the current cursor position.
* fix(lsp): autotrigger should only trigger on client's triggerCharacters (#32266)Robert Muir2025-02-13
| | | | | | | | | | | | Problem: autotrigger option of vim.lsp.completion.enable() would trigger all clients, as long as it matched at least one client's triggerCharacters. Solution: trigger only the clients with triggerCharacters matching the character. overtriggering still happens if any client returns isIncomplete=true (this case is more involved). Co-authored-by: Mathias Fussenegger <f.mathias@zignar.net>
* fix: resolve all remaining LuaLS diagnosticsLewis Russell2025-01-27
|
* fix: completion.enable(false,...) deletes invalid augroup #32121Konrad Malik2025-01-20
| | | | | | | | | | | | | | | | Problem: vim.lsp.completion.enable(true, client.id, bufnr) vim.lsp.completion.enable(false, client.id, bufnr) Error detected while processing LspDetach Autocommands for "*": Error executing lua callback: …/lsp/completion.lua:701: Vim:E367: No such group: "vim/lsp/completion-22" stack traceback: [C]: in function 'nvim_del_augroup_by_name' …/lsp/completion.lua:701: in function 'disable_completions' …/lsp/completion.lua:724: in function 'enable' Solution: Delete the correct augroup.
* fix(lsp): don't use completion filterText if prefix is emptyMathias Fussenegger2025-01-19
| | | | | | | | Follow up to https://github.com/neovim/neovim/pull/32072 If there is no prefix (e.g. at the start of word boundary or a line), it always used the `filterText` because the `match` function always returned false.
* fix(lsp): use filterText as word if textEdit/label doesn't matchMathias Fussenegger2025-01-17
| | | | | | | | | | | | | | | | | | | | | | | | | Problem: With language servers like lemminx, completing xml tags like `<mo` first shows the right candidates (`modules`) but after typing `d` the candidates disappear. This is because the server returns: [...] filterText = "<module", label = "module", textEdit = { newText = "<module>$1</module>$0", Which resulted in `module` being used as `word`, and `module` doesn't match the prefix `<mo`. Typing `d` causes the `complete()` filtering mechanism to kick in and remove the entry. Solution: Use `<module` from the `filterText` as `word` if the textEdit/label heuristic doesn't match.
* refactor: use nvim.foo.bar format for autocommand groupsMaria José Solano2025-01-14
|
* refactor: add vim._resolve_bufnrLewis Russell2024-12-07
|
* refactor(lsp): rename `offset_encoding` to `position_encoding` #31286Yi Ming2024-11-25
| | | | | | | | Problem: LSP spec uses the term "position encoding" where we say "offset encoding". Solution: - Rename it everywhere except `vim.lsp.Client.offset_encoding` (which would be breaking). - Mention "position encoding" in the documentation for `vim.lsp.Client.offset_encoding`.
* feat(lsp): deprecate non-method client functionsLewis Russell2024-11-20
| | | | | | | | | | | | | | Deprecated: - `client.request()` -> `client:request()` - `client.request_sync()` -> `client:request_sync()` - `client.notify()` -> `client:notify()` - `client.cancel_request()` -> `client:cancel_request()` - `client.stop()` -> `client:stop()` - `client.is_stopped()` `client:is_stopped()` - `client.supports_method()` -> `client:supports_method()` - `client.on_attach()` -> `client:on_attach()` Fixed docgen to link class fields to the full function doc.
* fix(lsp): filter completion candidates based on completeopt (#30945)Kristijan Husak2024-11-13
|
* refactor(lsp): drop str_byteindex/str_utfindex wrappers #30915Tristan Knight2024-10-26
| | | | | * deprecate old signatures * move to new str_byteindex/str_utfindex signature * use single-underscore name (double-underscore is reserved for Lua itself)
* feat(lsp): deprecate execute_command with client:exec_cmdLewis Russell2024-10-24
|
* docs: update autotrigger description of vim.lsp.compleiton.BufferOpts (#30796)glepnir2024-10-13
| | | Currently the behavior of autotrigger is not well documented.
* fix(lsp): fix cursor position after snippet expansion (#30659)Tomasz N2024-10-10
| | | | | | | | | | | | Problem: on `CompleteDone` cursor can jump to the end of line instead of the end of the completed word. Solution: remove only inserted word for snippet expansion instead of everything until eol. Fixes #30656 Co-authored-by: Mathias Fussenegger <f.mathias@zignar.net> Co-authored-by: Justin M. Keyes <justinkz@gmail.com>