Skip to content

Commit 8a599ba

Browse files
committed
fix: a lot
1 parent 2974bc0 commit 8a599ba

File tree

3 files changed

+198
-166
lines changed

3 files changed

+198
-166
lines changed

lua/blink/cmp/cmp.lua

+86-40
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,37 @@ M.accept = function(cmp_win)
5959
end
6060
end
6161

62-
M.select_next = function(cmp_win)
62+
M.select_next = function(cmp_win, doc_win)
63+
if cmp_win.id == nil then return end
64+
6365
local current_line = vim.api.nvim_win_get_cursor(cmp_win.id)[1]
64-
vim.api.nvim_win_set_cursor(cmp_win.id, { current_line + 1, 0 })
66+
local item_count = #M.filtered_items
67+
local line_count = vim.api.nvim_buf_line_count(cmp_win.buf)
68+
69+
-- draw a new line if we're at the end and there's more items
70+
-- todo: this is a hack while waiting for virtual scroll
71+
if current_line == line_count and item_count > line_count then
72+
M.draw_item(cmp_win.buf, line_count + 1, M.filtered_items[line_count + 1])
73+
vim.api.nvim_win_set_cursor(cmp_win.id, { line_count + 1, 0 })
74+
-- otherwise just move the cursor, wrapping if at the bottom
75+
else
76+
local line = current_line == item_count and 1 or current_line + 1
77+
vim.api.nvim_win_set_cursor(cmp_win.id, { line, 0 })
78+
end
79+
80+
M.update_doc(cmp_win, doc_win)
6581
end
6682

67-
M.select_prev = function(cmp_win)
83+
-- todo: how to handle overflow to the bottom? should probably just do proper virtual scroll
84+
M.select_prev = function(cmp_win, doc_win)
85+
if cmp_win.id == nil then return end
86+
6887
local current_line = vim.api.nvim_win_get_cursor(cmp_win.id)[1]
69-
vim.api.nvim_win_set_cursor(cmp_win.id, { current_line - 1, 0 })
88+
local line_count = vim.api.nvim_buf_line_count(cmp_win.buf)
89+
local line = current_line - 1 == 0 and line_count or current_line - 1
90+
vim.api.nvim_win_set_cursor(cmp_win.id, { line, 0 })
91+
92+
M.update_doc(cmp_win, doc_win)
7093
end
7194

7295
M.update = function(cmp_win, doc_win, items, opts)
@@ -89,51 +112,74 @@ M.update = function(cmp_win, doc_win, items, opts)
89112

90113
-- update completion window
91114
vim.api.nvim_buf_set_lines(cmp_win.buf, 0, -1, true, {})
92-
for idx, item in ipairs(filtered_items) do
93-
local max_length = 40
94-
local kind_hl = 'CmpItemKind' .. item.kind
95-
local kind_icon = M.kind_icons[item.kind] or M.kind_icons.Field
96-
local kind = item.kind
97-
98-
local utf8len = vim.fn.strdisplaywidth
99-
local other_content_length = utf8len(kind_icon) + utf8len(kind) + 5
100-
local remaining_length = math.max(0, max_length - other_content_length - utf8len(item.abbr))
101-
local abbr = string.sub(item.abbr, 1, max_length - other_content_length) .. string.rep(' ', remaining_length)
102-
103-
local line = string.format(' %s %s %s ', kind_icon, abbr, kind)
104-
vim.api.nvim_buf_set_lines(cmp_win.buf, idx - 1, idx, false, { line })
105-
vim.api.nvim_buf_add_highlight(cmp_win.buf, -1, kind_hl, idx - 1, 0, #kind_icon + 2)
115+
vim.api.nvim_buf_set_option(cmp_win.buf, 'modified', false)
106116

107-
if idx > cmp_win.config.max_height then break end
117+
for idx, item in ipairs(filtered_items) do
118+
M.draw_item(cmp_win.buf, idx, item)
119+
-- only draw until the window is full
120+
if idx >= cmp_win.config.max_height then break end
108121
end
109-
110-
-- set height
111-
vim.api.nvim_win_set_height(cmp_win.id, math.min(#filtered_items, cmp_win.config.max_height))
112-
113122
-- select first line
114123
vim.api.nvim_win_set_cursor(cmp_win.id, { 1, 0 })
124+
cmp_win:update()
115125

116126
-- documentation
117-
local first_item = filtered_items[1]
118-
if first_item ~= nil then
119-
M.lsp.resolve(first_item, function(_, resolved_item)
120-
if resolved_item.detail == nil then
121-
doc_win:close()
122-
return
123-
end
124-
local doc_lines = {}
125-
for s in resolved_item.detail:gmatch('[^\r\n]+') do
126-
table.insert(doc_lines, s)
127-
end
128-
vim.api.nvim_buf_set_lines(doc_win.buf, 0, -1, true, doc_lines)
129-
doc_win:open()
130-
end)
131-
end
127+
M.update_doc(cmp_win, doc_win)
132128

133129
M.filtered_items = filtered_items
134130
end
135131

132+
function M.update_doc(cmp_win, doc_win)
133+
-- completion window isn't open
134+
if cmp_win.id == nil then return end
135+
136+
local current_line = vim.api.nvim_win_get_cursor(cmp_win.id)[1]
137+
local item = M.filtered_items[current_line]
138+
if item == nil then
139+
doc_win:close()
140+
return
141+
end
142+
143+
M.lsp.resolve(item, function(_, resolved_item)
144+
if resolved_item.detail == nil then
145+
doc_win:close()
146+
return
147+
end
148+
local doc_lines = {}
149+
for s in resolved_item.detail:gmatch('[^\r\n]+') do
150+
table.insert(doc_lines, s)
151+
end
152+
vim.api.nvim_buf_set_lines(doc_win.buf, 0, -1, true, doc_lines)
153+
doc_win:open()
154+
155+
-- set unmodified so we don't get the prompt to save
156+
vim.api.nvim_buf_set_option(doc_win.buf, 'modified', false)
157+
end)
158+
end
159+
136160
---------- UTILS ------------
161+
M.draw_item = function(bufnr, idx, item)
162+
-- get highlight
163+
local kind_hl = 'CmpItemKind' .. item.kind
164+
local kind_icon = M.kind_icons[item.kind] or M.kind_icons.Field
165+
local kind = item.kind
166+
167+
-- get line text
168+
local max_length = 40
169+
local utf8len = vim.fn.strdisplaywidth
170+
local other_content_length = utf8len(kind_icon) + utf8len(kind) + 5
171+
local remaining_length = math.max(0, max_length - other_content_length - utf8len(item.abbr))
172+
local abbr = string.sub(item.abbr, 1, max_length - other_content_length) .. string.rep(' ', remaining_length)
173+
174+
local line = string.format(' %s %s %s ', kind_icon, abbr, kind)
175+
176+
-- draw the line
177+
vim.api.nvim_buf_set_lines(bufnr, idx - 1, idx, false, { line })
178+
vim.api.nvim_buf_add_highlight(bufnr, -1, kind_hl, idx - 1, 0, #kind_icon + 2)
179+
180+
-- set unmodified so we don't get the prompt to save
181+
vim.api.nvim_buf_set_option(bufnr, 'modified', false)
182+
end
137183

138184
M.filter_items = function(query, items)
139185
if query == '' then return items end
@@ -165,7 +211,7 @@ end
165211

166212
M.get_query_to_replace = function(bufnr)
167213
local current_line = vim.api.nvim_win_get_cursor(0)[1]
168-
local current_col = vim.api.nvim_win_get_cursor(0)[2] + 1
214+
local current_col = vim.api.nvim_win_get_cursor(0)[2]
169215
local line = vim.api.nvim_buf_get_lines(bufnr, current_line - 1, current_line, false)[1]
170216

171217
-- Search forward/backward for the start/end of the word
@@ -184,7 +230,7 @@ M.get_query_to_replace = function(bufnr)
184230
end
185231

186232
-- convert to 0-index
187-
return current_line - 1, start_col - 1, end_col - 1
233+
return current_line - 1, start_col - 1, end_col
188234
end
189235

190236
M.apply_additional_text_edits = function(client_id, item) M.apply_text_edits(client_id, item.additionalTextEdits or {}) end

lua/blink/cmp/init.lua

+2-13
Original file line numberDiff line numberDiff line change
@@ -94,19 +94,8 @@ M.accept = function()
9494
if M.cmp_win.id ~= nil then M.cmp.accept(M.cmp_win) end
9595
end
9696

97-
M.select_prev = function()
98-
if M.cmp_win.id == nil then return end
97+
M.select_prev = function() M.cmp.select_prev(M.cmp_win, M.doc_win) end
9998

100-
local current_line = vim.api.nvim_win_get_cursor(M.cmp_win.id)[1]
101-
vim.api.nvim_win_set_cursor(M.cmp_win.id, { math.max(1, current_line - 1), 0 })
102-
end
103-
104-
M.select_next = function()
105-
if M.cmp_win.id == nil then return end
106-
107-
local current_line = vim.api.nvim_win_get_cursor(M.cmp_win.id)[1]
108-
local line_count = vim.api.nvim_buf_line_count(M.cmp_win.buf)
109-
vim.api.nvim_win_set_cursor(M.cmp_win.id, { math.min(line_count, current_line + 1), 0 })
110-
end
99+
M.select_next = function() M.cmp.select_next(M.cmp_win, M.doc_win) end
111100

112101
return M

0 commit comments

Comments
 (0)