diff options
| author | Mike Vink <mike@pionative.com> | 2025-01-19 13:52:52 +0100 |
|---|---|---|
| committer | Mike Vink <mike@pionative.com> | 2025-01-19 13:52:52 +0100 |
| commit | b77413ff8f59f380612074f0c9bd49093d8db695 (patch) | |
| tree | 32c39a811ba96ed4ab0a1c81cce9f8d518ed7e31 /lua/blink/cmp/init.lua | |
Squashed 'mut/neovim/pack/plugins/start/blink.cmp/' content from commit 1cc3b1a
git-subtree-dir: mut/neovim/pack/plugins/start/blink.cmp
git-subtree-split: 1cc3b1a908fbcfd15451c4772759549724f38524
Diffstat (limited to 'lua/blink/cmp/init.lua')
| -rw-r--r-- | lua/blink/cmp/init.lua | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/lua/blink/cmp/init.lua b/lua/blink/cmp/init.lua new file mode 100644 index 0000000..deb9116 --- /dev/null +++ b/lua/blink/cmp/init.lua @@ -0,0 +1,235 @@ +--- @class blink.cmp.API +local cmp = {} + +local has_setup = false +--- Initializes blink.cmp with the given configuration and initiates the download +--- for the fuzzy matcher's prebuilt binaries, if necessary +--- @param opts? blink.cmp.Config +function cmp.setup(opts) + if has_setup then return end + has_setup = true + + opts = opts or {} + + if vim.fn.has('nvim-0.10') == 0 then + vim.notify('blink.cmp requires nvim 0.10 and newer', vim.log.levels.ERROR, { title = 'blink.cmp' }) + return + end + + local config = require('blink.cmp.config') + config.merge_with(opts) + + require('blink.cmp.fuzzy.download').ensure_downloaded(function(err) + if err then vim.notify(err, vim.log.levels.ERROR) end + + -- setup highlights, keymap, completion and signature help + require('blink.cmp.highlights').setup() + require('blink.cmp.keymap').setup() + require('blink.cmp.completion').setup() + if config.signature.enabled then require('blink.cmp.signature').setup() end + end) +end + +------- Public API ------- + +--- Checks if the completion menu is currently visible +--- @return boolean +function cmp.is_visible() + return require('blink.cmp.completion.windows.menu').win:is_open() + or require('blink.cmp.completion.windows.ghost_text').is_open() +end + +--- Show the completion window +--- @params opts? { providers?: string[], callback?: fun() } +function cmp.show(opts) + opts = opts or {} + + -- TODO: when passed a list of providers, we should check if we're already showing the menu + -- with that list of providers + if require('blink.cmp.completion.windows.menu').win:is_open() and not (opts and opts.providers) then return end + + vim.schedule(function() + require('blink.cmp.completion.windows.menu').auto_show = true + + -- HACK: because blink is event based, we don't have an easy way to know when the "show" + -- event completes. So we wait for the list to trigger the show event and check if we're + -- still in the same context + local context + if opts.callback then + vim.api.nvim_create_autocmd('User', { + pattern = 'BlinkCmpShow', + callback = function(event) + if context ~= nil and event.data.context.id == context.id then opts.callback() end + end, + once = true, + }) + end + + context = require('blink.cmp.completion.trigger').show({ + force = true, + providers = opts and opts.providers, + trigger_kind = 'manual', + }) + end) + return true +end + +--- Hide the completion window +--- @params opts? { callback?: fun() } +function cmp.hide(opts) + if not cmp.is_visible() then return end + + vim.schedule(function() + require('blink.cmp.completion.trigger').hide() + if opts and opts.callback then opts.callback() end + end) + return true +end + +--- Cancel the current completion, undoing the preview from auto_insert +--- @params opts? { callback?: fun() } +function cmp.cancel(opts) + if not cmp.is_visible() then return end + vim.schedule(function() + require('blink.cmp.completion.list').undo_preview() + require('blink.cmp.completion.trigger').hide() + if opts and opts.callback then opts.callback() end + end) + return true +end + +--- Accept the current completion item +--- @param opts? blink.cmp.CompletionListAcceptOpts +function cmp.accept(opts) + opts = opts or {} + if not cmp.is_visible() then return end + + local completion_list = require('blink.cmp.completion.list') + local item = opts.index ~= nil and completion_list.items[opts.index] or completion_list.get_selected_item() + if item == nil then return end + + vim.schedule(function() completion_list.accept(opts) end) + return true +end + +--- Select the first completion item, if there's no selection, and accept +--- @param opts? blink.cmp.CompletionListSelectAndAcceptOpts +function cmp.select_and_accept(opts) + if not cmp.is_visible() then return end + + local completion_list = require('blink.cmp.completion.list') + vim.schedule( + function() + completion_list.accept({ + index = completion_list.selected_item_idx or 1, + callback = opts and opts.callback, + }) + end + ) + return true +end + +--- Select the previous completion item +--- @param opts? blink.cmp.CompletionListSelectOpts +function cmp.select_prev(opts) + if not cmp.is_visible() then return end + vim.schedule(function() require('blink.cmp.completion.list').select_prev(opts) end) + return true +end + +--- Select the next completion item +--- @param opts? blink.cmp.CompletionListSelectOpts +function cmp.select_next(opts) + if not cmp.is_visible() then return end + vim.schedule(function() require('blink.cmp.completion.list').select_next(opts) end) + return true +end + +--- Gets the currently selected completion item +function cmp.get_selected_item() return require('blink.cmp.completion.list').get_selected_item() end + +--- Show the documentation window +function cmp.show_documentation() + local menu = require('blink.cmp.completion.windows.menu') + local documentation = require('blink.cmp.completion.windows.documentation') + if documentation.win:is_open() or not menu.win:is_open() then return end + + local context = require('blink.cmp.completion.list').context + local item = require('blink.cmp.completion.list').get_selected_item() + if not item or not context then return end + + vim.schedule(function() documentation.show_item(context, item) end) + return true +end + +--- Hide the documentation window +function cmp.hide_documentation() + local documentation = require('blink.cmp.completion.windows.documentation') + if not documentation.win:is_open() then return end + + vim.schedule(function() documentation.close() end) + return true +end + +--- Scroll the documentation window up +--- @param count? number +function cmp.scroll_documentation_up(count) + local documentation = require('blink.cmp.completion.windows.documentation') + if not documentation.win:is_open() then return end + + vim.schedule(function() documentation.scroll_up(count or 4) end) + return true +end + +--- Scroll the documentation window down +--- @param count? number +function cmp.scroll_documentation_down(count) + local documentation = require('blink.cmp.completion.windows.documentation') + if not documentation.win:is_open() then return end + + vim.schedule(function() documentation.scroll_down(count or 4) end) + return true +end + +--- Check if a snippet is active, optionally filtering by direction +--- @param filter? { direction?: number } +function cmp.snippet_active(filter) return require('blink.cmp.config').snippets.active(filter) end + +--- Move the cursor forward to the next snippet placeholder +function cmp.snippet_forward() + local snippets = require('blink.cmp.config').snippets + if not snippets.active({ direction = 1 }) then return end + vim.schedule(function() snippets.jump(1) end) + return true +end + +--- Move the cursor backward to the previous snippet placeholder +function cmp.snippet_backward() + local snippets = require('blink.cmp.config').snippets + if not snippets.active({ direction = -1 }) then return end + vim.schedule(function() snippets.jump(-1) end) + return true +end + +--- Tells the sources to reload a specific provider or all providers (when nil) +--- @param provider? string +function cmp.reload(provider) require('blink.cmp.sources.lib').reload(provider) end + +--- Gets the capabilities to pass to the LSP client +--- @param override? lsp.ClientCapabilities Overrides blink.cmp's default capabilities +--- @param include_nvim_defaults? boolean Whether to include nvim's default capabilities +function cmp.get_lsp_capabilities(override, include_nvim_defaults) + return require('blink.cmp.sources.lib').get_lsp_capabilities(override, include_nvim_defaults) +end + +--- Add a new source provider at runtime +--- @param id string +--- @param provider_config blink.cmp.SourceProviderConfig +function cmp.add_provider(id, provider_config) + local config = require('blink.cmp.config') + assert(config.sources.providers[id] == nil, 'Provider with id ' .. id .. ' already exists') + require('blink.cmp.config.sources').validate_provider(id, provider_config) + config.sources.providers[id] = provider_config +end + +return cmp |
