Skip to content

Commit fbfdf29

Browse files
committed
feat: signature help and misc
1 parent 9466198 commit fbfdf29

18 files changed

+599
-105
lines changed

README.md

+35-15
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- Native `vim.snippet` support (including `friendly-snippets`)
1212
- External sources support (currently incompatible with `nvim-cmp` sources)
1313
- Auto-bracket support based on semantic tokens (experimental, opt-in)
14+
- Signature help (experimental, opt-in)
1415
- [Comparison with nvim-cmp](#compared-to-nvim-cmp)
1516

1617
## Installation
@@ -42,6 +43,9 @@
4243

4344
-- experimental auto-brackets support
4445
-- accept = { auto_brackets = { enabled = true } }
46+
47+
-- experimental signature help support
48+
-- trigger = { signature_help = { enabled = true } }
4549
}
4650
}
4751
```
@@ -99,16 +103,26 @@ For LazyVim/distro users, you can disable nvim-cmp via:
99103
},
100104

101105
trigger = {
102-
-- regex used to get the text when fuzzy matching
103-
-- changing this may break some sources, so please report if you run into issues
104-
-- todo: shouldnt this also affect the accept command? should this also be per language?
105-
context_regex = '[%w_\\-]',
106-
-- LSPs can indicate when to show the completion window via trigger characters
107-
-- however, some LSPs (*cough* tsserver *cough*) return characters that would essentially
108-
-- always show the window. We block these by default
109-
blocked_trigger_characters = { ' ', '\n', '\t' },
110-
-- when true, will show the completion window when the cursor comes after a trigger character when entering insert mode
111-
show_on_insert_on_trigger_character = true,
106+
completion = {
107+
-- regex used to get the text when fuzzy matching
108+
-- changing this may break some sources, so please report if you run into issues
109+
-- todo: shouldnt this also affect the accept command? should this also be per language?
110+
context_regex = '[%w_\\-]',
111+
-- LSPs can indicate when to show the completion window via trigger characters
112+
-- however, some LSPs (*cough* tsserver *cough*) return characters that would essentially
113+
-- always show the window. We block these by default
114+
blocked_trigger_characters = { ' ', '\n', '\t' },
115+
-- when true, will show the completion window when the cursor comes after a trigger character when entering insert mode
116+
show_on_insert_on_trigger_character = true,
117+
},
118+
119+
signature_help = {
120+
enabled = false,
121+
blocked_trigger_characters = {},
122+
blocked_retrigger_characters = {},
123+
-- when true, will show the signature help window when the cursor comes after a trigger character when entering insert mode
124+
show_on_insert_on_trigger_character = true,
125+
},
112126
},
113127

114128
fuzzy = {
@@ -140,17 +154,16 @@ For LazyVim/distro users, you can disable nvim-cmp via:
140154
min_width = 30,
141155
max_width = 60,
142156
max_height = 10,
143-
order = 'top_down',
157+
border = 'none',
144158
-- which directions to show the window,
145159
-- falling back to the next direction when there's not enough space
146-
direction_priority = { 'n', 's' },
147-
-- todo: implement
148-
preselect = true,
160+
direction_priority = { 's', 'n' },
149161
},
150162
documentation = {
151163
min_width = 10,
152164
max_width = 60,
153165
max_height = 20,
166+
border = 'padded',
154167
-- which directions to show the documentation window,
155168
-- for each of the possible autocomplete window directions,
156169
-- falling back to the next direction when there's not enough space
@@ -159,9 +172,15 @@ For LazyVim/distro users, you can disable nvim-cmp via:
159172
autocomplete_south = { 'e', 'w', 's', 'n' },
160173
},
161174
auto_show = true,
162-
auto_show_delay_ms = 0,
175+
auto_show_delay_ms = 500,
163176
update_delay_ms = 100,
164177
},
178+
signature_help = {
179+
min_width = 1,
180+
max_width = 100,
181+
max_height = 10,
182+
border = 'padded',
183+
},
165184
},
166185

167186
highlight = {
@@ -247,6 +266,7 @@ The plugin use a 4 stage pipeline: trigger -> sources -> fuzzy -> render
247266
- Less customizable across the board wrt trigger, sources, sorting, filtering, and rendering
248267
- Significantly less testing and documentation
249268
- Ghost text
269+
- Matched character highlighting
250270

251271
### Missing features, not planned
252272

lua/blink/cmp/accept/brackets.lua

+1-2
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,8 @@ function brackets.add_brackets_via_semantic_token(filetype, item, callback)
118118
-- cancel if it's been too long, or if the cursor moved
119119
local ms_since_call = (vim.uv.hrtime() - start_time) / 1000000
120120
local cursor_after_call = vim.api.nvim_win_get_cursor(0)
121-
vim.print('semanticTokens: ' .. ms_since_call .. 'ms')
122121
if
123-
ms_since_call > 100
122+
ms_since_call > config.semantic_token_resolution.timeout_ms
124123
or cursor_before_call[1] ~= cursor_after_call[1]
125124
or cursor_before_call[2] ~= cursor_after_call[2]
126125
then

lua/blink/cmp/accept/init.lua

+7-5
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,14 @@ local function accept(item)
4444

4545
-- Check semantic tokens for brackets, if needed, and apply additional text edits
4646
if brackets_status == 'check_semantic_token' then
47-
brackets_lib.add_brackets_via_semantic_token(
48-
vim.bo.filetype,
49-
item,
50-
function() text_edits_lib.apply_additional_text_edits(item) end
51-
)
47+
-- todo: since we apply the additional text edits after, auto imported functions will not
48+
-- get auto brackets. If we apply them before, we have to modify the textEdit to compensate
49+
brackets_lib.add_brackets_via_semantic_token(vim.bo.filetype, item, function()
50+
require('blink.cmp.trigger.signature').show_if_on_trigger_character()
51+
text_edits_lib.apply_additional_text_edits(item)
52+
end)
5253
else
54+
require('blink.cmp.trigger.signature').show_if_on_trigger_character()
5355
text_edits_lib.apply_additional_text_edits(item)
5456
end
5557

lua/blink/cmp/config.lua

+57-13
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,29 @@
2020
--- @field force_allow_filetypes string[] Overrides the default blocked filetypes
2121
--- @field blocked_filetypes string[]
2222
--- @field kind_resolution blink.cmp.AutoBracketResolutionConfig Synchronously use the kind of the item to determine if brackets should be added
23-
--- @field semantic_token_resolution blink.cmp.AutoBracketResolutionConfig Asynchronously use semantic token to determine if brackets should be added
23+
--- @field semantic_token_resolution blink.cmp.AutoBracketSemanticTokenResolutionConfig Asynchronously use semantic token to determine if brackets should be added
2424

2525
--- @class blink.cmp.AutoBracketResolutionConfig
2626
--- @field enabled boolean
2727
--- @field blocked_filetypes string[]
28+
---
29+
--- @class blink.cmp.AutoBracketSemanticTokenResolutionConfig : blink.cmp.AutoBracketResolutionConfig
30+
--- @field timeout_ms number How long to wait for semantic tokens to return before assuming no brackets should be added
2831

29-
--- @class blink.cmp.TriggerConfig
32+
--- @class blink.cmp.CompletionTriggerConfig
3033
--- @field context_regex string
3134
--- @field blocked_trigger_characters string[]
3235
--- @field show_on_insert_on_trigger_character boolean When true, will show the completion window when the cursor comes after a trigger character when entering insert mode
36+
---
37+
--- @class blink.cmp.SignatureHelpTriggerConfig
38+
--- @field enabled boolean
39+
--- @field blocked_trigger_characters string[]
40+
--- @field blocked_retrigger_characters string[]
41+
--- @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
42+
---
43+
--- @class blink.cmp.TriggerConfig
44+
--- @field completion blink.cmp.CompletionTriggerConfig
45+
--- @field signature_help blink.cmp.SignatureHelpTriggerConfig
3346

3447
--- @class blink.cmp.SourceConfig
3548
--- @field providers blink.cmp.SourceProviderConfig[][]
@@ -55,6 +68,7 @@
5568
--- @class blink.cmp.WindowConfig
5669
--- @field autocomplete blink.cmp.AutocompleteConfig
5770
--- @field documentation blink.cmp.DocumentationConfig
71+
--- @field signature_help blink.cmp.SignatureHelpConfig
5872

5973
--- @class blink.cmp.HighlightConfig
6074
--- @field ns number
@@ -64,6 +78,7 @@
6478
--- @field min_width number
6579
--- @field max_width number
6680
--- @field max_height number
81+
--- @field border blink.cmp.WindowBorder
6782
--- @field order "top_down" | "bottom_up"
6883
--- @field direction_priority ("n" | "s")[]
6984
--- @field preselect boolean
@@ -72,15 +87,24 @@
7287
--- @field autocomplete_north ("n" | "s" | "e" | "w")[]
7388
--- @field autocomplete_south ("n" | "s" | "e" | "w")[]
7489
---
90+
--- @alias blink.cmp.WindowBorder 'single' | 'double' | 'rounded' | 'solid' | 'shadow' | 'padded' | 'none'
91+
---
7592
--- @class blink.cmp.DocumentationConfig
7693
--- @field min_width number
7794
--- @field max_width number
7895
--- @field max_height number
96+
--- @field border blink.cmp.WindowBorder
7997
--- @field direction_priority blink.cmp.DocumentationDirectionPriorityConfig
8098
--- @field auto_show boolean
8199
--- @field auto_show_delay_ms number Delay before showing the documentation window
82100
--- @field update_delay_ms number Delay before updating the documentation window
83101

102+
--- @class blink.cmp.SignatureHelpConfig
103+
--- @field min_width number
104+
--- @field max_width number
105+
--- @field max_height number
106+
--- @field border blink.cmp.WindowBorder
107+
84108
--- @class blink.cmp.Config
85109
--- @field keymap blink.cmp.KeymapConfig
86110
--- @field accept blink.cmp.AcceptConfig
@@ -126,21 +150,32 @@ local config = {
126150
semantic_token_resolution = {
127151
enabled = true,
128152
blocked_filetypes = {},
153+
timeout_ms = 400,
129154
},
130155
},
131156
},
132157

133158
trigger = {
134-
-- regex used to get the text when fuzzy matching
135-
-- changing this may break some sources, so please report if you run into issues
136-
-- todo: shouldnt this also affect the accept command? should this also be per language?
137-
context_regex = '[%w_\\-]',
138-
-- LSPs can indicate when to show the completion window via trigger characters
139-
-- however, some LSPs (*cough* tsserver *cough*) return characters that would essentially
140-
-- always show the window. We block these by default
141-
blocked_trigger_characters = { ' ', '\n', '\t' },
142-
-- when true, will show the completion window when the cursor comes after a trigger character when entering insert mode
143-
show_on_insert_on_trigger_character = true,
159+
completion = {
160+
-- regex used to get the text when fuzzy matching
161+
-- changing this may break some sources, so please report if you run into issues
162+
-- todo: shouldnt this also affect the accept command? should this also be per language?
163+
context_regex = '[%w_\\-]',
164+
-- LSPs can indicate when to show the completion window via trigger characters
165+
-- however, some LSPs (*cough* tsserver *cough*) return characters that would essentially
166+
-- always show the window. We block these by default
167+
blocked_trigger_characters = { ' ', '\n', '\t' },
168+
-- when true, will show the completion window when the cursor comes after a trigger character when entering insert mode
169+
show_on_insert_on_trigger_character = true,
170+
},
171+
172+
signature_help = {
173+
enabled = false,
174+
blocked_trigger_characters = {},
175+
blocked_retrigger_characters = {},
176+
-- when true, will show the signature help window when the cursor comes after a trigger character when entering insert mode
177+
show_on_insert_on_trigger_character = true,
178+
},
144179
},
145180

146181
fuzzy = {
@@ -172,17 +207,20 @@ local config = {
172207
min_width = 30,
173208
max_width = 60,
174209
max_height = 10,
210+
border = 'none',
211+
-- todo: implement
175212
order = 'top_down',
176213
-- which directions to show the window,
177214
-- falling back to the next direction when there's not enough space
178-
direction_priority = { 'n', 's' },
215+
direction_priority = { 's', 'n' },
179216
-- todo: implement
180217
preselect = true,
181218
},
182219
documentation = {
183220
min_width = 10,
184221
max_width = 60,
185222
max_height = 20,
223+
border = 'padded',
186224
-- which directions to show the documentation window,
187225
-- for each of the possible autocomplete window directions,
188226
-- falling back to the next direction when there's not enough space
@@ -194,6 +232,12 @@ local config = {
194232
auto_show_delay_ms = 500,
195233
update_delay_ms = 100,
196234
},
235+
signature_help = {
236+
min_width = 1,
237+
max_width = 100,
238+
max_height = 10,
239+
border = 'padded',
240+
},
197241
},
198242

199243
highlight = {

lua/blink/cmp/fuzzy/fuzzy.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// TODO: refactor this heresy
2+
13
use crate::frecency::FrecencyTracker;
24
use lua_marshalling::LuaMarshalling;
35
use serde::{Deserialize, Serialize};

lua/blink/cmp/init.lua

+28-7
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,22 @@ cmp.setup = function(opts)
1111
return
1212
end
1313

14-
require('blink.cmp.keymap').setup(config.keymap)
15-
1614
cmp.add_default_highlights()
17-
-- todo: do we need to clear first?
18-
vim.api.nvim_create_autocmd('ColorScheme', { callback = cmp.add_default_highlights })
15+
16+
require('blink.cmp.keymap').setup(config.keymap)
1917

2018
-- STRUCTURE
2119
-- trigger -> sources -> fuzzy (filter/sort) -> windows (render)
2220

2321
-- trigger controls when to show the window and the current context for caching
2422
-- TODO: add first_trigger event for setting up the rest of the plugin
25-
cmp.trigger = require('blink.cmp.trigger').activate_autocmds()
23+
cmp.trigger = require('blink.cmp.trigger.completion').activate_autocmds()
2624

27-
-- sources fetch autocomplete items and documentation
25+
-- sources fetch autocomplete items, documentation and signature help
2826
cmp.sources = require('blink.cmp.sources.lib')
2927
cmp.sources.register()
3028

31-
-- windows render and apply items
29+
-- windows render and apply completion items and signature help
3230
cmp.windows = {
3331
autocomplete = require('blink.cmp.windows.autocomplete').setup(),
3432
documentation = require('blink.cmp.windows.documentation').setup(),
@@ -64,9 +62,31 @@ cmp.setup = function(opts)
6462
cmp.windows.autocomplete.close()
6563
end)
6664
cmp.sources.listen_on_completions(update_completions)
65+
66+
-- setup signature help if enabled
67+
if config.trigger.signature_help.enabled then cmp.setup_signature_help() end
6768
end)
6869
end
6970

71+
cmp.setup_signature_help = function()
72+
local signature_trigger = require('blink.cmp.trigger.signature').activate_autocmds()
73+
local signature_window = require('blink.cmp.windows.signature').setup()
74+
75+
signature_trigger.listen_on_show(function(context)
76+
cmp.sources.cancel_signature_help()
77+
cmp.sources.get_signature_help(context, function(signature_help)
78+
if signature_help ~= nil then
79+
signature_trigger.set_active_signature_help(signature_help)
80+
signature_window.open_with_signature_help(context, signature_help)
81+
else
82+
signature_trigger.hide()
83+
end
84+
end)
85+
end)
86+
87+
signature_trigger.listen_on_hide(function() cmp.windows.signature.close() end)
88+
end
89+
7090
cmp.add_default_highlights = function()
7191
local use_nvim_cmp = require('blink.cmp.config').highlight.use_nvim_cmp_as_default
7292

@@ -79,6 +99,7 @@ cmp.add_default_highlights = function()
7999
set_hl('BlinkCmpLabelDeprecated', { link = use_nvim_cmp and 'CmpItemAbbrDeprecated' or 'Comment' })
80100
set_hl('BlinkCmpLabelMatch', { link = use_nvim_cmp and 'CmpItemAbbrMatch' or 'Pmenu' })
81101
set_hl('BlinkCmpKind', { link = use_nvim_cmp and 'CmpItemKind' or 'Special' })
102+
set_hl('BlinkCmpSignatureHelpActiveParameter', { link = 'LspSignatureActiveParameter' })
82103
for _, kind in pairs(vim.lsp.protocol.CompletionItemKind) do
83104
set_hl('BlinkCmpKind' .. kind, { link = use_nvim_cmp and 'CmpItemKind' .. kind or 'BlinkCmpItemKind' })
84105
end

0 commit comments

Comments
 (0)