|
| 1 | +--- @class blink.cmp.CompletionRenderContext |
| 2 | +--- @field item blink.cmp.CompletionItem |
| 3 | +--- @field kind string |
| 4 | +--- @field kind_icon string |
| 5 | +--- @field icon_gap string |
| 6 | + |
1 | 7 | -- todo: track cursor position
|
2 | 8 | local config = require('blink.cmp.config')
|
| 9 | +local renderer = require('blink.cmp.windows.lib.render') |
3 | 10 | local autocmp_config = config.windows.autocomplete
|
4 | 11 | local autocomplete = {
|
5 | 12 | items = {},
|
@@ -30,32 +37,9 @@ function autocomplete.setup()
|
30 | 37 | return autocomplete.win:get_win() == winnr and bufnr == autocomplete.win:get_buf()
|
31 | 38 | end,
|
32 | 39 | on_line = function(_, _, bufnr, line_number)
|
33 |
| - local item = autocomplete.items[line_number + 1] |
34 |
| - if item == nil then return end |
35 |
| - local line_text = vim.api.nvim_buf_get_lines(bufnr, line_number, line_number + 1, false)[1] |
36 |
| - |
37 |
| - local kind = vim.lsp.protocol.CompletionItemKind[item.kind] or 'Unknown' |
38 |
| - local kind_hl = 'BlinkCmpKind' .. kind |
39 |
| - |
40 |
| - -- todo: handle .labelDetails and others |
41 |
| - vim.api.nvim_buf_set_extmark(bufnr, config.highlight.ns, line_number, 0, { |
42 |
| - end_col = 4, |
43 |
| - hl_group = kind_hl, |
44 |
| - hl_mode = 'combine', |
45 |
| - hl_eol = true, |
46 |
| - ephemeral = true, |
47 |
| - }) |
48 |
| - |
49 |
| - -- todo: use vim.lsp.protocol.CompletionItemTag |
50 |
| - if item.deprecated or (item.tags and vim.tbl_contains(item.tags, 1)) then |
51 |
| - -- todo: why 7? |
52 |
| - vim.api.nvim_buf_set_extmark(bufnr, config.highlight.ns, line_number, 7, { |
53 |
| - end_col = #line_text - 1, |
54 |
| - hl_group = 'BlinkCmpLabelDeprecated', |
55 |
| - hl_mode = 'combine', |
56 |
| - ephemeral = true, |
57 |
| - }) |
58 |
| - end |
| 40 | + local rendered_item = autocomplete.rendered_items[line_number + 1] |
| 41 | + if rendered_item == nil then return end |
| 42 | + renderer.draw_highlights(rendered_item, bufnr, config.highlight.ns, line_number) |
59 | 43 | end,
|
60 | 44 | })
|
61 | 45 |
|
@@ -174,42 +158,68 @@ function autocomplete.listen_on_select(callback) autocomplete.event_targets.on_s
|
174 | 158 | ---------- Rendering ----------
|
175 | 159 |
|
176 | 160 | function autocomplete.draw()
|
177 |
| - local max_line_width = 0 |
| 161 | + local draw_fn = autocomplete.get_draw_fn() |
| 162 | + local icon_gap = config.nerd_font_variant == 'mono' and ' ' or ' ' |
| 163 | + local arr_of_components = {} |
178 | 164 | for _, item in ipairs(autocomplete.items) do
|
179 |
| - max_line_width = math.max(max_line_width, autocomplete.get_item_max_length(item)) |
| 165 | + local kind = vim.lsp.protocol.CompletionItemKind[item.kind] or 'Unknown' |
| 166 | + local kind_icon = config.kind_icons[kind] or config.kind_icons.Field |
| 167 | + |
| 168 | + table.insert( |
| 169 | + arr_of_components, |
| 170 | + draw_fn({ |
| 171 | + item = item, |
| 172 | + kind = kind, |
| 173 | + kind_icon = kind_icon, |
| 174 | + icon_gap = icon_gap, |
| 175 | + }) |
| 176 | + ) |
180 | 177 | end
|
181 |
| - local target_width = |
182 |
| - math.max(math.min(max_line_width, autocomplete.win.config.max_width), autocomplete.win.config.min_width) |
183 | 178 |
|
184 |
| - local lines = {} |
185 |
| - for _, item in ipairs(autocomplete.items) do |
186 |
| - table.insert(lines, autocomplete.draw_item(item, target_width)) |
187 |
| - end |
| 179 | + local max_line_length = renderer.get_max_length(arr_of_components) |
| 180 | + autocomplete.rendered_items = vim.tbl_map( |
| 181 | + function(component) return renderer.render(component, max_line_length) end, |
| 182 | + arr_of_components |
| 183 | + ) |
188 | 184 |
|
| 185 | + local lines = vim.tbl_map(function(rendered) return rendered.text end, autocomplete.rendered_items) |
189 | 186 | local bufnr = autocomplete.win:get_buf()
|
190 | 187 | vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
191 | 188 | vim.api.nvim_set_option_value('modified', false, { buf = bufnr })
|
192 | 189 | end
|
193 | 190 |
|
194 |
| -function autocomplete.get_item_max_length(item) |
195 |
| - local icon_width = 4 |
196 |
| - local label_width = vim.api.nvim_strwidth(autocomplete.get_label(item)) |
197 |
| - return icon_width + label_width |
| 191 | +function autocomplete.get_draw_fn() |
| 192 | + if type(autocmp_config.draw) == 'function' then |
| 193 | + return autocmp_config.draw |
| 194 | + elseif autocmp_config.draw == 'simple' then |
| 195 | + return autocomplete.render_item_simple |
| 196 | + elseif autocmp_config.draw == 'reversed' then |
| 197 | + return autocomplete.render_item_reversed |
| 198 | + end |
| 199 | + error('Invalid autocomplete window draw config') |
198 | 200 | end
|
199 | 201 |
|
200 |
| -function autocomplete.draw_item(item, max_length) |
201 |
| - local kind = vim.lsp.protocol.CompletionItemKind[item.kind] or 'Unknown' |
202 |
| - local kind_icon = config.kind_icons[kind] or config.kind_icons.Field |
203 |
| - |
204 |
| - -- get line text |
205 |
| - local label = autocomplete.get_label(item) |
206 |
| - local other_content_length = 5 |
207 |
| - local abbr = string.sub(label, 1, max_length - other_content_length) |
208 |
| - |
209 |
| - return string.format(' %s%s%s ', kind_icon, config.nerd_font_variant == 'mono' and ' ' or ' ', abbr) |
| 202 | +--- @param ctx blink.cmp.CompletionRenderContext |
| 203 | +--- @return blink.cmp.Component[] |
| 204 | +function autocomplete.render_item_simple(ctx) |
| 205 | + return { |
| 206 | + { ' ', ctx.kind_icon, ctx.icon_gap, hl_group = 'BlinkCmpKind' .. ctx.kind }, |
| 207 | + { ctx.item.label, fill = true, hl_group = ctx.item.deprecated and 'BlinkCmpLabelDeprecated' or 'BlinkCmpLabel' }, |
| 208 | + } |
210 | 209 | end
|
211 | 210 |
|
212 |
| -function autocomplete.get_label(item) return item.label end |
| 211 | +--- @param ctx blink.cmp.CompletionRenderContext |
| 212 | +--- @return blink.cmp.Component[] |
| 213 | +function autocomplete.render_item_reversed(ctx) |
| 214 | + return { |
| 215 | + { |
| 216 | + ' ' .. ctx.item.label, |
| 217 | + fill = true, |
| 218 | + hl_group = ctx.item.deprecated and 'BlinkCmpLabelDeprecated' or 'BlinkCmpLabel', |
| 219 | + }, |
| 220 | + { ' ', ctx.kind_icon, ctx.icon_gap, ctx.kind .. ' ', hl_group = 'BlinkCmpKind' .. ctx.kind }, |
| 221 | + } |
| 222 | +end |
213 | 223 |
|
214 | 224 | function autocomplete.get_selected_item()
|
215 | 225 | if not autocomplete.win:is_open() then return end
|
|
0 commit comments