From cd98b2acd540a517658ee163ffede0491f87ed58 Mon Sep 17 00:00:00 2001 From: L Lllvvuu Date: Tue, 12 Sep 2023 16:49:39 -0700 Subject: [PATCH] feat: config.view.entries.vertical_positioning = 'above'|'below' Works best with vim.opt.scrolloff = 999 Fixes: #495 --- lua/cmp/config/default.lua | 1 + lua/cmp/types/cmp.lua | 1 + lua/cmp/view/custom_entries_view.lua | 23 +++++++++++++---------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/lua/cmp/config/default.lua b/lua/cmp/config/default.lua index 3c020cd46..5552b9a28 100644 --- a/lua/cmp/config/default.lua +++ b/lua/cmp/config/default.lua @@ -94,6 +94,7 @@ return function() entries = { name = 'custom', selection_order = 'top_down', + vertical_positioning = 'below', }, docs = { auto_open = true, diff --git a/lua/cmp/types/cmp.lua b/lua/cmp/types/cmp.lua index a17409db5..d5b29f2ae 100644 --- a/lua/cmp/types/cmp.lua +++ b/lua/cmp/types/cmp.lua @@ -176,6 +176,7 @@ cmp.ItemField = { ---@class cmp.CustomEntriesViewConfig ---@field name 'custom' ---@field selection_order 'top_down'|'near_cursor' +---@field vertical_positioning 'above'|'below' ---@class cmp.NativeEntriesViewConfig ---@field name 'native' diff --git a/lua/cmp/view/custom_entries_view.lua b/lua/cmp/view/custom_entries_view.lua index a5eca58b1..65aebdea3 100644 --- a/lua/cmp/view/custom_entries_view.lua +++ b/lua/cmp/view/custom_entries_view.lua @@ -117,7 +117,8 @@ custom_entries_view.is_direction_top_down = function(self) end custom_entries_view.open = function(self, offset, entries) - local completion = config.get().window.completion + local c = config.get() + local completion = c.window.completion self.offset = offset self.entries = {} self.column_width = { abbr = 0, kind = 0, menu = 0 } @@ -161,12 +162,20 @@ custom_entries_view.open = function(self, offset, entries) local border_info = window.get_border_info({ style = completion }) local border_offset_row = border_info.top + border_info.bottom local border_offset_col = border_info.left + border_info.right - if math.floor(vim.o.lines * 0.5) <= row + border_offset_row and vim.o.lines - row - border_offset_row <= math.min(DEFAULT_HEIGHT, height) then + + local prefers_above = c.view.entries.vertical_positioning == 'above' + local cant_fit_at_bottom = vim.o.lines - row - border_offset_row <= math.min(DEFAULT_HEIGHT, height) + local cant_fit_at_top = row - border_offset_row <= math.min(DEFAULT_HEIGHT, height) + local should_position_above = cant_fit_at_bottom or (prefers_above and not cant_fit_at_top) + if should_position_above then + self.bottom_up = true height = math.min(height, row - 1) row = row - height - border_offset_row - 1 if row < 0 then height = height + row end + else + self.bottom_up = false end if math.floor(vim.o.columns * 0.5) <= col + border_offset_col and vim.o.columns - col - border_offset_col <= width then width = math.min(width, vim.o.columns - 1) @@ -176,12 +185,6 @@ custom_entries_view.open = function(self, offset, entries) end end - if pos[1] > row then - self.bottom_up = true - else - self.bottom_up = false - end - if not self:is_direction_top_down() then local n = #self.entries for i = 1, math.floor(n / 2) do @@ -208,9 +211,9 @@ custom_entries_view.open = function(self, offset, entries) }) -- always set cursor when starting. It will be adjusted on the call to _select vim.api.nvim_win_set_cursor(self.entries_win.win, { 1, 0 }) - if preselect_index > 0 and config.get().preselect == types.cmp.PreselectMode.Item then + if preselect_index > 0 and c.preselect == types.cmp.PreselectMode.Item then self:_select(preselect_index, { behavior = types.cmp.SelectBehavior.Select, active = false }) - elseif not string.match(config.get().completion.completeopt, 'noselect') then + elseif not string.match(c.completion.completeopt, 'noselect') then if self:is_direction_top_down() then self:_select(1, { behavior = types.cmp.SelectBehavior.Select, active = false }) else