Skip to content

Commit 6571c96

Browse files
committed
feat: nerd font variant and misc cleanup
1 parent 632e6ac commit 6571c96

File tree

7 files changed

+61
-38
lines changed

7 files changed

+61
-38
lines changed

README.md

+32-12
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ TODO: `nvim-cmp` sources are supported out of the box but migration to the `blin
4040
-- defaults to nvim-cmp's highlight groups for now
4141
-- will be removed in a future release, assuming themes add support
4242
use_nvim_cmp_as_default = true,
43-
}
43+
},
44+
-- set to 'mono' for 'Nerd Font Mono' or 'normal' for 'Nerd Font'
45+
-- adjusts spacing to ensure icons are aligned
46+
nerd_font_variant = 'normal',
4447
}
4548
}
4649
```
@@ -69,14 +72,19 @@ TODO: `nvim-cmp` sources are supported out of the box but migration to the `blin
6972
snippet_forward = '<Tab>',
7073
snippet_backward = '<S-Tab>',
7174
},
75+
7276
trigger = {
7377
-- regex used to get the text when fuzzy matching
78+
-- changing this may break some sources, so please report if you run into issues
7479
context_regex = '[%w_\\-]',
7580
-- LSPs can indicate when to show the completion window via trigger characters
7681
-- however, some LSPs (*cough* tsserver *cough*) return characters that would essentially
7782
-- always show the window. We block these by default
7883
blocked_trigger_characters = { ' ', '\n', '\t' },
84+
-- when true, will show the completion window when the cursor comes after a trigger character when entering insert mode
85+
show_on_insert_on_trigger_character = true,
7986
},
87+
8088
fuzzy = {
8189
-- frencency tracks the most recently/frequently used items and boosts the score of the item
8290
use_frecency = true,
@@ -86,13 +94,21 @@ TODO: `nvim-cmp` sources are supported out of the box but migration to the `blin
8694
-- controls which sorts to use and in which order, these three are currently the only allowed options
8795
sorts = { 'label', 'kind', 'score' },
8896
},
97+
8998
sources = {
99+
-- similar to nvim-cmp's sources, but we point directly to the source module
100+
-- multiple groups can be provided, where it'll fallback to the next group if the previous
101+
-- returns no completion items
90102
providers = {
91-
{ module = 'blink.cmp.sources.lsp' },
92-
{ module = 'blink.cmp.sources.buffer' },
93-
{ module = 'blink.cmp.sources.snippets', fallback_for = { 'blink.cmp.sources.lsp' } },
103+
{
104+
{ 'blink.cmp.sources.lsp' },
105+
{ 'blink.cmp.sources.path' },
106+
{ 'blink.cmp.sources.snippets', score_offset = -3 },
107+
},
108+
{ { 'blink.cmp.sources.buffer' } },
94109
},
95110
},
111+
96112
windows = {
97113
autocomplete = {
98114
min_width = 30,
@@ -102,8 +118,6 @@ TODO: `nvim-cmp` sources are supported out of the box but migration to the `blin
102118
-- which directions to show the window,
103119
-- falling back to the next direction when there's not enough space
104120
direction_priority = { 'n', 's' },
105-
-- whether to preselect the first item in the window
106-
preselect = true,
107121
},
108122
documentation = {
109123
min_width = 10,
@@ -117,15 +131,19 @@ TODO: `nvim-cmp` sources are supported out of the box but migration to the `blin
117131
autocomplete_south = { 'e', 'w', 's', 'n' },
118132
},
119133
auto_show = true,
120-
delay_ms = 0,
121-
debounce_ms = 100,
134+
auto_show_delay_ms = 0,
135+
update_delay_ms = 100,
122136
},
123137
},
124138

125139
highlight = {
126140
ns = vim.api.nvim_create_namespace('blink_cmp'),
141+
-- sets the fallback highlight groups to nvim-cmp's highlight groups
142+
-- useful for when your theme doesn't support blink.cmp
127143
use_nvim_cmp_as_default = false,
128144
},
145+
146+
nerd_font_variant = 'mono',
129147
kind_icons = {
130148
Text = '󰉿',
131149
Method = '󰊕',
@@ -171,15 +189,15 @@ The plugin use a 4 stage pipeline: trigger -> sources -> fuzzy -> render
171189

172190
**Trigger:** Controls when to request completion items from the sources and provides a context downstream with the current query (i.e. `hello.wo|`, the query would be `wo`) and the treesitter object under the cursor (i.e. for intelligently enabling/disabling sources). It respects trigger characters passed by the LSP (or any other source) and includes it in the context for sending to the LSP.
173191

174-
**Sources:** Provides a common interface for and merges the results of completion, trigger character, resolution of additional information and cancellation. It also provides a compatibility layer to `nvim-cmp`'s sources. Many sources are builtin: `LSP`, `buffer`, `treesitter`, `path`, `snippets`
192+
**Sources:** Provides a common interface for and merges the results of completion, trigger character, resolution of additional information and cancellation. It also provides a compatibility layer to `nvim-cmp`'s sources. Some sources are builtin: `LSP`, `buffer`, `path`, `snippets`
175193

176194
**Fuzzy:** Rust <-> Lua FFI which performs both filtering and sorting of the items
177195

178196
&nbsp;&nbsp;&nbsp;&nbsp;**Filtering:** The fuzzy matching uses smith-waterman, same as FZF, but implemented in SIMD for ~6x the performance of FZF (todo: add benchmarks). Due to the SIMD's performance, the prefiltering phase on FZF was dropped to allow for typos. Similar to fzy/fzf, additional points are given to prefix matches, characters with capitals (to promote camelCase/PascalCase first char matching) and matches after delimiters (to promote snake_case first char matching)
179197

180-
&nbsp;&nbsp;&nbsp;&nbsp;**Sorting:** Combines fuzzy matching score with frecency and proximity bonus. Each completion item may also include a `score_offset` which will be added to this score to demote certain sources. The `buffer` and `snippets` sources take advantage of this to avoid taking presedence over the LSP source. The paramaters here still need to be tuned and have been exposed, so please let me know if you find some magical parameters!
198+
&nbsp;&nbsp;&nbsp;&nbsp;**Sorting:** Combines fuzzy matching score with frecency and proximity bonus. Each completion item may also include a `score_offset` which will be added to this score to demote certain sources. The `snippets` source takes advantage of this to avoid taking presedence over the LSP source. The paramaters here still need to be tuned, so please let me know if you find some magical parameters!
181199

182-
**Render:** Responsible for placing the autocomplete, documentation and function parameters windows. All of the rendering can be overriden following a syntax similar to incline.nvim. It uses the neovim window decoration provider to provide next to no overhead from highlighting.
200+
**Windows:** Responsible for placing the autocomplete, documentation and function parameters windows. All of the rendering can be overriden following a syntax similar to incline.nvim. It uses the neovim window decoration provider to provide next to no overhead from highlighting.
183201

184202
## Compared to nvim-cmp
185203

@@ -190,7 +208,7 @@ The plugin use a 4 stage pipeline: trigger -> sources -> fuzzy -> render
190208
- Setting nvim-cmp's debounce to 0ms leads to visible stuttering. If you'd like to stick with nvim-cmp, try [yioneko's fork](https://github.com/yioneko/nvim-cmp)
191209
- Boosts completion item score via frecency *and* proximity bonus. nvim-cmp only boosts score via proximity bonus
192210
- Typo-resistant fuzzy matching unlike nvim-cmp's fzf-style fuzzy matching
193-
- Core sources (buffer, snippets, lsp) are built-in versus nvim-cmp's exclusively external sources
211+
- Core sources (buffer, snippets, path, lsp) are built-in versus nvim-cmp's exclusively external sources
194212
- Uses native snippets versus nvim-cmp's required snippet engine
195213

196214
### Disadvantages
@@ -204,6 +222,8 @@ All of the following are planned, but not yet implemented.
204222

205223
## Special Thanks
206224

225+
@hrsh7th nvim-cmp used as inspiration, nvim-path implementation used for path source
226+
207227
@garymjr nvim-snippets implementation used for snippets source
208228

209229
@redxtech Help with design and testing

lua/blink/cmp/config.lua

+18-9
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,19 @@
6262
--- @field max_height number
6363
--- @field direction_priority blink.cmp.DocumentationDirectionPriorityConfig
6464
--- @field auto_show boolean
65-
--- @field debounce_ms number
66-
--- @field delay_ms number
65+
--- @field auto_show_delay_ms number Delay before showing the documentation window
66+
--- @field update_delay_ms number Delay before updating the documentation window
6767

68-
--- @class blink.cmp.CmpConfig
68+
--- @class blink.cmp.Config
6969
--- @field trigger blink.cmp.TriggerConfig
7070
--- @field fuzzy blink.cmp.FuzzyConfig
7171
--- @field sources blink.cmp.SourceConfig
7272
--- @field windows blink.cmp.WindowConfig
7373
--- @field highlight blink.cmp.HighlightConfig
74+
--- @field nerd_font_variant 'mono' | 'normal'
7475
--- @field kind_icons table<string, string>
7576

76-
--- @type blink.cmp.CmpConfig
77+
--- @type blink.cmp.Config
7778
local config = {
7879
keymap = {
7980
show = '<C-space>',
@@ -90,34 +91,40 @@ local config = {
9091
snippet_forward = '<Tab>',
9192
snippet_backward = '<S-Tab>',
9293
},
94+
9395
trigger = {
96+
-- todo: shouldnt this also affect the accept command? should this also be per language?
9497
context_regex = '[%w_\\-]',
9598
blocked_trigger_characters = { ' ', '\n', '\t' },
9699
show_on_insert_on_trigger_character = true,
97100
},
101+
98102
fuzzy = {
99103
use_frecency = true,
100104
use_proximity = true,
101105
max_items = 200,
102106
sorts = { 'label', 'kind', 'score' },
103107
},
108+
104109
sources = {
105110
providers = {
106111
{
107112
{ 'blink.cmp.sources.lsp' },
108113
{ 'blink.cmp.sources.path' },
109114
{ 'blink.cmp.sources.snippets', score_offset = -3 },
110115
},
111-
{ { 'blink.cmp.sources.buffer', score_offset = -9 } },
116+
{ { 'blink.cmp.sources.buffer' } },
112117
},
113118
},
119+
114120
windows = {
115121
autocomplete = {
116122
min_width = 30,
117123
max_width = 60,
118124
max_height = 10,
119125
order = 'top_down',
120126
direction_priority = { 'n', 's' },
127+
-- todo: implement
121128
preselect = true,
122129
},
123130
documentation = {
@@ -129,15 +136,17 @@ local config = {
129136
autocomplete_south = { 'e', 'w', 's', 'n' },
130137
},
131138
auto_show = true,
132-
delay_ms = 0,
133-
debounce_ms = 100,
139+
auto_show_delay_ms = 0,
140+
update_delay_ms = 100,
134141
},
135142
},
136143

137144
highlight = {
138145
ns = vim.api.nvim_create_namespace('blink_cmp'),
139146
use_nvim_cmp_as_default = false,
140147
},
148+
149+
nerd_font_variant = 'normal',
141150
kind_icons = {
142151
Text = '󰉿',
143152
Method = '󰊕',
@@ -172,10 +181,10 @@ local config = {
172181
},
173182
}
174183

175-
--- @class blink.cmp.CmpConfig
184+
--- @class blink.cmp.Config
176185
local M = {}
177186

178-
--- @param opts blink.cmp.CmpConfig
187+
--- @param opts blink.cmp.Config
179188
function M.merge_with(opts) config = vim.tbl_deep_extend('force', config, opts or {}) end
180189

181190
return setmetatable(M, { __index = function(_, k) return config[k] end })

lua/blink/cmp/init.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
local cmp = {}
22

3-
--- @param opts blink.cmp.CmpConfig
3+
--- @param opts blink.cmp.Config
44
cmp.setup = function(opts)
55
local config = require('blink.cmp.config')
66
config.merge_with(opts)

lua/blink/cmp/sources/lib/context.lua

-5
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,13 @@ function sources_context.new(context, sources_groups, on_completions_callback)
1111

1212
self.active_request = nil
1313
self.queued_request_context = nil
14-
self.last_successful_completions = nil
1514
self.last_sources_group_idx = nil
1615
--- @type fun(context: blink.cmp.Context, items: blink.cmp.CompletionItem[])
1716
self.on_completions_callback = on_completions_callback
1817

1918
return self
2019
end
2120

22-
--- @return blink.cmp.CompletionItem[]
23-
function sources_context:get_last_successful_completions() return self.last_successful_completions end
24-
2521
--- @param context blink.cmp.Context
2622
function sources_context:get_completions(context)
2723
assert(context.id == self.id, 'Requested completions on a sources context with a different context ID')
@@ -46,7 +42,6 @@ function sources_context:get_completions(context)
4642
-- Send response upstream and run the queued request, if it exists
4743
self.active_request = request:map(function(response)
4844
self.active_request = nil
49-
self.last_successful_completions = response.items
5045
-- only send upstream if the response contains something new
5146
if not response.is_cached or response.sources_group_idx ~= self.last_sources_group_idx then
5247
self.on_completions_callback(context, response.items)

lua/blink/cmp/sources/lib/init.lua

-4
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,6 @@ function sources.request_completions(context)
5151
sources.current_context:get_completions(context)
5252
end
5353

54-
function sources.get_last_successful_completions()
55-
return sources.current_context and sources.current_context:get_last_successful_completions()
56-
end
57-
5854
function sources.cancel_completions()
5955
if sources.current_context ~= nil then sources.current_context:destroy() end
6056
sources.current_context = nil

lua/blink/cmp/windows/autocomplete.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ function autocomplete.draw_item(item, max_length)
194194
local other_content_length = 5
195195
local abbr = string.sub(label, 1, max_length - other_content_length)
196196

197-
return string.format(' %s %s ', kind_icon, abbr)
197+
return string.format(' %s%s%s ', kind_icon, config.nerd_font_variant == 'mono' and ' ' or ' ', abbr)
198198
end
199199

200200
function autocomplete.get_label(item) return item.label end

lua/blink/cmp/windows/documentation.lua

+9-6
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@ function docs.setup()
1515
})
1616

1717
autocomplete.listen_on_position_update(function()
18-
if autocomplete.win:get_win() then docs.update_position() end
18+
if autocomplete.win:is_open() then docs.update_position() end
1919
end)
2020
if config.auto_show then
21-
if config.delay_ms > 0 then
22-
autocomplete.listen_on_select(utils.debounce(docs.show_item, config.delay_ms))
23-
else
24-
autocomplete.listen_on_select(docs.show_item)
25-
end
21+
autocomplete.listen_on_select(function(item)
22+
local delay = autocomplete.win:is_open() and config.update_delay_ms or config.auto_show_delay_ms
23+
if delay == 0 then
24+
return docs.show_item(item)
25+
else
26+
utils.debounce(docs.show_item, delay)(item)
27+
end
28+
end)
2629
end
2730
autocomplete.listen_on_close(function() docs.win:close() end)
2831

0 commit comments

Comments
 (0)