@@ -12,6 +12,7 @@ local DEFAULT_HEIGHT = 10 -- @see https://github.com/vim/vim/blob/master/src/pop
1212
1313--- @class cmp.CustomEntriesView
1414--- @field private entries_win cmp.Window
15+ --- @field private ghost_text_view cmp.GhostTextView
1516--- @field private offset integer
1617--- @field private active boolean
1718--- @field private entries cmp.Entry[]
@@ -21,7 +22,7 @@ local custom_entries_view = {}
2122
2223custom_entries_view .ns = vim .api .nvim_create_namespace (' cmp.view.custom_entries_view' )
2324
24- custom_entries_view .new = function ()
25+ custom_entries_view .new = function (ghost_text_view )
2526 local self = setmetatable ({}, { __index = custom_entries_view })
2627
2728 self .entries_win = window .new ()
@@ -43,6 +44,7 @@ custom_entries_view.new = function()
4344 self .active = false
4445 self .entries = {}
4546 self .bottom_up = false
47+ self .ghost_text_view = ghost_text_view
4648
4749 autocmd .subscribe (
4850 ' CompleteChanged' ,
@@ -431,6 +433,55 @@ custom_entries_view._select = function(self, cursor, option)
431433 0 ,
432434 })
433435
436+ if not self .bottom_up then
437+ local info = self .entries_win :info ()
438+ local border_info = info .border_info
439+ local border_offset_row = border_info .top + border_info .bottom
440+ local row = api .get_screen_cursor ()[1 ]
441+
442+ -- If user specify 'noselect', select first entry
443+ local entry = self :get_selected_entry () or self :get_first_entry ()
444+ local should_move_up = self .ghost_text_view :has_multi_line (entry ) and row > self .entries_win :get_content_height () + border_offset_row
445+
446+ if should_move_up then
447+ self .bottom_up = true
448+
449+ -- This logic keeps the same as open()
450+ local height = vim .api .nvim_get_option_value (' pumheight' , {})
451+ height = height ~= 0 and height or # self .entries
452+ height = math.min (height , # self .entries )
453+ height = math.min (height , row - 1 )
454+
455+ row = row - height - border_offset_row - 1
456+ if row < 0 then
457+ height = height + row
458+ end
459+
460+ local completion = config .get ().window .completion
461+ local new_position = {
462+ style = ' minimal' ,
463+ relative = ' editor' ,
464+ row = math.max (0 , row ),
465+ height = height ,
466+ col = info .col ,
467+ width = info .width ,
468+ border = completion .border ,
469+ zindex = completion .zindex or 1001 ,
470+ }
471+ self .entries_win :open (new_position )
472+
473+ if not self :is_direction_top_down () then
474+ local n = # self .entries
475+ for i = 1 , math.floor (n / 2 ) do
476+ self .entries [i ], self .entries [n - i + 1 ] = self .entries [n - i + 1 ], self .entries [i ]
477+ end
478+ self :_select (# self .entries - cursor + 1 , option )
479+ else
480+ self :_select (cursor , option )
481+ end
482+ end
483+ end
484+
434485 if is_insert then
435486 self :_insert (self .entries [cursor ] and self .entries [cursor ]:get_vim_item (self .offset ).word or self .prefix )
436487 end
0 commit comments