-
Notifications
You must be signed in to change notification settings - Fork 227
/
Copy pathmini-completion.txt
403 lines (324 loc) · 17 KB
/
mini-completion.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
*mini.completion* Completion and signature help
*MiniCompletion*
MIT License Copyright (c) 2021 Evgeni Chasnovski
==============================================================================
Key design ideas:
- Have an async (with customizable "debounce" delay) "two-stage chain
completion": first try to get completion items from LSP client (if set
up) and if no result, fallback to custom action.
- Managing completion is done as much with Neovim's built-in tools as
possible. |popupmenu-completion| is used to show completion suggestions.
Features:
- Two-stage chain completion:
- First stage is an LSP completion implemented via
|MiniCompletion.completefunc_lsp()|. It should be set up as either
|completefunc| or |omnifunc|. It tries to get completion items from
LSP client (via 'textDocument/completion' request). Custom
preprocessing of response items is possible (with
`MiniCompletion.config.lsp_completion.process_items`), for example
with fuzzy matching. By default items directly starting with completed
word are kept and are sorted according to LSP specification.
Supports `additionalTextEdits`, like auto-import and others (see 'Notes'),
and snippet items (best results require |mini.snippets| dependency).
- If first stage is not set up or resulted into no candidates, fallback
action is executed. The most tested actions are Neovim's built-in
insert completion (see |ins-completion|).
- Automatic display in floating window of completion item info (via
'completionItem/resolve' request) and signature help (with highlighting
of active parameter if LSP server provides such information).
Signature help is shown if character to cursor's left is a dedicated trigger
character (configured in `signatureHelpProvider.triggerCharacters` of LSP
server capabilities) and updated without delay if is currently opened.
Already shown window for signature help is fixed and is closed when there
is nothing to show, its text is different, or when leaving Insert mode.
Scroll in either info/signature window with `<C-f>` / `<C-b>` (by default).
- Automatic actions are done after some configurable amount of delay. This
reduces computational load and allows fast typing (completion and
signature help) and item selection (item info)
- Force two-stage/fallback completion (`<C-Space>` / `<A-Space>` by default).
- LSP kind highlighting ("Function", "Keyword", etc.). Requires Neovim>=0.11.
By default uses "lsp" category of |MiniIcons| (if enabled). Can be customized
via `config.lsp_completion.process_items` by adding field <kind_hlgroup>
(same meaning as in |complete-items|) to items.
What it doesn't do:
- Many configurable sources.
- Automatic mapping of `<CR>`, `<Tab>`, etc., as those tend to have highly
variable user expectations. See 'Helpful mappings' for suggestions.
# Dependencies ~
Suggested dependencies (provide extra functionality, will work without them):
- Enabled |MiniIcons| module to highlight LSP kind (requires Neovim>=0.11).
If absent, |MiniCompletion.default_process_items()| does not add highlighting.
Also take a look at |MiniIcons.tweak_lsp_kind()|.
- Enabled |MiniSnippets| module for better snippet handling (much recommended).
If absent and custom snippet insert is not configured, |vim.snippet.expand()|
is used on Neovim>=0.10 (nothing extra is done on earlier versions).
See |MiniCompletion.default_snippet_insert()|.
# Setup ~
This module needs a setup with `require('mini.completion').setup({})`
(replace `{}` with your `config` table). It will create global Lua table
`MiniCompletion` which you can use for scripting or manually (with
`:lua MiniCompletion.*`).
See |MiniCompletion.config| for `config` structure and default values.
You can override runtime config settings locally to buffer inside
`vim.b.minicompletion_config` which should have same structure as
`MiniCompletion.config`. See |mini.nvim-buffer-local-config| for more details.
# Snippets ~
As per LSP specification, some completion items can be supplied in the form of
snippet - a template with both pre-defined text and places (called "tabstops")
for user to interactively change/add text during snippet session.
In 'mini.completion' items that will insert snippet have "S" symbol shown in
the popup (as part of `menu` in |complete-items|). To actually insert a snippet:
- Select an item via <C-n> / <C-p>. This will insert item's label (usually not
full snippet) first to reduce visual flicker. The full snippet text will be
shown in info window if LSP server doesn't provide its own info for an item.
- Press <C-y> (|complete_CTRL-Y|) or attempt inserting a non-keyword character
(like <CR>; new character will be removed). It will clear text from previous
step, set cursor, and call `lsp_completion.snippet_insert` with snippet text.
- Press <C-e> (|complete_CTRL-E|) to cancel snippet insert and properly end
completion.
See |MiniCompletion.default_snippet_insert()| for overview of how to work with
inserted snippets.
Notes:
- To stop LSP server from suggesting snippets, disable (set to `false`) the
following capability during LSP server start:
`textDocument.completion.completionItem.snippetSupport`.
- If snippet body doesn't contain tabstops, `lsp_completion.snippet_insert`
is not called and text is inserted as is.
# Notes ~
- More appropriate (albeit slightly advanced) LSP completion setup is to set
it not on every |BufEnter| event (default), but on every attach of LSP
client. To do that:
- Use in initial config:
`lsp_completion = { source_func = 'omnifunc', auto_setup = false }`.
- In `on_attach()` of every LSP client set 'omnifunc' option to exactly
`v:lua.MiniCompletion.completefunc_lsp`.
- The `additionalTextEdits` data can come from LSP server only in response for
"textDocument/resolve". For these servers select completion item and wait
for `config.delay.info` time plus server response time to process the request.
- Uses `vim.lsp.protocol.CompletionItemKind` map in LSP step to show a readable
version of item's kind. Modify it directly to change what is displayed.
If you have |mini.icons| enabled, take a look at |MiniIcons.tweak_lsp_kind()|.
- If you have trouble using custom (overridden) |vim.ui.input|, disable
'mini.completion' for input buffer (usually based on its 'filetype').
# Comparisons ~
- 'hrsh7th/nvim-cmp':
- Implements own popup menu to show completion candidates, while this
module reuses |ins-completion-menu|.
- Has more complex design which allows multiple sources, each in a form of
a separate plugin. This module has two built-in: LSP and fallback.
- Requires separate plugin for automated signature help.
- Implements own "ghost text" feature, while this module does not.
- 'Saghen/blink.cmp':
- Mostly similar to 'nvim-cmp' comparison: provides more features at the
cost of more code and config complexity, while this module is designed
to provide only a handful of "enough" features while relying on Neovim's
built-in capabilities as much as possible.
- Both provide automated signature help out of the box.
# Helpful mappings ~
To use `<Tab>` and `<S-Tab>` for navigation through completion list, make
these mappings: >lua
local imap_expr = function(lhs, rhs)
vim.keymap.set('i', lhs, rhs, { expr = true })
end
imap_expr('<Tab>', [[pumvisible() ? "\<C-n>" : "\<Tab>"]])
imap_expr('<S-Tab>', [[pumvisible() ? "\<C-p>" : "\<S-Tab>"]])
<
To get more consistent behavior of `<CR>`, you can use this template in
your 'init.lua' to make customized mapping: >lua
local keycode = vim.keycode or function(x)
return vim.api.nvim_replace_termcodes(x, true, true, true)
end
local keys = {
['cr'] = keycode('<CR>'),
['ctrl-y'] = keycode('<C-y>'),
['ctrl-y_cr'] = keycode('<C-y><CR>'),
}
_G.cr_action = function()
if vim.fn.pumvisible() ~= 0 then
-- If popup is visible, confirm selected item or add new line otherwise
local item_selected = vim.fn.complete_info()['selected'] ~= -1
return item_selected and keys['ctrl-y'] or keys['ctrl-y_cr']
else
-- If popup is not visible, use plain `<CR>`. You might want to customize
-- according to other plugins. For example, to use 'mini.pairs', replace
-- next line with `return require('mini.pairs').cr()`
return keys['cr']
end
end
vim.keymap.set('i', '<CR>', 'v:lua._G.cr_action()', { expr = true })
<
# Highlight groups ~
* `MiniCompletionActiveParameter` - signature active parameter.
By default displayed as plain underline.
To change any highlight group, modify it directly with |:highlight|.
# Disabling ~
To disable, set `vim.g.minicompletion_disable` (globally) or
`vim.b.minicompletion_disable` (for a buffer) to `true`. Considering high
number of different scenarios and customization intentions, writing exact
rules for disabling module's functionality is left to user. See
|mini.nvim-disabling-recipes| for common recipes.
------------------------------------------------------------------------------
*MiniCompletion.setup()*
`MiniCompletion.setup`({config})
Module setup
Parameters ~
{config} `(table|nil)` Module config table. See |MiniCompletion.config|.
Usage ~
>lua
require('mini.completion').setup() -- use default config
-- OR
require('mini.completion').setup({}) -- replace {} with your config table
<
------------------------------------------------------------------------------
*MiniCompletion.config*
`MiniCompletion.config`
Module config
Default values:
>lua
MiniCompletion.config = {
-- Delay (debounce type, in ms) between certain Neovim event and action.
-- This can be used to (virtually) disable certain automatic actions by
-- setting very high delay time (like 10^7).
delay = { completion = 100, info = 100, signature = 50 },
-- Configuration for action windows:
-- - `height` and `width` are maximum dimensions.
-- - `border` defines border (as in `nvim_open_win()`; default "single").
window = {
info = { height = 25, width = 80, border = nil },
signature = { height = 25, width = 80, border = nil },
},
-- Way of how module does LSP completion
lsp_completion = {
-- `source_func` should be one of 'completefunc' or 'omnifunc'.
source_func = 'completefunc',
-- `auto_setup` should be boolean indicating if LSP completion is set up
-- on every `BufEnter` event.
auto_setup = true,
-- A function which takes LSP 'textDocument/completion' response items
-- and word to complete. Output should be a table of the same nature as
-- input items. Common use case is custom filter/sort.
-- Default: `default_process_items`
process_items = nil,
-- A function which takes a snippet as string and inserts it at cursor.
-- Default: `default_snippet_insert` which tries to use 'mini.snippets'
-- and falls back to `vim.snippet.expand` (on Neovim>=0.10).
snippet_insert = nil,
},
-- Fallback action as function/string. Executed in Insert mode.
-- To use built-in completion (`:h ins-completion`), set its mapping as
-- string. Example: set '<C-x><C-l>' for 'whole lines' completion.
fallback_action = '<C-n>',
-- Module mappings. Use `''` (empty string) to disable one. Some of them
-- might conflict with system mappings.
mappings = {
-- Force two-step/fallback completions
force_twostep = '<C-Space>',
force_fallback = '<A-Space>',
-- Scroll info/signature window down/up. When overriding, check for
-- conflicts with built-in keys for popup menu (like `<C-u>`/`<C-o>`
-- for 'completefunc'/'omnifunc' source function; or `<C-n>`/`<C-p>`).
scroll_down = '<C-f>',
scroll_up = '<C-b>',
},
-- Whether to set Vim's settings for better experience (modifies
-- `shortmess` and `completeopt`)
set_vim_settings = true,
}
<
------------------------------------------------------------------------------
*MiniCompletion.complete_twostage()*
`MiniCompletion.complete_twostage`({fallback}, {force})
Run two-stage completion
Parameters ~
{fallback} `(boolean|nil)` Whether to use fallback completion. Default: `true`.
{force} `(boolean|nil)` Whether to force update of completion popup.
Default: `true`.
------------------------------------------------------------------------------
*MiniCompletion.complete_fallback()*
`MiniCompletion.complete_fallback`()
Run fallback completion
------------------------------------------------------------------------------
*MiniCompletion.scroll()*
`MiniCompletion.scroll`({direction})
Scroll in info/signature window
Designed to be used in |:map-<expr>|.
Scrolling is done as if |CTRL-F| and |CTRL-B| is pressed inside target window.
Used in default `config.mappings.scroll_xxx` mappings.
Parameters ~
{direction} `(string)` One of `"down"` or `"up"`.
Return ~
`(boolean)` Whether scroll is scheduled to be done.
------------------------------------------------------------------------------
*MiniCompletion.stop()*
`MiniCompletion.stop`({actions})
Stop actions
This stops currently active (because of module delay or LSP answer delay)
actions.
Designed to be used with |autocmd|. No need to use it directly, everything
is setup in |MiniCompletion.setup|.
Parameters ~
{actions} `(table|nil)` Array containing any of 'completion', 'info', or
'signature' string. Default: array containing all of them.
------------------------------------------------------------------------------
*MiniCompletion.completefunc_lsp()*
`MiniCompletion.completefunc_lsp`({findstart}, {base})
Module's |complete-function|
This is the main function which enables two-stage completion. It should be
set as one of |completefunc| or |omnifunc|.
No need to use it directly, everything is setup in |MiniCompletion.setup|.
------------------------------------------------------------------------------
*MiniCompletion.default_process_items()*
`MiniCompletion.default_process_items`({items}, {base}, {opts})
Default processing of LSP items
Steps:
- Filter and sort items according to supplied method.
- If |MiniIcons| is enabled, add <kind_hlgroup> based on the "lsp" category.
Example of forcing fuzzy matching: >lua
local opts = { filtersort = 'fuzzy' }
local process_items = function(items, base)
return MiniCompletion.default_process_items(items, base, opts)
end
require('mini.completion').setup({
lsp_completion = { process_items = process_items },
})
<
Parameters ~
{items} `(table)` Array of items from LSP response.
{base} `(string)` Base for which completion is done. See |complete-functions|.
{opts} `(table|nil)` Options. Possible fields:
- <filtersort> `(string|function)` - method of filtering and sorting items.
If string, should be one of the following:
- `'prefix'` - filter out items not starting with `base`, sort according
to LSP specification. Use `filterText` and `sortText` respectively with
fallback to `label`.
- `'fuzzy'` - filter and sort with |matchfuzzy()| using `filterText`.
- `'none'` - no filter and no sort.
If callable, should take `items` and `base` arguments and return items array.
Default: `'fuzzy'` if 'completeopt' contains "fuzzy", `'prefix'` otherwise.
Return ~
`(table)` Array of processed items from LSP response.
------------------------------------------------------------------------------
*MiniCompletion.default_snippet_insert()*
`MiniCompletion.default_snippet_insert`({snippet})
Default snippet insert
Order of preference:
- Use |MiniSnippets| if set up (i.e. there is `require('mini.snippets').setup()`).
- Use |vim.snippet.expand()| on Neovim>=0.10
- Add snippet text at cursor as is.
After snippet is inserted, user is expected to navigate/jump between dedicated
places (tabstops) to adjust inserted text as needed:
- |MiniSnippets| by default uses <C-l> / <C-h> to jump to next/previous tabstop.
Can be adjusted in `mappings` of |MiniSnippets.config|.
- |vim.snippet| on Neovim=0.10 requires manually created mappings for jumping
between tabstops (see |vim.snippet.jump()|). Neovim>=0.11 sets them up
automatically to <Tab> / <S-Tab> (if not overridden by user).
End session by navigating all the way to the last tabstop. In 'mini.snippets':
- Also make any text edit or exit Insert mode to end the session. This allows
smoother navigation to previous tabstops in case of a lately spotted typo.
- Press `<C-c>` to force session stop.
Parameters ~
{snippet} `(string)` Snippet body to insert at cursor.
See also ~
|MiniSnippets-session| if 'mini.snippets' is set up.
|vim.snippet| for Neovim's built-in snippet engine.
vim:tw=78:ts=8:noet:ft=help:norl: