Skip to content

Commit

Permalink
feat: signature commands and more events
Browse files Browse the repository at this point in the history
Closes #816
Closes #89
  • Loading branch information
Saghen committed Jan 22, 2025
1 parent 9dc7207 commit 6da1023
Show file tree
Hide file tree
Showing 17 changed files with 116 additions and 61 deletions.
8 changes: 8 additions & 0 deletions docs/configuration/keymap.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ keymap = {
- Optionally use `function(cmp) cmp.scroll_documentation_up(4) end` to scroll by a specific number of lines
- `scroll_documentation_down`: Scrolls the documentation down by 4 lines
- Optionally use `function(cmp) cmp.scroll_documentation_down(4) end` to scroll by a specific number of lines
- `show_signature`: Shows the signature help window
- `hide_signature`: Hides the signature help window
- `snippet_forward`: Jumps to the next snippet placeholder
- `snippet_backward`: Jumps to the previous snippet placeholder
- `fallback`: Runs the next non-blink keymap, or runs the built-in neovim binding
Expand Down Expand Up @@ -96,6 +98,8 @@ Set the preset to `none` to disable the presets

['<Tab>'] = { 'snippet_forward', 'fallback' },
['<S-Tab>'] = { 'snippet_backward', 'fallback' },

['<C-k>'] = { 'show_signature', 'hide_signature' },
```

### `super-tab`
Expand Down Expand Up @@ -123,6 +127,8 @@ You may want to set `completion.trigger.show_in_snippet = false` or use `complet

['<C-b>'] = { 'scroll_documentation_up', 'fallback' },
['<C-f>'] = { 'scroll_documentation_down', 'fallback' },

['<C-k>'] = { 'show_signature', 'hide_signature' },
```

### `enter`
Expand All @@ -144,4 +150,6 @@ You may want to set `completion.list.selection.preselect = false`. See more info

['<C-b>'] = { 'scroll_documentation_up', 'fallback' },
['<C-f>'] = { 'scroll_documentation_down', 'fallback' },

['<C-k>'] = { 'show_signature', 'hide_signature' },
```
10 changes: 9 additions & 1 deletion docs/configuration/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,17 @@ completion.ghost_text = {
signature = {
enabled = false,
trigger = {
-- Show the signature help automatically
enabled = true,
-- Show the signature help window after typing any of alphanumerics, `-` or `_`
show_on_keyword = false,
blocked_trigger_characters = {},
blocked_retrigger_characters = {},
-- When true, will show the signature help window when the cursor comes after a trigger character when entering insert mode
-- Show the signature help window after typing a trigger character
show_on_trigger_character = true,
-- Show the signature help window when entering insert mode
show_on_insert = false,
-- Show the signature help window when the cursor comes after a trigger character when entering insert mode
show_on_insert_on_trigger_character = true,
},
window = {
Expand Down
1 change: 1 addition & 0 deletions docs/configuration/signature.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ signature = { enabled = true }

<img src="https://github.com/user-attachments/assets/9ab576c8-2a04-465f-88c0-9c130fef146c" />

You may want to set `signature.window.show_documentation = false` to only show the signature, and not the documentation.
2 changes: 1 addition & 1 deletion lua/blink/cmp/completion/brackets/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ return {
by_filetype = {
-- ignore `use` imports
rust = function(ctx) return ctx.line:find('^%s*use%s') == nil end,
-- ignore import statements
-- ignore `from` and `import` statements
python = function(ctx) return ctx.line:find('^%s*import%s') == nil and ctx.line:find('^%s*from%s') == nil end,
},
},
Expand Down
2 changes: 1 addition & 1 deletion lua/blink/cmp/completion/trigger/context.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-- TODO: remove the end_col field from ContextBounds
-- TODO: move the get_line, get_cursor, etc.. to a separate lib

--- @class blink.cmp.ContextBounds
--- @field line string
Expand Down
17 changes: 4 additions & 13 deletions lua/blink/cmp/completion/trigger/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
--- @field hide_emitter blink.cmp.EventEmitter<{}>
---
--- @field activate fun()
--- @field is_keyword_character fun(char: string): boolean
--- @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 })
Expand All @@ -31,7 +30,8 @@

local config = require('blink.cmp.config').completion.trigger
local context = require('blink.cmp.completion.trigger.context')
local utils = require('blink.cmp.completion.trigger.utils')
local utils = require('blink.cmp.lib.utils')
local fuzzy = require('blink.cmp.fuzzy')

--- @type blink.cmp.CompletionTrigger
--- @diagnostic disable-next-line: missing-fields
Expand Down Expand Up @@ -61,7 +61,7 @@ function trigger.activate()
trigger.show({ trigger_kind = 'trigger_character', trigger_character = char })

-- character is part of a keyword
elseif trigger.is_keyword_character(char) and (config.show_on_keyword or trigger.context ~= nil) then
elseif fuzzy.is_keyword_character(char) and (config.show_on_keyword or trigger.context ~= nil) then
trigger.show({ trigger_kind = 'keyword' })

-- nothing matches so hide
Expand All @@ -75,7 +75,7 @@ function trigger.activate()
local cursor_col = cursor[2]

local char_under_cursor = utils.get_char_at_cursor()
local is_keyword = trigger.is_keyword_character(char_under_cursor)
local is_keyword = fuzzy.is_keyword_character(char_under_cursor)

-- we were told to ignore the cursor moved event, so we update the context
-- but don't send an on_show event upstream
Expand Down Expand Up @@ -141,15 +141,6 @@ function trigger.activate()
})
end

function trigger.is_keyword_character(char)
-- special case for hyphen, since we don't consider a lone hyphen to be a keyword
if char == '-' then return true end

local success, keyword_start_col, keyword_end_col =
pcall(require('blink.cmp.fuzzy').get_keyword_range, char, #char, 'prefix')
return success and keyword_start_col ~= keyword_end_col
end

function trigger.is_trigger_character(char, is_show_on_x)
local sources = require('blink.cmp.sources.lib')
local is_trigger = vim.tbl_contains(sources.get_trigger_characters(context.get_mode()), char)
Expand Down
30 changes: 0 additions & 30 deletions lua/blink/cmp/completion/trigger/utils.lua

This file was deleted.

2 changes: 2 additions & 0 deletions lua/blink/cmp/config/keymap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ function keymap.validate(config)
'hide_documentation',
'scroll_documentation_up',
'scroll_documentation_down',
'show_signature',
'hide_signature',
'snippet_forward',
'snippet_backward',
}
Expand Down
14 changes: 12 additions & 2 deletions lua/blink/cmp/config/signature.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
--- @field window blink.cmp.SignatureWindowConfig

--- @class (exact) blink.cmp.SignatureTriggerConfig
--- @field enabled boolean Show the signature help automatically
--- @field show_on_keyword boolean Show the signature help window after typing any of alphanumerics, `-` or `_`
--- @field blocked_trigger_characters string[]
--- @field blocked_retrigger_characters string[]
--- @field show_on_insert_on_trigger_character boolean When true, will show the signature help window when the cursor comes after a trigger character when entering insert mode
--- @field show_on_trigger_character boolean Show the signature help window after typing a trigger character
--- @field show_on_insert boolean Show the signature help window when entering insert mode
--- @field show_on_insert_on_trigger_character boolean Show the signature help window when the cursor comes after a trigger character when entering insert mode

--- @class (exact) blink.cmp.SignatureWindowConfig
--- @field min_width number
Expand All @@ -27,8 +31,11 @@ local signature = {
enabled = false,
trigger = {
enabled = true,
show_on_keyword = false,
blocked_trigger_characters = {},
blocked_retrigger_characters = {},
show_on_trigger_character = true,
show_on_insert = false,
show_on_insert_on_trigger_character = true,
},
window = {
Expand All @@ -41,7 +48,7 @@ local signature = {
scrollbar = false,
direction_priority = { 'n', 's' },
treesitter_highlighting = true,
show_documentation = true,
show_documentation = false,
},
},
}
Expand All @@ -54,8 +61,11 @@ function signature.validate(config)
}, config)
validate('signature.trigger', {
enabled = { config.trigger.enabled, 'boolean' },
show_on_keyword = { config.trigger.show_on_keyword, 'boolean' },
blocked_trigger_characters = { config.trigger.blocked_trigger_characters, 'table' },
blocked_retrigger_characters = { config.trigger.blocked_retrigger_characters, 'table' },
show_on_trigger_character = { config.trigger.show_on_trigger_character, 'boolean' },
show_on_insert = { config.trigger.show_on_insert, 'boolean' },
show_on_insert_on_trigger_character = { config.trigger.show_on_insert_on_trigger_character, 'boolean' },
}, config.trigger)
validate('signature.window', {
Expand Down
8 changes: 8 additions & 0 deletions lua/blink/cmp/fuzzy/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ function fuzzy.get_keyword_range(line, col, range)
return require('blink.cmp.fuzzy.rust').get_keyword_range(line, col, range == 'full')
end

function fuzzy.is_keyword_character(char)
-- special case for hyphen, since we don't consider a lone hyphen to be a keyword
if char == '-' then return true end

local keyword_start_col, keyword_end_col = fuzzy.get_keyword_range(char, #char, 'prefix')
return keyword_start_col ~= keyword_end_col
end

--- @param item blink.cmp.CompletionItem
--- @param line string
--- @param col number
Expand Down
18 changes: 18 additions & 0 deletions lua/blink/cmp/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,24 @@ function cmp.scroll_documentation_down(count)
return true
end

--- Check if the signature help window is visible
--- @return boolean
function cmp.is_signature_visible() return require('blink.cmp.signature.window').win:is_open() end

--- Show the signature help window
function cmp.show_signature()
if cmp.is_signature_visible() then return end
require('blink.cmp.signature.trigger').show()
return true
end

--- Hide the signature help window
function cmp.hide_signature()
if not cmp.is_signature_visible() then return end
require('blink.cmp.signature.trigger').hide()
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
Expand Down
6 changes: 6 additions & 0 deletions lua/blink/cmp/keymap/presets.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ local presets = {

['<Tab>'] = { 'snippet_forward', 'fallback' },
['<S-Tab>'] = { 'snippet_backward', 'fallback' },

['<C-k>'] = { 'show_signature', 'hide_signature' },
},

['super-tab'] = {
Expand All @@ -42,6 +44,8 @@ local presets = {

['<C-b>'] = { 'scroll_documentation_up', 'fallback' },
['<C-f>'] = { 'scroll_documentation_down', 'fallback' },

['<C-k>'] = { 'show_signature', 'hide_signature' },
},

enter = {
Expand All @@ -59,6 +63,8 @@ local presets = {

['<C-b>'] = { 'scroll_documentation_up', 'fallback' },
['<C-f>'] = { 'scroll_documentation_down', 'fallback' },

['<C-k>'] = { 'show_signature', 'hide_signature' },
},
}

Expand Down
28 changes: 28 additions & 0 deletions lua/blink/cmp/lib/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,32 @@ function utils.slice(arr, start, finish)
return sliced
end

--- Gets the full Unicode character at cursor position
--- @return string
function utils.get_char_at_cursor()
local context = require('blink.cmp.completion.trigger.context')

local line = context.get_line()
if line == '' then return '' end
local cursor_col = context.get_cursor()[2]

-- Find the start of the UTF-8 character
local start_col = cursor_col
while start_col > 1 do
local char = string.byte(line:sub(start_col, start_col))
if char < 0x80 or char > 0xBF then break end
start_col = start_col - 1
end

-- Find the end of the UTF-8 character
local end_col = cursor_col
while end_col < #line do
local char = string.byte(line:sub(end_col + 1, end_col + 1))
if char < 0x80 or char > 0xBF then break end
end_col = end_col + 1
end

return line:sub(start_col, end_col)
end

return utils
6 changes: 4 additions & 2 deletions lua/blink/cmp/signature/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ local signature = {}
function signature.setup()
local trigger = require('blink.cmp.signature.trigger')
trigger.activate()
local window = require('blink.cmp.signature.window')

local sources = require('blink.cmp.sources.lib')
local window = require('blink.cmp.signature.window')

trigger.show_emitter:on(function(event)
local context = event.context
sources.cancel_signature_help()
sources.get_signature_help(context, function(signature_help)
sources.get_signature_help(context):map(function(signature_helps)
-- TODO: pick intelligently
local signature_help = signature_helps[1]
if signature_help ~= nil and trigger.context ~= nil and trigger.context.id == context.id then
trigger.set_active_signature_help(signature_help)
window.open_with_signature_help(context, signature_help)
Expand Down
15 changes: 9 additions & 6 deletions lua/blink/cmp/signature/trigger.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
--- @field set_active_signature_help fun(signature_help: lsp.SignatureHelp)

local config = require('blink.cmp.config').signature.trigger
local utils = require('blink.cmp.lib.utils')
local fuzzy = require('blink.cmp.fuzzy')

--- @type blink.cmp.SignatureTrigger
--- @diagnostic disable-next-line: missing-fields
Expand All @@ -46,37 +48,38 @@ function trigger.activate()
})
trigger.buffer_events:listen({
on_char_added = function()
local cursor_col = vim.api.nvim_win_get_cursor(0)[2]
local char_under_cursor = vim.api.nvim_get_current_line():sub(cursor_col, cursor_col)
local char_under_cursor = utils.get_char_at_cursor()

-- ignore if disabled
if not require('blink.cmp.config').enabled() then
return trigger.hide()
elseif config.show_on_keyword and fuzzy.is_keyword_character(char_under_cursor) then
return trigger.show({ trigger_character = char_under_cursor })
-- character forces a trigger according to the sources, refresh the existing context if it exists
elseif trigger.is_trigger_character(char_under_cursor) then
elseif config.show_on_trigger_character and trigger.is_trigger_character(char_under_cursor) then
return trigger.show({ trigger_character = char_under_cursor })
-- character forces a re-trigger according to the sources, show if we have a context
elseif trigger.is_trigger_character(char_under_cursor, true) and trigger.context ~= nil then
return trigger.show()
end
end,
on_cursor_moved = function(event)
local cursor_col = vim.api.nvim_win_get_cursor(0)[2]
local char_under_cursor = vim.api.nvim_get_current_line():sub(cursor_col, cursor_col)
local char_under_cursor = utils.get_char_at_cursor()
local is_on_trigger = trigger.is_trigger_character(char_under_cursor)

if config.show_on_insert_on_trigger_character and is_on_trigger and event == 'InsertEnter' then
trigger.show({ trigger_character = char_under_cursor })
elseif event == 'CursorMoved' and trigger.context ~= nil then
trigger.show()
elseif event == 'InsertEnter' and config.show_on_insert then
trigger.show()
end
end,
on_insert_leave = function() trigger.hide() end,
})
end

function trigger.is_trigger_character(char, is_retrigger)
-- TODO: should the get_mode() be moved to sources or somewhere else?
local mode = require('blink.cmp.completion.trigger.context').get_mode()

local res = require('blink.cmp.sources.lib').get_signature_help_trigger_characters(mode)
Expand Down
Loading

0 comments on commit 6da1023

Please sign in to comment.