273 lines
11 KiB
Plaintext
273 lines
11 KiB
Plaintext
*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.
|
|
|
|
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 which are not snippets and
|
|
directly start with completed word are kept and sorted according to
|
|
LSP specification. Supports `additionalTextEdits`, like auto-import
|
|
and others (see 'Notes').
|
|
- 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). After
|
|
opening, window for signature help is fixed and is closed when there is
|
|
nothing to show, text is different or
|
|
when leaving Insert mode.
|
|
|
|
- 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)
|
|
|
|
- User can force two-stage completion via
|
|
|MiniCompletion.complete_twostage()| (by default is mapped to
|
|
`<C-Space>`) or fallback completion via
|
|
|MiniCompletion.complete_fallback()| (mapped to `<M-Space>`).
|
|
|
|
What it doesn't do:
|
|
- Snippet expansion.
|
|
- Many configurable sources.
|
|
- Automatic mapping of `<CR>`, `<Tab>`, etc., as those tend to have highly
|
|
variable user expectations. See 'Helpful key mappings' for suggestions.
|
|
|
|
# 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.
|
|
|
|
# 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`.
|
|
|
|
- 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| (like from
|
|
'stevearc/dressing.nvim'), make automated disable of 'mini.completion'
|
|
for input buffer. For example, currently for 'dressing.nvim' it can be
|
|
with `au FileType DressingInput lua vim.b.minicompletion_disable = true`.
|
|
|
|
- Support of `additionalTextEdits` tries to handle both types of servers:
|
|
- When `additionalTextEdits` are supplied in response to
|
|
'textDocument/completion' request (like currently in 'pyright').
|
|
- When `additionalTextEdits` are supplied in response to
|
|
'completionItem/resolve' request (like currently in
|
|
'typescript-language-server'). In this case to apply edits user needs
|
|
to trigger such request, i.e. select completion item and wait for
|
|
`MiniCompletion.config.delay.info` time plus server response time.
|
|
|
|
# Comparisons ~
|
|
|
|
- 'nvim-cmp':
|
|
- More complex design which allows multiple sources each in form of
|
|
separate plugin. `MiniCompletion` has two built in: LSP and fallback.
|
|
- Supports snippet expansion.
|
|
- Doesn't have customizable delays for basic actions.
|
|
- Doesn't allow fallback action.
|
|
- Doesn't provide signature help.
|
|
|
|
# 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()`).
|
|
window = {
|
|
info = { height = 25, width = 80, border = 'none' },
|
|
signature = { height = 25, width = 80, border = 'none' },
|
|
},
|
|
|
|
-- 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,
|
|
|
|
-- `process_items` should be a function which takes LSP
|
|
-- 'textDocument/completion' response items and word to complete. Its
|
|
-- output should be a table of the same nature as input items. The most
|
|
-- common use-cases are custom filtering and sorting. You can use
|
|
-- default `process_items` as `MiniCompletion.default_process_items()`.
|
|
process_items = --<function: filters out snippets; sorts by LSP specs>,
|
|
},
|
|
|
|
-- Fallback action. It will always be run in Insert mode. To use Neovim's
|
|
-- built-in completion (see `:h ins-completion`), supply its mapping as
|
|
-- string. Example: to use 'whole lines' completion, supply '<C-x><C-l>'.
|
|
fallback_action = --<function: like `<C-n>` completion>,
|
|
|
|
-- Module mappings. Use `''` (empty string) to disable one. Some of them
|
|
-- might conflict with system mappings.
|
|
mappings = {
|
|
force_twostep = '<C-Space>', -- Force two-step completion
|
|
force_fallback = '<A-Space>', -- Force fallback completion
|
|
},
|
|
|
|
-- 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.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})
|
|
Default `MiniCompletion.config.lsp_completion.process_items`
|
|
|
|
|
|
vim:tw=78:ts=8:noet:ft=help:norl: |