Refactor get_active_entry and core.filter (#535)
* Refactor get_active_entry and core.filter * Refactor source.lua
This commit is contained in:
@@ -14,8 +14,8 @@ local api = require('cmp.utils.api')
|
||||
local event = require('cmp.utils.event')
|
||||
|
||||
local SOURCE_TIMEOUT = 500
|
||||
local THROTTLE_TIME = 120
|
||||
local DEBOUNCE_TIME = 20
|
||||
local THROTTLE_TIME = 100
|
||||
local DEBOUNCE_TIME = 50
|
||||
|
||||
---@class cmp.Core
|
||||
---@field public suspending boolean
|
||||
@@ -250,32 +250,22 @@ end
|
||||
---Update completion menu
|
||||
core.filter = async.throttle(
|
||||
vim.schedule_wrap(function(self)
|
||||
if not api.is_suitable_mode() then
|
||||
local ignore = false
|
||||
ignore = ignore or not api.is_suitable_mode()
|
||||
ignore = ignore or self.view:get_active_entry()
|
||||
if ignore then
|
||||
return
|
||||
end
|
||||
if self.view:get_active_entry() ~= nil then
|
||||
return
|
||||
end
|
||||
local ctx = self:get_context()
|
||||
|
||||
-- To wait for processing source for that's timeout.
|
||||
local sources = {}
|
||||
for _, s in ipairs(self:get_sources({ source.SourceStatus.FETCHING, source.SourceStatus.COMPLETED })) do
|
||||
local time = SOURCE_TIMEOUT - s:get_fetching_time()
|
||||
if not s.incomplete and time > 0 then
|
||||
if #sources == 0 then
|
||||
self.filter.stop()
|
||||
self.filter.timeout = time + 1
|
||||
self:filter()
|
||||
return
|
||||
end
|
||||
break
|
||||
end
|
||||
table.insert(sources, s)
|
||||
end
|
||||
self.filter.timeout = THROTTLE_TIME
|
||||
|
||||
self.view:open(ctx, sources)
|
||||
self.view:open(self:get_context(), sources)
|
||||
end),
|
||||
THROTTLE_TIME
|
||||
)
|
||||
|
||||
@@ -229,20 +229,15 @@ end
|
||||
---@return boolean Return true if not trigger completion.
|
||||
source.complete = function(self, ctx, callback)
|
||||
local offset = ctx:get_offset(self:get_keyword_pattern())
|
||||
if ctx.cursor.col <= offset then
|
||||
self:reset()
|
||||
end
|
||||
|
||||
-- NOTE: This implementation is nvim-cmp specific.
|
||||
-- We trigger new completion after core.confirm but we check only the symbol trigger_character in this case.
|
||||
local before_char = string.sub(ctx.cursor_before_line, -1)
|
||||
local before_char_iw = string.match(ctx.cursor_before_line, '(.)%s*$') or before_char
|
||||
|
||||
if ctx:get_reason() == types.cmp.ContextReason.TriggerOnly then
|
||||
if string.match(before_char, '^%a+$') then
|
||||
before_char = string.match(ctx.cursor_before_line, '(.)%s*$')
|
||||
if not char.is_symbol(string.byte(before_char)) then
|
||||
before_char = ''
|
||||
end
|
||||
if string.match(before_char_iw, '^%a+$') then
|
||||
before_char_iw = ''
|
||||
end
|
||||
end
|
||||
|
||||
local completion_context
|
||||
@@ -256,11 +251,6 @@ source.complete = function(self, ctx, callback)
|
||||
triggerKind = types.lsp.CompletionTriggerKind.TriggerCharacter,
|
||||
triggerCharacter = before_char,
|
||||
}
|
||||
elseif vim.tbl_contains(self:get_trigger_characters(), before_char_iw) then
|
||||
completion_context = {
|
||||
triggerKind = types.lsp.CompletionTriggerKind.TriggerCharacter,
|
||||
triggerCharacter = before_char_iw,
|
||||
}
|
||||
elseif ctx:get_reason() ~= types.cmp.ContextReason.TriggerOnly then
|
||||
if self:get_keyword_length() <= (ctx.cursor.col - offset) then
|
||||
if self.incomplete and self.context.cursor.col ~= ctx.cursor.col then
|
||||
@@ -279,7 +269,7 @@ source.complete = function(self, ctx, callback)
|
||||
end
|
||||
|
||||
if not completion_context then
|
||||
if ctx:get_reason() == types.cmp.ContextReason.TriggerOnly then
|
||||
if not vim.tbl_contains({ self.request_offset, self.offset }, offset) then
|
||||
self:reset()
|
||||
end
|
||||
debug.log(self:get_debug_name(), 'skip completion')
|
||||
|
||||
@@ -14,6 +14,7 @@ local DEFAULT_HEIGHT = 10 -- @see https://github.com/vim/vim/blob/master/src/pop
|
||||
---@class cmp.CustomEntriesView
|
||||
---@field private entries_win cmp.Window
|
||||
---@field private offset number
|
||||
---@field private active boolean
|
||||
---@field private entries cmp.Entry[]
|
||||
---@field private column_width any
|
||||
---@field public event cmp.Event
|
||||
@@ -33,6 +34,7 @@ custom_entries_view.new = function()
|
||||
self.entries_win:option('winhighlight', 'Normal:Pmenu,FloatBorder:Pmenu,CursorLine:PmenuSel,Search:None')
|
||||
self.event = event.new()
|
||||
self.offset = -1
|
||||
self.active = false
|
||||
self.entries = {}
|
||||
|
||||
autocmd.subscribe(
|
||||
@@ -93,10 +95,7 @@ custom_entries_view.ready = function()
|
||||
end
|
||||
|
||||
custom_entries_view.on_change = function(self)
|
||||
if self:visible() and self:get_active_entry() then
|
||||
self.entries_win:option('cursorline', false)
|
||||
vim.api.nvim_win_set_cursor(self.entries_win.win, { 1, 1 })
|
||||
end
|
||||
self.active = false
|
||||
end
|
||||
|
||||
custom_entries_view.open = function(self, offset, entries)
|
||||
@@ -161,22 +160,19 @@ custom_entries_view.open = function(self, offset, entries)
|
||||
height = height,
|
||||
zindex = 1001,
|
||||
})
|
||||
vim.api.nvim_win_set_cursor(self.entries_win.win, { 1, 1 })
|
||||
self.entries_win:option('cursorline', false)
|
||||
|
||||
if preselect > 0 and config.get().preselect == types.cmp.PreselectMode.Item then
|
||||
self:preselect(preselect)
|
||||
self:_select(preselect, { behavior = types.cmp.SelectBehavior.Select })
|
||||
elseif not string.match(config.get().completion.completeopt, 'noselect') then
|
||||
self:preselect(1)
|
||||
self:_select(1, { behavior = types.cmp.SelectBehavior.Select })
|
||||
else
|
||||
self:draw()
|
||||
self:_select(0, { behavior = types.cmp.SelectBehavior.Select })
|
||||
end
|
||||
self.event:emit('change')
|
||||
end
|
||||
|
||||
custom_entries_view.close = function(self)
|
||||
self.prefix = nil
|
||||
self.offset = -1
|
||||
self.active = false
|
||||
self.entries = {}
|
||||
self.entries_win:close()
|
||||
end
|
||||
@@ -227,19 +223,8 @@ custom_entries_view.info = function(self)
|
||||
return self.entries_win:info()
|
||||
end
|
||||
|
||||
custom_entries_view.preselect = function(self, index)
|
||||
if self:visible() then
|
||||
if index <= #self.entries then
|
||||
self.entries_win:option('cursorline', true)
|
||||
vim.api.nvim_win_set_cursor(self.entries_win.win, { index, 1 })
|
||||
self.entries_win:update()
|
||||
self:draw()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
custom_entries_view.select_next_item = function(self, option)
|
||||
if self.entries_win:visible() then
|
||||
if self:visible() then
|
||||
local cursor = vim.api.nvim_win_get_cursor(self.entries_win.win)[1] + 1
|
||||
if not self.entries_win:option('cursorline') then
|
||||
cursor = 1
|
||||
@@ -251,7 +236,7 @@ custom_entries_view.select_next_item = function(self, option)
|
||||
end
|
||||
|
||||
custom_entries_view.select_prev_item = function(self, option)
|
||||
if self.entries_win:visible() then
|
||||
if self:visible() then
|
||||
local cursor = vim.api.nvim_win_get_cursor(self.entries_win.win)[1] - 1
|
||||
if not self.entries_win:option('cursorline') then
|
||||
cursor = #self.entries
|
||||
@@ -261,36 +246,32 @@ custom_entries_view.select_prev_item = function(self, option)
|
||||
end
|
||||
|
||||
custom_entries_view.get_first_entry = function(self)
|
||||
if self.entries_win:visible() then
|
||||
if self:visible() then
|
||||
return self.entries[1]
|
||||
end
|
||||
end
|
||||
|
||||
custom_entries_view.get_selected_entry = function(self)
|
||||
if self.entries_win:visible() and self.entries_win:option('cursorline') then
|
||||
if self:visible() and self.entries_win:option('cursorline') then
|
||||
return self.entries[vim.api.nvim_win_get_cursor(self.entries_win.win)[1]]
|
||||
end
|
||||
end
|
||||
|
||||
custom_entries_view.get_active_entry = function(self)
|
||||
if self.entries_win:visible() and self.entries_win:option('cursorline') then
|
||||
local cursor = vim.api.nvim_win_get_cursor(self.entries_win.win)
|
||||
if cursor[2] == 0 then
|
||||
return self:get_selected_entry()
|
||||
end
|
||||
if self:visible() and self.active then
|
||||
return self:get_selected_entry()
|
||||
end
|
||||
end
|
||||
|
||||
custom_entries_view._select = function(self, cursor, option)
|
||||
local is_insert = (option.behavior or types.cmp.SelectBehavior.Insert) == types.cmp.SelectBehavior.Insert
|
||||
if is_insert then
|
||||
if vim.api.nvim_win_get_cursor(self.entries_win.win)[2] == 1 then
|
||||
self.prefix = string.sub(api.get_current_line(), self.offset, api.get_cursor()[2]) or ''
|
||||
end
|
||||
if is_insert and not self.active then
|
||||
self.prefix = string.sub(api.get_current_line(), self.offset, api.get_cursor()[2]) or ''
|
||||
end
|
||||
|
||||
self.active = cursor > 0 and is_insert
|
||||
self.entries_win:option('cursorline', cursor > 0)
|
||||
vim.api.nvim_win_set_cursor(self.entries_win.win, { math.max(cursor, 1), is_insert and 0 or 1 })
|
||||
vim.api.nvim_win_set_cursor(self.entries_win.win, { math.max(cursor, 1), 0 })
|
||||
|
||||
if is_insert then
|
||||
self:_insert(self.entries[cursor] and self.entries[cursor]:get_vim_item(self.offset).word or self.prefix)
|
||||
|
||||
Reference in New Issue
Block a user