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/config/completion | |
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/config/completion')
| -rw-r--r-- | lua/blink/cmp/config/completion/accept.lua | 72 | ||||
| -rw-r--r-- | lua/blink/cmp/config/completion/documentation.lua | 98 | ||||
| -rw-r--r-- | lua/blink/cmp/config/completion/ghost_text.lua | 19 | ||||
| -rw-r--r-- | lua/blink/cmp/config/completion/init.lua | 42 | ||||
| -rw-r--r-- | lua/blink/cmp/config/completion/keyword.lua | 27 | ||||
| -rw-r--r-- | lua/blink/cmp/config/completion/list.lua | 54 | ||||
| -rw-r--r-- | lua/blink/cmp/config/completion/menu.lua | 223 | ||||
| -rw-r--r-- | lua/blink/cmp/config/completion/trigger.lua | 42 |
8 files changed, 577 insertions, 0 deletions
diff --git a/lua/blink/cmp/config/completion/accept.lua b/lua/blink/cmp/config/completion/accept.lua new file mode 100644 index 0000000..a81aa55 --- /dev/null +++ b/lua/blink/cmp/config/completion/accept.lua @@ -0,0 +1,72 @@ +--- @class (exact) blink.cmp.CompletionAcceptConfig +--- @field create_undo_point boolean Create an undo point when accepting a completion item +--- @field auto_brackets blink.cmp.AutoBracketsConfig + +--- @class (exact) blink.cmp.AutoBracketsConfig +--- @field enabled boolean Whether to auto-insert brackets for functions +--- @field default_brackets string[] Default brackets to use for unknown languages +--- @field override_brackets_for_filetypes table<string, string[] | fun(item: blink.cmp.CompletionItem): string[]> +--- @field force_allow_filetypes string[] Overrides the default blocked filetypes +--- @field blocked_filetypes string[] +--- @field kind_resolution blink.cmp.AutoBracketResolutionConfig Synchronously use the kind of the item to determine if brackets should be added +--- @field semantic_token_resolution blink.cmp.AutoBracketSemanticTokenResolutionConfig Asynchronously use semantic token to determine if brackets should be added + +--- @class (exact) blink.cmp.AutoBracketResolutionConfig +--- @field enabled boolean +--- @field blocked_filetypes string[] + +--- @class (exact) blink.cmp.AutoBracketSemanticTokenResolutionConfig +--- @field enabled boolean +--- @field blocked_filetypes string[] +--- @field timeout_ms number How long to wait for semantic tokens to return before assuming no brackets should be added + +local validate = require('blink.cmp.config.utils').validate +local accept = { + --- @type blink.cmp.CompletionAcceptConfig + default = { + create_undo_point = true, + auto_brackets = { + enabled = true, + default_brackets = { '(', ')' }, + override_brackets_for_filetypes = {}, + force_allow_filetypes = {}, + blocked_filetypes = {}, + kind_resolution = { + enabled = true, + blocked_filetypes = { 'typescriptreact', 'javascriptreact', 'vue', 'rust' }, + }, + semantic_token_resolution = { + enabled = true, + blocked_filetypes = { 'java' }, + timeout_ms = 400, + }, + }, + }, +} + +function accept.validate(config) + validate('completion.accept', { + create_undo_point = { config.create_undo_point, 'boolean' }, + auto_brackets = { config.auto_brackets, 'table' }, + }, config) + validate('completion.accept.auto_brackets', { + enabled = { config.auto_brackets.enabled, 'boolean' }, + default_brackets = { config.auto_brackets.default_brackets, 'table' }, + override_brackets_for_filetypes = { config.auto_brackets.override_brackets_for_filetypes, 'table' }, + force_allow_filetypes = { config.auto_brackets.force_allow_filetypes, 'table' }, + blocked_filetypes = { config.auto_brackets.blocked_filetypes, 'table' }, + kind_resolution = { config.auto_brackets.kind_resolution, 'table' }, + semantic_token_resolution = { config.auto_brackets.semantic_token_resolution, 'table' }, + }, config.auto_brackets) + validate('completion.accept.auto_brackets.kind_resolution', { + enabled = { config.auto_brackets.kind_resolution.enabled, 'boolean' }, + blocked_filetypes = { config.auto_brackets.kind_resolution.blocked_filetypes, 'table' }, + }, config.auto_brackets.kind_resolution) + validate('completion.accept.auto_brackets.semantic_token_resolution', { + enabled = { config.auto_brackets.semantic_token_resolution.enabled, 'boolean' }, + blocked_filetypes = { config.auto_brackets.semantic_token_resolution.blocked_filetypes, 'table' }, + timeout_ms = { config.auto_brackets.semantic_token_resolution.timeout_ms, 'number' }, + }, config.auto_brackets.semantic_token_resolution) +end + +return accept diff --git a/lua/blink/cmp/config/completion/documentation.lua b/lua/blink/cmp/config/completion/documentation.lua new file mode 100644 index 0000000..71784d1 --- /dev/null +++ b/lua/blink/cmp/config/completion/documentation.lua @@ -0,0 +1,98 @@ +--- @class (exact) blink.cmp.CompletionDocumentationConfig +--- @field auto_show boolean Controls whether the documentation window will automatically show when selecting a completion item +--- @field auto_show_delay_ms number Delay before showing the documentation window +--- @field update_delay_ms number Delay before updating the documentation window when selecting a new item, while an existing item is still visible +--- @field treesitter_highlighting boolean Whether to use treesitter highlighting, disable if you run into performance issues +--- @field window blink.cmp.CompletionDocumentationWindowConfig + +--- @class (exact) blink.cmp.CompletionDocumentationWindowConfig +--- @field min_width number +--- @field max_width number +--- @field max_height number +--- @field desired_min_width number +--- @field desired_min_height number +--- @field border blink.cmp.WindowBorder +--- @field winblend number +--- @field winhighlight string +--- @field scrollbar boolean Note that the gutter will be disabled when border ~= 'none' +--- @field direction_priority blink.cmp.CompletionDocumentationDirectionPriorityConfig Which directions to show the window, for each of the possible menu window directions, falling back to the next direction when there's not enough space + +--- @class (exact) blink.cmp.CompletionDocumentationDirectionPriorityConfig +--- @field menu_north ("n" | "s" | "e" | "w")[] +--- @field menu_south ("n" | "s" | "e" | "w")[] + +local validate = require('blink.cmp.config.utils').validate +local documentation = { + --- @type blink.cmp.CompletionDocumentationConfig + default = { + auto_show = false, + auto_show_delay_ms = 500, + update_delay_ms = 50, + treesitter_highlighting = true, + window = { + min_width = 10, + max_width = 80, + max_height = 20, + desired_min_width = 50, + desired_min_height = 10, + border = 'padded', + winblend = 0, + winhighlight = 'Normal:BlinkCmpDoc,FloatBorder:BlinkCmpDocBorder,EndOfBuffer:BlinkCmpDoc', + scrollbar = true, + direction_priority = { + menu_north = { 'e', 'w', 'n', 's' }, + menu_south = { 'e', 'w', 's', 'n' }, + }, + }, + }, +} + +function documentation.validate(config) + validate('completion.documentation', { + auto_show = { config.auto_show, 'boolean' }, + auto_show_delay_ms = { config.auto_show_delay_ms, 'number' }, + update_delay_ms = { config.update_delay_ms, 'number' }, + treesitter_highlighting = { config.treesitter_highlighting, 'boolean' }, + window = { config.window, 'table' }, + }, config) + + validate('completion.documentation.window', { + min_width = { config.window.min_width, 'number' }, + max_width = { config.window.max_width, 'number' }, + max_height = { config.window.max_height, 'number' }, + desired_min_width = { config.window.desired_min_width, 'number' }, + desired_min_height = { config.window.desired_min_height, 'number' }, + border = { config.window.border, { 'string', 'table' } }, + winblend = { config.window.winblend, 'number' }, + winhighlight = { config.window.winhighlight, 'string' }, + scrollbar = { config.window.scrollbar, 'boolean' }, + direction_priority = { config.window.direction_priority, 'table' }, + }, config.window) + + validate('completion.documentation.window.direction_priority', { + menu_north = { + config.window.direction_priority.menu_north, + function(directions) + if type(directions) ~= 'table' or #directions == 0 then return false end + for _, direction in ipairs(directions) do + if not vim.tbl_contains({ 'n', 's', 'e', 'w' }, direction) then return false end + end + return true + end, + 'one of: "n", "s", "e", "w"', + }, + menu_south = { + config.window.direction_priority.menu_south, + function(directions) + if type(directions) ~= 'table' or #directions == 0 then return false end + for _, direction in ipairs(directions) do + if not vim.tbl_contains({ 'n', 's', 'e', 'w' }, direction) then return false end + end + return true + end, + 'one of: "n", "s", "e", "w"', + }, + }, config.window.direction_priority) +end + +return documentation diff --git a/lua/blink/cmp/config/completion/ghost_text.lua b/lua/blink/cmp/config/completion/ghost_text.lua new file mode 100644 index 0000000..47fb2cd --- /dev/null +++ b/lua/blink/cmp/config/completion/ghost_text.lua @@ -0,0 +1,19 @@ +--- Displays a preview of the selected item on the current line +--- @class (exact) blink.cmp.CompletionGhostTextConfig +--- @field enabled boolean + +local validate = require('blink.cmp.config.utils').validate +local ghost_text = { + --- @type blink.cmp.CompletionGhostTextConfig + default = { + enabled = false, + }, +} + +function ghost_text.validate(config) + validate('completion.ghost_text', { + enabled = { config.enabled, 'boolean' }, + }, config) +end + +return ghost_text diff --git a/lua/blink/cmp/config/completion/init.lua b/lua/blink/cmp/config/completion/init.lua new file mode 100644 index 0000000..24407ff --- /dev/null +++ b/lua/blink/cmp/config/completion/init.lua @@ -0,0 +1,42 @@ +--- @class (exact) blink.cmp.CompletionConfig +--- @field keyword blink.cmp.CompletionKeywordConfig +--- @field trigger blink.cmp.CompletionTriggerConfig +--- @field list blink.cmp.CompletionListConfig +--- @field accept blink.cmp.CompletionAcceptConfig +--- @field menu blink.cmp.CompletionMenuConfig +--- @field documentation blink.cmp.CompletionDocumentationConfig +--- @field ghost_text blink.cmp.CompletionGhostTextConfig + +local validate = require('blink.cmp.config.utils').validate +local completion = { + default = { + keyword = require('blink.cmp.config.completion.keyword').default, + trigger = require('blink.cmp.config.completion.trigger').default, + list = require('blink.cmp.config.completion.list').default, + accept = require('blink.cmp.config.completion.accept').default, + menu = require('blink.cmp.config.completion.menu').default, + documentation = require('blink.cmp.config.completion.documentation').default, + ghost_text = require('blink.cmp.config.completion.ghost_text').default, + }, +} + +function completion.validate(config) + validate('completion', { + keyword = { config.keyword, 'table' }, + trigger = { config.trigger, 'table' }, + list = { config.list, 'table' }, + accept = { config.accept, 'table' }, + menu = { config.menu, 'table' }, + documentation = { config.documentation, 'table' }, + ghost_text = { config.ghost_text, 'table' }, + }, config) + require('blink.cmp.config.completion.keyword').validate(config.keyword) + require('blink.cmp.config.completion.trigger').validate(config.trigger) + require('blink.cmp.config.completion.list').validate(config.list) + require('blink.cmp.config.completion.accept').validate(config.accept) + require('blink.cmp.config.completion.menu').validate(config.menu) + require('blink.cmp.config.completion.documentation').validate(config.documentation) + require('blink.cmp.config.completion.ghost_text').validate(config.ghost_text) +end + +return completion diff --git a/lua/blink/cmp/config/completion/keyword.lua b/lua/blink/cmp/config/completion/keyword.lua new file mode 100644 index 0000000..a922ac4 --- /dev/null +++ b/lua/blink/cmp/config/completion/keyword.lua @@ -0,0 +1,27 @@ +--- @class (exact) blink.cmp.CompletionKeywordConfig +--- 'prefix' will fuzzy match on the text before the cursor +--- 'full' will fuzzy match on the text before *and* after the cursor +--- example: 'foo_|_bar' will match 'foo_' for 'prefix' and 'foo__bar' for 'full' +--- @field range blink.cmp.CompletionKeywordRange +--- +--- @alias blink.cmp.CompletionKeywordRange +--- | 'prefix' Fuzzy match on the text before the cursor (example: 'foo_|bar' will match 'foo_') +--- | 'full' Fuzzy match on the text before *and* after the cursor (example: 'foo_|_bar' will match 'foo__bar') + +local validate = require('blink.cmp.config.utils').validate +local keyword = { + --- @type blink.cmp.CompletionKeywordConfig + default = { range = 'prefix' }, +} + +function keyword.validate(config) + validate('completion.keyword', { + range = { + config.range, + function(range) return vim.tbl_contains({ 'prefix', 'full' }, range) end, + 'one of: prefix, full', + }, + }, config) +end + +return keyword diff --git a/lua/blink/cmp/config/completion/list.lua b/lua/blink/cmp/config/completion/list.lua new file mode 100644 index 0000000..c0c5690 --- /dev/null +++ b/lua/blink/cmp/config/completion/list.lua @@ -0,0 +1,54 @@ +--- @class (exact) blink.cmp.CompletionListConfig +--- @field max_items number Maximum number of items to display +--- @field selection blink.cmp.CompletionListSelectionConfig +--- @field cycle blink.cmp.CompletionListCycleConfig + +--- @class (exact) blink.cmp.CompletionListSelectionConfig +--- @field preselect boolean | fun(ctx: blink.cmp.Context): boolean When `true`, will automatically select the first item in the completion list +--- @field auto_insert boolean | fun(ctx: blink.cmp.Context): boolean When `true`, inserts the completion item automatically when selecting it. You may want to bind a key to the `cancel` command (default <C-e>) when using this option, which will both undo the selection and hide the completion menu + +--- @class (exact) blink.cmp.CompletionListCycleConfig +--- @field from_bottom boolean When `true`, calling `select_next` at the *bottom* of the completion list will select the *first* completion item. +--- @field from_top boolean When `true`, calling `select_prev` at the *top* of the completion list will select the *last* completion item. + +local validate = require('blink.cmp.config.utils').validate +local list = { + --- @type blink.cmp.CompletionListConfig + default = { + max_items = 200, + selection = { + preselect = true, + auto_insert = true, + }, + cycle = { + from_bottom = true, + from_top = true, + }, + }, +} + +function list.validate(config) + if type(config.selection) == 'function' then + error( + '`completion.list.selection` has been replaced with `completion.list.selection.preselect` and `completion.list.selection.auto_insert`. See the docs for more info: https://cmp.saghen.dev/configuration/completion.html#list' + ) + end + + validate('completion.list', { + max_items = { config.max_items, 'number' }, + selection = { config.selection, 'table' }, + cycle = { config.cycle, 'table' }, + }, config) + + validate('completion.list.selection', { + preselect = { config.selection.preselect, { 'boolean', 'function' } }, + auto_insert = { config.selection.auto_insert, { 'boolean', 'function' } }, + }, config.selection) + + validate('completion.list.cycle', { + from_bottom = { config.cycle.from_bottom, 'boolean' }, + from_top = { config.cycle.from_top, 'boolean' }, + }, config.cycle) +end + +return list diff --git a/lua/blink/cmp/config/completion/menu.lua b/lua/blink/cmp/config/completion/menu.lua new file mode 100644 index 0000000..c807566 --- /dev/null +++ b/lua/blink/cmp/config/completion/menu.lua @@ -0,0 +1,223 @@ +local validate = require('blink.cmp.config.utils').validate + +--- @class (exact) blink.cmp.CompletionMenuConfig +--- @field enabled boolean +--- @field min_width number +--- @field max_height number +--- @field border blink.cmp.WindowBorder +--- @field winblend number +--- @field winhighlight string +--- @field scrolloff number Keep the cursor X lines away from the top/bottom of the window +--- @field scrollbar boolean Note that the gutter will be disabled when border ~= 'none' +--- @field direction_priority ("n" | "s")[] Which directions to show the window, falling back to the next direction when there's not enough space +--- @field order blink.cmp.CompletionMenuOrderConfig TODO: implement +--- @field auto_show boolean | fun(ctx: blink.cmp.Context, items: blink.cmp.CompletionItem[]): boolean Whether to automatically show the window when new completion items are available +--- @field cmdline_position fun(): number[] Screen coordinates (0-indexed) of the command line +--- @field draw blink.cmp.Draw Controls how the completion items are rendered on the popup window + +--- @class (exact) blink.cmp.CompletionMenuOrderConfig +--- @field n 'top_down' | 'bottom_up' +--- @field s 'top_down' | 'bottom_up' + +local window = { + --- @type blink.cmp.CompletionMenuConfig + default = { + enabled = true, + min_width = 15, + max_height = 10, + border = 'none', + winblend = 0, + winhighlight = 'Normal:BlinkCmpMenu,FloatBorder:BlinkCmpMenuBorder,CursorLine:BlinkCmpMenuSelection,Search:None', + -- keep the cursor X lines away from the top/bottom of the window + scrolloff = 2, + -- note that the gutter will be disabled when border ~= 'none' + scrollbar = true, + -- which directions to show the window, + -- falling back to the next direction when there's not enough space + direction_priority = { 's', 'n' }, + -- which direction previous/next items show up + -- TODO: implement + order = { n = 'bottom_up', s = 'top_down' }, + + -- Whether to automatically show the window when new completion items are available + auto_show = true, + + -- Screen coordinates of the command line + cmdline_position = function() + if vim.g.ui_cmdline_pos ~= nil then + local pos = vim.g.ui_cmdline_pos -- (1, 0)-indexed + return { pos[1] - 1, pos[2] } + end + local height = (vim.o.cmdheight == 0) and 1 or vim.o.cmdheight + return { vim.o.lines - height, 0 } + end, + + -- Controls how the completion items are rendered on the popup window + draw = { + -- Aligns the keyword you've typed to a component in the menu + align_to = 'label', -- or 'none' to disable + -- Left and right padding, optionally { left, right } for different padding on each side + padding = 1, + -- Gap between columns + gap = 1, + treesitter = {}, -- Use treesitter to highlight the label text of completions from these sources + -- Components to render, grouped by column + columns = { { 'kind_icon' }, { 'label', 'label_description', gap = 1 } }, + -- Definitions for possible components to render. Each component defines: + -- ellipsis: whether to add an ellipsis when truncating the text + -- width: control the min, max and fill behavior of the component + -- text function: will be called for each item + -- highlight function: will be called only when the line appears on screen + components = { + kind_icon = { + ellipsis = false, + text = function(ctx) return ctx.kind_icon .. ctx.icon_gap end, + highlight = function(ctx) + return require('blink.cmp.completion.windows.render.tailwind').get_hl(ctx) or ('BlinkCmpKind' .. ctx.kind) + end, + }, + + kind = { + ellipsis = false, + width = { fill = true }, + text = function(ctx) return ctx.kind end, + highlight = function(ctx) + return require('blink.cmp.completion.windows.render.tailwind').get_hl(ctx) or ('BlinkCmpKind' .. ctx.kind) + end, + }, + + label = { + width = { fill = true, max = 60 }, + text = function(ctx) return ctx.label .. ctx.label_detail end, + highlight = function(ctx) + -- label and label details + local label = ctx.label + local highlights = { + { 0, #label, group = ctx.deprecated and 'BlinkCmpLabelDeprecated' or 'BlinkCmpLabel' }, + } + if ctx.label_detail then + table.insert(highlights, { #label, #label + #ctx.label_detail, group = 'BlinkCmpLabelDetail' }) + end + + if vim.list_contains(ctx.self.treesitter, ctx.source_id) then + -- add treesitter highlights + vim.list_extend(highlights, require('blink.cmp.completion.windows.render.treesitter').highlight(ctx)) + end + + -- characters matched on the label by the fuzzy matcher + for _, idx in ipairs(ctx.label_matched_indices) do + table.insert(highlights, { idx, idx + 1, group = 'BlinkCmpLabelMatch' }) + end + + return highlights + end, + }, + + label_description = { + width = { max = 30 }, + text = function(ctx) return ctx.label_description end, + highlight = 'BlinkCmpLabelDescription', + }, + + source_name = { + width = { max = 30 }, + -- source_name or source_id are supported + text = function(ctx) return ctx.source_name end, + highlight = 'BlinkCmpSource', + }, + }, + }, + }, +} + +function window.validate(config) + validate('completion.menu', { + enabled = { config.enabled, 'boolean' }, + min_width = { config.min_width, 'number' }, + max_height = { config.max_height, 'number' }, + border = { config.border, { 'string', 'table' } }, + winblend = { config.winblend, 'number' }, + winhighlight = { config.winhighlight, 'string' }, + scrolloff = { config.scrolloff, 'number' }, + scrollbar = { config.scrollbar, 'boolean' }, + direction_priority = { + config.direction_priority, + function(direction_priority) + for _, direction in ipairs(direction_priority) do + if not vim.tbl_contains({ 'n', 's' }, direction) then return false end + end + return true + end, + 'one of: "n", "s"', + }, + order = { config.order, 'table' }, + auto_show = { config.auto_show, { 'boolean', 'function' } }, + cmdline_position = { config.cmdline_position, 'function' }, + draw = { config.draw, 'table' }, + }, config) + validate('completion.menu.order', { + n = { config.order.n, { 'string', 'nil' } }, + s = { config.order.s, { 'string', 'nil' } }, + }, config.order) + + validate('completion.menu.draw', { + align_to = { + config.draw.align_to, + function(align) + if align == 'none' or align == 'cursor' then return true end + for _, column in ipairs(config.draw.columns) do + for _, component in ipairs(column) do + if component == align then return true end + end + end + return false + end, + '"none" or one of the components defined in the "columns"', + }, + + padding = { + config.draw.padding, + function(padding) + if type(padding) == 'number' then return true end + if type(padding) ~= 'table' or #padding ~= 2 then return false end + if type(padding[1]) == 'number' and type(padding[2]) == 'number' then return true end + return false + end, + 'a number or a tuple of 2 numbers (i.e. [1, 2])', + }, + gap = { config.draw.gap, 'number' }, + + treesitter = { config.draw.treesitter, 'table' }, + + columns = { + config.draw.columns, + function(columns) + local available_components = vim.tbl_keys(config.draw.components) + + if type(columns) ~= 'table' or #columns == 0 then return false end + for _, column in ipairs(columns) do + if #column == 0 then return false end + for _, component in ipairs(column) do + if not vim.tbl_contains(available_components, component) then return false end + end + if column.gap ~= nil and type(column.gap) ~= 'number' then return false end + end + return true + end, + 'a table of tables, where each table contains a list of components and an optional gap. List of available components: ' + .. table.concat(vim.tbl_keys(config.draw.components), ', '), + }, + components = { config.draw.components, 'table' }, + }, config.draw) + + for component, definition in pairs(config.draw.components) do + validate('completion.menu.draw.components.' .. component, { + ellipsis = { definition.ellipsis, 'boolean', true }, + width = { definition.width, 'table', true }, + text = { definition.text, 'function' }, + highlight = { definition.highlight, { 'string', 'function' }, true }, + }, config.draw.components[component]) + end +end + +return window diff --git a/lua/blink/cmp/config/completion/trigger.lua b/lua/blink/cmp/config/completion/trigger.lua new file mode 100644 index 0000000..94d0af8 --- /dev/null +++ b/lua/blink/cmp/config/completion/trigger.lua @@ -0,0 +1,42 @@ +--- @class (exact) blink.cmp.CompletionTriggerConfig +--- @field prefetch_on_insert boolean When true, will prefetch the completion items when entering insert mode. WARN: buggy, not recommended unless you'd like to help develop prefetching +--- @field show_in_snippet boolean When false, will not show the completion window when in a snippet +--- @field show_on_keyword boolean When true, will show the completion window after typing any of alphanumerics, `-` or `_` +--- @field show_on_trigger_character boolean When true, will show the completion window after typing a trigger character +--- @field show_on_blocked_trigger_characters string[] | (fun(): string[]) LSPs can indicate when to show the completion window via trigger characters. However, some LSPs (i.e. tsserver) return characters that would essentially always show the window. We block these by default. +--- @field show_on_accept_on_trigger_character boolean When both this and show_on_trigger_character are true, will show the completion window when the cursor comes after a trigger character after accepting an item +--- @field show_on_insert_on_trigger_character boolean When both this and show_on_trigger_character are true, will show the completion window when the cursor comes after a trigger character when entering insert mode +--- @field show_on_x_blocked_trigger_characters string[] | (fun(): string[]) List of trigger characters (on top of `show_on_blocked_trigger_characters`) that won't trigger the completion window when the cursor comes after a trigger character when entering insert mode/accepting an item + +local validate = require('blink.cmp.config.utils').validate +local trigger = { + --- @type blink.cmp.CompletionTriggerConfig + default = { + prefetch_on_insert = false, + show_in_snippet = true, + show_on_keyword = true, + show_on_trigger_character = true, + show_on_blocked_trigger_characters = function() + if vim.api.nvim_get_mode().mode == 'c' then return {} end + return { ' ', '\n', '\t' } + end, + show_on_accept_on_trigger_character = true, + show_on_insert_on_trigger_character = true, + show_on_x_blocked_trigger_characters = { "'", '"', '(', '{', '[' }, + }, +} + +function trigger.validate(config) + validate('completion.trigger', { + prefetch_on_insert = { config.prefetch_on_insert, 'boolean' }, + show_in_snippet = { config.show_in_snippet, 'boolean' }, + show_on_keyword = { config.show_on_keyword, 'boolean' }, + show_on_trigger_character = { config.show_on_trigger_character, 'boolean' }, + show_on_blocked_trigger_characters = { config.show_on_blocked_trigger_characters, { 'function', 'table' } }, + show_on_accept_on_trigger_character = { config.show_on_accept_on_trigger_character, 'boolean' }, + show_on_insert_on_trigger_character = { config.show_on_insert_on_trigger_character, 'boolean' }, + show_on_x_blocked_trigger_characters = { config.show_on_x_blocked_trigger_characters, { 'function', 'table' } }, + }, config) +end + +return trigger |
