Skip to content

Commit 819b978

Browse files
committed
fix: window positioning with folds
closes #95
1 parent c679e7f commit 819b978

File tree

3 files changed

+28
-19
lines changed

3 files changed

+28
-19
lines changed

lua/blink/cmp/windows/autocomplete.lua

+3-5
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,9 @@ function autocomplete.update_position(context)
121121
win:update_size()
122122

123123
local height = win:get_height()
124-
local screen_height = vim.api.nvim_win_get_height(0)
125-
local screen_scroll_range = win.get_screen_scroll_range()
124+
local cursor_screen_position = win.get_cursor_screen_position()
126125

127126
local cursor = vim.api.nvim_win_get_cursor(0)
128-
local cursor_row = cursor[1]
129127
local cursor_col = cursor[2]
130128

131129
-- place the window at the start col of the current text we're fuzzy matching against
@@ -134,8 +132,8 @@ function autocomplete.update_position(context)
134132

135133
-- detect if there's space above/below the cursor
136134
-- todo: should pick the largest space if both are false and limit height of the window
137-
local is_space_below = screen_height - (cursor_row - screen_scroll_range.start_line) > height
138-
local is_space_above = cursor_row - screen_scroll_range.start_line > height
135+
local is_space_below = cursor_screen_position.distance_from_bottom > height
136+
local is_space_above = cursor_screen_position.distance_from_top > height
139137

140138
-- default to the user's preference but attempt to use the other options
141139
local row = autocmp_config.direction_priority[1] == 's' and 1 or -height

lua/blink/cmp/windows/lib/init.lua

+22-10
Original file line numberDiff line numberDiff line change
@@ -171,18 +171,30 @@ function win:get_width()
171171
return vim.api.nvim_win_get_width(self:get_win()) + self:get_border_size().horizontal
172172
end
173173

174-
--- @return { bufnr: number, start_line: number, end_line: number, horizontal_offset: number }
175-
function win.get_screen_scroll_range()
176-
local bufnr = vim.api.nvim_win_get_buf(0)
177-
local line_count = vim.api.nvim_buf_line_count(bufnr)
178-
179-
-- Get the scrolled range (start and end line)
180-
local start_line = math.max(1, vim.fn.line('w0') - 1)
181-
local end_line = math.max(start_line, math.min(line_count, vim.fn.line('w$') + 1))
174+
--- Gets the cursor's distance from the top and bottom of the window
175+
--- @return { distance_from_top: number, distance_from_bottom: number }
176+
function win.get_cursor_screen_position()
177+
local win_height = vim.api.nvim_win_get_height(0)
178+
local cursor_line = vim.api.nvim_win_get_cursor(0)[1]
179+
180+
-- Calculate the visual distance from top of the window sinc the vim.fn.line()
181+
-- func gives the literal line number but there can be folds.
182+
-- HACK: ideally there's a more generic solution since vertical conceal
183+
-- will be added in the future
184+
local distance_from_top = 0
185+
local line = math.max(1, vim.fn.line('w0'))
186+
while line < cursor_line do
187+
distance_from_top = distance_from_top + 1
188+
if vim.fn.foldclosedend(line) ~= -1 then line = vim.fn.foldclosedend(line) end
189+
line = line + 1
190+
end
182191

183-
local horizontal_offset = vim.fn.winsaveview().leftcol
192+
local distance_from_bottom = win_height - distance_from_top - 1
184193

185-
return { bufnr = bufnr, start_line = start_line, end_line = end_line, horizontal_offset = horizontal_offset }
194+
return {
195+
distance_from_bottom = distance_from_bottom,
196+
distance_from_top = distance_from_top,
197+
}
186198
end
187199

188200
return win

lua/blink/cmp/windows/signature.lua

+3-4
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,12 @@ function signature.update_position(context)
104104
local direction = autocomplete_win_is_up and 's' or 'n'
105105

106106
local height = signature.win:get_height()
107-
local screen_height = vim.api.nvim_win_get_height(0)
108-
local screen_scroll_range = signature.win.get_screen_scroll_range()
107+
local cursor_screen_position = win.get_cursor_screen_position()
109108

110109
-- detect if there's space above/below the cursor
111110
local cursor_row = vim.api.nvim_win_get_cursor(0)[1]
112-
local is_space_below = screen_height - cursor_row - screen_scroll_range.start_line > height
113-
local is_space_above = cursor_row - screen_scroll_range.start_line > height
111+
local is_space_below = cursor_screen_position.distance_from_bottom > height
112+
local is_space_above = cursor_screen_position.distance_from_top > height
114113

115114
-- default to the user's preference but attempt to use the other options
116115
local row = direction == 's' and 1 or -height

0 commit comments

Comments
 (0)