Skip to content

Commit 6b78c89

Browse files
committed
feat: dynamic cmp and doc window width
1 parent fae11d1 commit 6b78c89

File tree

4 files changed

+37
-33
lines changed

4 files changed

+37
-33
lines changed

lua/blink/cmp/sources/init.lua

+2-6
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,9 @@ function sources.send_completions()
116116
end
117117

118118
-- flatten the items
119-
local flattened_items = nil
119+
local flattened_items = {}
120120
for _, response in pairs(sources.sources_items) do
121-
if flattened_items == nil then
122-
flattened_items = response.items
123-
else
124-
vim.list_extend(flattened_items, response.items)
125-
end
121+
vim.list_extend(flattened_items, response.items)
126122
end
127123

128124
sources.on_completions_callback(flattened_items)

lua/blink/cmp/windows/autocomplete.lua

+4-3
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,12 @@ function autocomplete.draw_item(item)
130130
local kind_icon = config.kind_icons[kind] or config.kind_icons.Field
131131

132132
-- get line text
133-
local max_length = 40
134-
local utf8len = vim.fn.strdisplaywidth
133+
local max_length = autocomplete.win.config.max_width
134+
local utf8len = vim.api.nvim_strwidth
135135
local other_content_length = utf8len(kind_icon) + utf8len(kind) + 5
136136
local remaining_length = math.max(0, max_length - other_content_length - utf8len(item.label))
137-
local abbr = string.sub(item.label, 1, max_length - other_content_length) .. string.rep(' ', remaining_length)
137+
-- + 1 to include the final character, + 1 to account for lua being 1-indexed
138+
local abbr = string.sub(item.label, 1, max_length - other_content_length + 2) .. string.rep(' ', remaining_length)
138139

139140
return string.format(' %s %s %s ', kind_icon, abbr, kind)
140141
end

lua/blink/cmp/windows/documentation.lua

+11-5
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ local docs = {}
66

77
function docs.setup()
88
docs.win = require('blink.cmp.windows.lib').new({
9-
width = 60,
9+
min_width = 10,
1010
max_height = 20,
1111
wrap = true,
12-
-- todo: should be able to use the markdown stuff now?
13-
-- filetype = 'typescript', -- todo: set dynamically
12+
-- todo: is just using markdown enough?
13+
filetype = 'markdown',
1414
padding = true,
1515
})
1616

@@ -31,18 +31,24 @@ function docs.show_item(item)
3131
end
3232

3333
sources.resolve(item, function(resolved_item)
34-
if resolved_item.detail == nil then
34+
if resolved_item.documentation == nil then
3535
docs.win:close()
3636
return
3737
end
3838

39+
-- todo: respect .kind (MarkupKind) which is markdown or plaintext
3940
local doc_lines = {}
40-
for s in resolved_item.detail:gmatch('[^\r\n]+') do
41+
for s in resolved_item.documentation.value:gmatch('[^\r\n]+') do
4142
table.insert(doc_lines, s)
4243
end
4344
vim.api.nvim_buf_set_lines(docs.win:get_buf(), 0, -1, true, doc_lines)
4445
vim.api.nvim_set_option_value('modified', false, { buf = docs.win:get_buf() })
4546

47+
local filetype = resolved_item.documentation.kind == 'markdown' and 'markdown' or 'plaintext'
48+
if filetype ~= vim.api.nvim_get_option_value('filetype', { buf = docs.win:get_buf() }) then
49+
vim.api.nvim_set_option_value('filetype', filetype, { buf = docs.win:get_buf() })
50+
end
51+
4652
if autocomplete.win:get_win() then
4753
docs.win:open()
4854
docs.win:update_position(autocomplete.win:get_win())

lua/blink/cmp/windows/lib.lua

+20-19
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ function win.new(config)
55

66
self.id = nil
77
self.config = {
8-
width = config.width or 40,
8+
min_width = config.min_width or 30,
9+
max_width = config.max_width or 60,
910
max_height = config.max_height or 10,
1011
cursorline = config.cursorline or false,
1112
wrap = config.wrap or false,
@@ -21,8 +22,8 @@ function win:get_buf()
2122
-- create buffer if it doesn't exist
2223
if self.buf == nil or not vim.api.nvim_buf_is_valid(self.buf) then
2324
self.buf = vim.api.nvim_create_buf(false, true)
24-
-- vim.api.nvim_buf_set_option(self.buf, 'tabstop', 1) -- prevents tab widths from being unpredictable
25-
-- vim.api.nvim_buf_set_option(self.buf, 'filetype', self.config.filetype)
25+
vim.api.nvim_set_option_value('tabstop', 1, { buf = self.buf }) -- prevents tab widths from being unpredictable
26+
vim.api.nvim_set_option_value('filetype', self.config.filetype, { buf = self.buf })
2627
end
2728
return self.buf
2829
end
@@ -43,7 +44,7 @@ function win:open()
4344
self.id = vim.api.nvim_open_win(self:get_buf(), false, {
4445
relative = 'cursor',
4546
style = 'minimal',
46-
width = self.config.width,
47+
width = self.config.min_width,
4748
height = self.config.max_height,
4849
row = 1,
4950
col = 1,
@@ -80,11 +81,14 @@ function win:update_position(relative_to)
8081
local cursor_row = cursor[1]
8182
local cursor_col = cursor[2]
8283

83-
-- set height to current line count
84+
-- set width to current content width, bounded by min and max
85+
local width = math.max(math.min(self:get_content_width(), config.max_width), config.min_width)
86+
vim.api.nvim_win_set_width(winnr, width)
87+
88+
-- set height to current line count, bounded by max
8489
local height = math.min(self:get_content_height(), config.max_height)
8590
vim.api.nvim_win_set_height(winnr, height)
8691

87-
-- relative to cursor
8892
if relative_to == 'cursor' then
8993
local is_space_below = screen_height - cursor_row > height
9094

@@ -102,9 +106,7 @@ function win:update_position(relative_to)
102106
local max_width_right = screen_width - cursor_col - relative_win_config.width - 7
103107
local max_width_left = cursor_col
104108

105-
local width = math.min(math.max(max_width_left, max_width_right), config.width)
106-
107-
if max_width_right >= config.width or max_width_right >= max_width_left then
109+
if max_width_right >= width or max_width_right >= max_width_left then
108110
vim.api.nvim_win_set_config(winnr, {
109111
relative = 'win',
110112
win = relative_to,
@@ -121,7 +123,6 @@ function win:update_position(relative_to)
121123
width = width,
122124
})
123125
end
124-
-- No idea what it's supposed to be relative to
125126
else
126127
error('Invalid relative config')
127128
end
@@ -131,15 +132,15 @@ end
131132
function win:get_content_height()
132133
if not self:is_open() then return 0 end
133134
return vim.api.nvim_win_text_height(self:get_win(), {}).all
134-
--
135-
-- if not self.config.wrap then return vim.api.nvim_buf_line_count(self.buf) end
136-
-- local height = 0
137-
-- vim.api.nvim_buf_call(self.buf, function()
138-
-- for _, text in ipairs(vim.api.nvim_buf_get_lines(self.buf, 0, -1, false)) do
139-
-- height = height + math.max(1, math.ceil(vim.fn.strdisplaywidth(text) / self.config.width))
140-
-- end
141-
-- end)
142-
-- return height
135+
end
136+
137+
function win:get_content_width()
138+
if not self:is_open() then return 0 end
139+
local max_width = 0
140+
for _, line in ipairs(vim.api.nvim_buf_get_lines(self.buf, 0, -1, false)) do
141+
max_width = math.max(max_width, vim.api.nvim_strwidth(line))
142+
end
143+
return max_width
143144
end
144145

145146
return win

0 commit comments

Comments
 (0)