Skip to content

Commit

Permalink
feat: show_and_select keymap command
Browse files Browse the repository at this point in the history
Closes #1004
  • Loading branch information
Saghen committed Jan 16, 2025
1 parent 93541e4 commit 373535e
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 6 deletions.
6 changes: 6 additions & 0 deletions docs/configuration/completion.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ completion.list.selection = { preselect = true, auto_insert = true }
```
Selects the first item automatically, and inserts a preview of the item on selection. The `cancel` keymap (default `<C-e>`) will close the menu and undo the preview.

You may use the `show_and_select` keymap to show the completion menu and select the first item, with `auto_insert`. The default keymap (`<C-space>`) uses the `show` command, which will have the first item selected, but will not `auto_insert`.

<video src="https://github.com/user-attachments/assets/ef295526-8332-4ad0-9a2a-e2f6484081b2" muted autoplay loop />

== Preselect
Expand All @@ -82,6 +84,8 @@ completion.list.selection = { preselect = false, auto_insert = false }

No item will be selected by default. You may use the `select_and_accept` keymap command to select the first item and accept it when there's no selection. The `accept` keymap command, on the other hand, will only trigger if an item is selected.

You may use the `show_and_select` keymap to show the completion menu and select the first item. The default keymap (`<C-space>`) uses the `show` command, which will not select the first item.

<video src="https://github.com/user-attachments/assets/09cd9b4b-18b3-456b-bb0a-074ae54e9d77" muted autoplay loop />
== Manual, Auto Insert
```lua
Expand All @@ -90,6 +94,8 @@ completion.list.selection = { preselect = false, auto_insert = true }

Selecting an item will insert a "preview" of the item automatically. You may use the `select_and_accept` keymap command to select the first item and accept it when there's no selection. The `accept` keymap command will only trigger if an item is selected. The `cancel` keymap (default `<C-e>`) will close the menu and undo the preview.

You may use the `show_and_select` keymap to show the completion menu and select the first item, with `auto_insert`. The default keymap (`<C-space>`) uses the `show` command, which will not select the first item.

<video src="https://github.com/user-attachments/assets/4658b61d-1b95-404a-b6b5-3a4afbfb8112" muted autoplay loop />
:::

Expand Down
6 changes: 4 additions & 2 deletions lua/blink/cmp/completion/list.lua
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,13 @@ function list.show(context, items_by_source)
local previous_item_idx = list.get_item_idx_in_list(previous_selected_item)
if list.is_explicitly_selected and previous_item_idx ~= nil and previous_item_idx <= 10 then
list.select(previous_item_idx, { auto_insert = false, undo_preview = false })

-- respect the context's initial selected item idx
elseif context.initial_selected_item_idx ~= nil then
list.select(context.initial_selected_item_idx, { undo_preview = false, is_explicit_selection = true })
-- otherwise, use the default selection
else
list.select(
list.get_selection_mode(list.context).preselect and 1 or nil,
list.get_selection_mode(context).preselect and 1 or nil,
{ auto_insert = false, undo_preview = false, is_explicit_selection = false }
)
end
Expand Down
3 changes: 3 additions & 0 deletions lua/blink/cmp/completion/trigger/context.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
--- @field bounds blink.cmp.ContextBounds
--- @field trigger blink.cmp.ContextTrigger
--- @field providers string[]
--- @field initial_selected_item_idx? number
---
--- @field new fun(opts: blink.cmp.ContextOpts): blink.cmp.Context
--- @field get_keyword fun(): string
Expand All @@ -39,6 +40,7 @@
--- @field initial_trigger_character? string
--- @field trigger_kind blink.cmp.CompletionTriggerKind
--- @field trigger_character? string
--- @field initial_selected_item_idx? number

--- @type blink.cmp.Context
--- @diagnostic disable-next-line: missing-fields
Expand All @@ -62,6 +64,7 @@ function context.new(opts)
character = opts.trigger_character,
},
providers = opts.providers,
initial_selected_item_idx = opts.initial_selected_item_idx,
}, { __index = context })
end

Expand Down
11 changes: 10 additions & 1 deletion lua/blink/cmp/completion/trigger/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,19 @@
--- @field is_trigger_character fun(char: string, is_show_on_x?: boolean): boolean
--- @field suppress_events_for_callback fun(cb: fun())
--- @field show_if_on_trigger_character fun(opts?: { is_accept?: boolean })
--- @field show fun(opts?: { trigger_kind: blink.cmp.CompletionTriggerKind, trigger_character?: string, force?: boolean, send_upstream?: boolean, providers?: string[] }): blink.cmp.Context?
--- @field show fun(opts?: blink.cmp.CompletionTriggerShowOptions): blink.cmp.Context?
--- @field hide fun()
--- @field within_query_bounds fun(cursor: number[]): boolean
--- @field get_bounds fun(regex: vim.regex, line: string, cursor: number[]): blink.cmp.ContextBounds

--- @class blink.cmp.CompletionTriggerShowOptions
--- @field trigger_kind blink.cmp.CompletionTriggerKind
--- @field trigger_character? string
--- @field force? boolean
--- @field send_upstream? boolean
--- @field providers? string[]
--- @field initial_selected_item_idx? number

local config = require('blink.cmp.config').completion.trigger
local context = require('blink.cmp.completion.trigger.context')
local utils = require('blink.cmp.completion.trigger.utils')
Expand Down Expand Up @@ -226,6 +234,7 @@ function trigger.show(opts)
initial_trigger_character = trigger.context and trigger.context.trigger.initial_character or opts.trigger_character,
trigger_kind = opts.trigger_kind,
trigger_character = opts.trigger_character,
initial_selected_item_idx = opts.initial_selected_item_idx,
})

if opts.send_upstream ~= false then trigger.show_emitter:emit({ context = trigger.context }) end
Expand Down
2 changes: 2 additions & 0 deletions lua/blink/cmp/config/keymap.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
--- @alias blink.cmp.KeymapCommand
--- | 'fallback' Fallback to the built-in behavior
--- | 'show' Show the completion window
--- | 'show_and_select' Show the completion window and select the first item
--- | 'hide' Hide the completion window
--- | 'cancel' Cancel the current completion, undoing the preview from auto_insert
--- | 'accept' Accept the current completion item
Expand Down Expand Up @@ -125,6 +126,7 @@ function keymap.validate(config)
local commands = {
'fallback',
'show',
'show_and_select',
'hide',
'cancel',
'accept',
Expand Down
15 changes: 12 additions & 3 deletions lua/blink/cmp/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function cmp.is_ghost_text_visible() return require('blink.cmp.completion.window
function cmp.is_documentation_visible() return require('blink.cmp.completion.windows.documentation').win:is_open() end

--- Show the completion window
--- @params opts? { providers?: string[], callback?: fun() }
--- @param opts? { providers?: string[], initial_selected_item_idx?: number, callback?: fun() }
function cmp.show(opts)
opts = opts or {}

Expand Down Expand Up @@ -79,13 +79,22 @@ function cmp.show(opts)
force = true,
providers = opts and opts.providers,
trigger_kind = 'manual',
initial_selected_item_idx = opts.initial_selected_item_idx,
})
end)
return true
end

-- Show the completion window and select the first item
--- @params opts? { providers?: string[], callback?: fun() }
function cmp.show_and_select(opts)
opts = opts or {}
opts.initial_selected_item_idx = 1
return cmp.show(opts)
end

--- Hide the completion window
--- @params opts? { callback?: fun() }
--- @param opts? { callback?: fun() }
function cmp.hide(opts)
if not cmp.is_visible() then return end

Expand All @@ -97,7 +106,7 @@ function cmp.hide(opts)
end

--- Cancel the current completion, undoing the preview from auto_insert
--- @params opts? { callback?: fun() }
--- @param opts? { callback?: fun() }
function cmp.cancel(opts)
if not cmp.is_visible() then return end
vim.schedule(function()
Expand Down

0 comments on commit 373535e

Please sign in to comment.