Skip to content

Commit c306d24

Browse files
committed
feat(completion)!: add snippet support
Detalis: - Insert snippet completion items (both `Snippet` kind and `insertTextFormat`) respecting their snippet nature. - Update `default_process_items` to not exclude items with snippet kind. Resolve #886
1 parent 337e8e4 commit c306d24

12 files changed

+856
-78
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131

3232
## mini.completion
3333

34+
- BREAKING FEATURE: add snippet support. By default uses 'mini.snippets' to manage snippet session (if enabled, **highly recommended), falls back to `vim.snippet` on Neovim>=0.10. See "Snippets" section in `:h MiniCompletion` for more details.<br>
35+
This is a breaking change mostly because items with `Snippet` kind are no longer filtered out by default.
3436
- FEATURE: add scrolling in info and signature window. By default can be done with `<C-f>` / `<C-b>` when target window is shown. Can be configured via `mappings.scroll_down` and `mappings.scroll_up` config options.
3537
- FEATURE: respect `isIncomplete` in LSP completion response and immediately force new completion request on the next key press.
3638
- FEATURE: both info and signature help windows now use tree-sitter highlighting:

doc/mini-completion.txt

+82-24
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Key design ideas:
1111
up) and if no result, fallback to custom action.
1212

1313
- Managing completion is done as much with Neovim's built-in tools as
14-
possible.
14+
possible. |popupmenu-completion| is used to show completion suggetsions.
1515

1616
Features:
1717
- Two-stage chain completion:
@@ -21,10 +21,10 @@ Features:
2121
LSP client (via 'textDocument/completion' request). Custom
2222
preprocessing of response items is possible (with
2323
`MiniCompletion.config.lsp_completion.process_items`), for example
24-
with fuzzy matching. By default items which are not snippets and
25-
directly start with completed word are kept and sorted according to
26-
LSP specification. Supports `additionalTextEdits`, like auto-import
27-
and others (see 'Notes').
24+
with fuzzy matching. By default items directly starting with completed
25+
word are kept and are sorted according to LSP specification.
26+
Supports `additionalTextEdits`, like auto-import and others (see 'Notes'),
27+
and snippet items (best results require |mini.snippets| dependency).
2828
- If first stage is not set up or resulted into no candidates, fallback
2929
action is executed. The most tested actions are Neovim's built-in
3030
insert completion (see |ins-completion|).
@@ -48,7 +48,6 @@ Features:
4848
(same meaning as in |complete-items|) to items.
4949

5050
What it doesn't do:
51-
- Snippet expansion.
5251
- Many configurable sources.
5352
- Automatic mapping of `<CR>`, `<Tab>`, etc., as those tend to have highly
5453
variable user expectations. See 'Helpful mappings' for suggestions.
@@ -58,8 +57,12 @@ What it doesn't do:
5857
Suggested dependencies (provide extra functionality, will work without them):
5958

6059
- Enabled |MiniIcons| module to highlight LSP kind (requires Neovim>=0.11).
61-
Otherwise |MiniCompletion.default_process_items()| does not add highlighting.
60+
If absent, |MiniCompletion.default_process_items()| does not add highlighting.
6261
Also take a look at |MiniIcons.tweak_lsp_kind()|.
62+
- Enabled |MiniSnippets| module for better snippet handling (much recommended).
63+
If absent and custom snippet insert is not configured, |vim.snippet.expand()|
64+
is used on Neovim>=0.10 (nothing extra is done on earlier versions).
65+
See |MiniCompletion.default_snippet_insert()|.
6366

6467
# Setup ~
6568

@@ -74,33 +77,53 @@ You can override runtime config settings locally to buffer inside
7477
`vim.b.minicompletion_config` which should have same structure as
7578
`MiniCompletion.config`. See |mini.nvim-buffer-local-config| for more details.
7679

80+
# Snippets ~
81+
82+
As per LSP specification, some completion items can be supplied in the form of
83+
snippet - a template with both pre-defined text and places (called "tabstops")
84+
for user to interactively change/add text during snippet session.
85+
86+
In 'mini.completion' items that will insert snippet have "S" symbol shown in
87+
the popup (as part of `menu` in |complete-items|). To actually insert a snippet:
88+
- Select an item via <C-n> / <C-p>. This will insert item's label (usually not
89+
full snippet) first to reduce visual flicker. The full snippet text will be
90+
shown in info window if LSP server doesn't provide its own info for an item.
91+
- Press <C-y> (|complete_CTRL-Y|) or attempt inserting a non-keyword character
92+
(like <CR>; new character will be removed). It will clear text from previous
93+
step, set cursor, and call `lsp_completion.snippet_insert` with snippet text.
94+
- Press <C-e> (|complete_CTRL-E|) to cancel snippet insert and properly end
95+
completion.
96+
97+
See |MiniCompletion.default_snippet_insert()| for overview of how to work with
98+
inserted snippets.
99+
100+
Notes:
101+
- To stop LSP server from suggesting snippets, disable (set to `false`) the
102+
following capability during LSP server start:
103+
`textDocument.completion.completionItem.snippetSupport`.
104+
- If snippet body doesn't contain tabstops, `lsp_completion.snippet_insert`
105+
is not called and text is inserted as is.
106+
77107
# Notes ~
78108

79-
- More appropriate, albeit slightly advanced, LSP completion setup is to set
80-
it not on every `BufEnter` event (default), but on every attach of LSP
109+
- More appropriate (albeit slightly advanced) LSP completion setup is to set
110+
it not on every |BufEnter| event (default), but on every attach of LSP
81111
client. To do that:
82112
- Use in initial config:
83-
`lsp_completion = {source_func = 'omnifunc', auto_setup = false}`.
113+
`lsp_completion = { source_func = 'omnifunc', auto_setup = false }`.
84114
- In `on_attach()` of every LSP client set 'omnifunc' option to exactly
85115
`v:lua.MiniCompletion.completefunc_lsp`.
86116

117+
- The `additionalTextEdits` data can come from LSP server only in response for
118+
"textDocument/resolve". For these servers select completion item and wait
119+
for `config.delay.info` time plus server response time to process the request.
120+
87121
- Uses `vim.lsp.protocol.CompletionItemKind` map in LSP step to show a readable
88122
version of item's kind. Modify it directly to change what is displayed.
89123
If you have |mini.icons| enabled, take a look at |MiniIcons.tweak_lsp_kind()|.
90124

91-
- If you have trouble using custom (overridden) |vim.ui.input| (like from
92-
'stevearc/dressing.nvim'), make automated disable of 'mini.completion'
93-
for input buffer. For example, currently for 'dressing.nvim' it can be
94-
with `au FileType DressingInput lua vim.b.minicompletion_disable = true`.
95-
96-
- Support of `additionalTextEdits` tries to handle both types of servers:
97-
- When `additionalTextEdits` are supplied in response to
98-
'textDocument/completion' request (like currently in 'pyright').
99-
- When `additionalTextEdits` are supplied in response to
100-
'completionItem/resolve' request (like currently in
101-
'typescript-language-server'). In this case to apply edits user needs
102-
to trigger such request, i.e. select completion item and wait for
103-
`MiniCompletion.config.delay.info` time plus server response time.
125+
- If you have trouble using custom (overridden) |vim.ui.input|, disable
126+
'mini.completion' for input buffer (usually based on its 'filetype').
104127

105128
# Comparisons ~
106129

@@ -214,6 +237,11 @@ Default values:
214237
-- input items. Common use case is custom filter/sort.
215238
-- Default: `default_process_items`
216239
process_items = nil,
240+
241+
-- A function which takes a snippet as string and inserts it at cursor.
242+
-- Default: `default_snippet_insert` which tries to use 'mini.snippets'
243+
-- and falls back to `vim.snippet.expand` (on Neovim>=0.10).
244+
snippet_insert = nil,
217245
},
218246

219247
-- Fallback action as function/string. Executed in Insert mode.
@@ -301,7 +329,7 @@ No need to use it directly, everything is setup in |MiniCompletion.setup|.
301329
Default processing of LSP items
302330

303331
Steps:
304-
- Filter out items not matching `base` and snippet items.
332+
- Filter out items not starting with `base`.
305333
- Sort by LSP specification.
306334
- If |MiniIcons| is enabled, add <kind_hlgroup> based on the "lsp" category.
307335

@@ -312,5 +340,35 @@ Parameters ~
312340
Return ~
313341
`(table)` Array of processed items from LSP response.
314342

343+
------------------------------------------------------------------------------
344+
*MiniCompletion.default_snippet_insert()*
345+
`MiniCompletion.default_snippet_insert`({snippet})
346+
Default snippet insert
347+
348+
Order of preference:
349+
- Use |MiniSnippets| if set up (i.e. there is `require('mini.snippets').setup()`).
350+
- Use |vim.snippet.expand()| on Neovim>=0.10
351+
- Add snippet text at cursor as is.
352+
353+
After snippet is inserted, user is expected to navigate/jump between dedicated
354+
places (tabstops) to adjust inserted text as needed:
355+
- |MiniSnippets| by default uses <C-l> / <C-h> to jump to next/previous tabstop.
356+
Can be adjusted in `mappings` of |MiniSnippets.config|.
357+
- |vim.snippet| on Neovim=0.10 requires manually created mappings for jumping
358+
between tabstops (see |vim.snippet.jump()|). Neovim>=0.11 sets them up
359+
automatically to <Tab> / <S-Tab> (if not overridden by user).
360+
361+
End session by navigating all the way to the last tabstop. In 'mini.snippets':
362+
- Also make any text edit or exit Insert mode to end the session. This allows
363+
smoother navigation to previous tabstops in case of a lately spotted typo.
364+
- Press `<C-c>` to force session stop.
365+
366+
Parameters ~
367+
{snippet} `(string)` Snippet body to insert at cursor.
368+
369+
See also ~
370+
|MiniSnippets-session| if 'mini.snippets' is set up.
371+
|vim.snippet| for Neovim's built-in snippet engine.
372+
315373

316374
vim:tw=78:ts=8:noet:ft=help:norl:

0 commit comments

Comments
 (0)