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 event = require('cmp.utils.event')
|
||||||
|
|
||||||
local SOURCE_TIMEOUT = 500
|
local SOURCE_TIMEOUT = 500
|
||||||
local THROTTLE_TIME = 120
|
local THROTTLE_TIME = 100
|
||||||
local DEBOUNCE_TIME = 20
|
local DEBOUNCE_TIME = 50
|
||||||
|
|
||||||
---@class cmp.Core
|
---@class cmp.Core
|
||||||
---@field public suspending boolean
|
---@field public suspending boolean
|
||||||
@@ -250,32 +250,22 @@ end
|
|||||||
---Update completion menu
|
---Update completion menu
|
||||||
core.filter = async.throttle(
|
core.filter = async.throttle(
|
||||||
vim.schedule_wrap(function(self)
|
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
|
return
|
||||||
end
|
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 = {}
|
local sources = {}
|
||||||
for _, s in ipairs(self:get_sources({ source.SourceStatus.FETCHING, source.SourceStatus.COMPLETED })) do
|
for _, s in ipairs(self:get_sources({ source.SourceStatus.FETCHING, source.SourceStatus.COMPLETED })) do
|
||||||
local time = SOURCE_TIMEOUT - s:get_fetching_time()
|
local time = SOURCE_TIMEOUT - s:get_fetching_time()
|
||||||
if not s.incomplete and time > 0 then
|
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
|
break
|
||||||
end
|
end
|
||||||
table.insert(sources, s)
|
table.insert(sources, s)
|
||||||
end
|
end
|
||||||
self.filter.timeout = THROTTLE_TIME
|
self.view:open(self:get_context(), sources)
|
||||||
|
|
||||||
self.view:open(ctx, sources)
|
|
||||||
end),
|
end),
|
||||||
THROTTLE_TIME
|
THROTTLE_TIME
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -229,20 +229,15 @@ end
|
|||||||
---@return boolean Return true if not trigger completion.
|
---@return boolean Return true if not trigger completion.
|
||||||
source.complete = function(self, ctx, callback)
|
source.complete = function(self, ctx, callback)
|
||||||
local offset = ctx:get_offset(self:get_keyword_pattern())
|
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 = 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 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 = ''
|
before_char = ''
|
||||||
end
|
end
|
||||||
if string.match(before_char_iw, '^%a+$') then
|
|
||||||
before_char_iw = ''
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local completion_context
|
local completion_context
|
||||||
@@ -256,11 +251,6 @@ source.complete = function(self, ctx, callback)
|
|||||||
triggerKind = types.lsp.CompletionTriggerKind.TriggerCharacter,
|
triggerKind = types.lsp.CompletionTriggerKind.TriggerCharacter,
|
||||||
triggerCharacter = before_char,
|
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
|
elseif ctx:get_reason() ~= types.cmp.ContextReason.TriggerOnly then
|
||||||
if self:get_keyword_length() <= (ctx.cursor.col - offset) then
|
if self:get_keyword_length() <= (ctx.cursor.col - offset) then
|
||||||
if self.incomplete and self.context.cursor.col ~= ctx.cursor.col then
|
if self.incomplete and self.context.cursor.col ~= ctx.cursor.col then
|
||||||
@@ -279,7 +269,7 @@ source.complete = function(self, ctx, callback)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not completion_context then
|
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()
|
self:reset()
|
||||||
end
|
end
|
||||||
debug.log(self:get_debug_name(), 'skip completion')
|
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
|
---@class cmp.CustomEntriesView
|
||||||
---@field private entries_win cmp.Window
|
---@field private entries_win cmp.Window
|
||||||
---@field private offset number
|
---@field private offset number
|
||||||
|
---@field private active boolean
|
||||||
---@field private entries cmp.Entry[]
|
---@field private entries cmp.Entry[]
|
||||||
---@field private column_width any
|
---@field private column_width any
|
||||||
---@field public event cmp.Event
|
---@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.entries_win:option('winhighlight', 'Normal:Pmenu,FloatBorder:Pmenu,CursorLine:PmenuSel,Search:None')
|
||||||
self.event = event.new()
|
self.event = event.new()
|
||||||
self.offset = -1
|
self.offset = -1
|
||||||
|
self.active = false
|
||||||
self.entries = {}
|
self.entries = {}
|
||||||
|
|
||||||
autocmd.subscribe(
|
autocmd.subscribe(
|
||||||
@@ -93,10 +95,7 @@ custom_entries_view.ready = function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
custom_entries_view.on_change = function(self)
|
custom_entries_view.on_change = function(self)
|
||||||
if self:visible() and self:get_active_entry() then
|
self.active = false
|
||||||
self.entries_win:option('cursorline', false)
|
|
||||||
vim.api.nvim_win_set_cursor(self.entries_win.win, { 1, 1 })
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
custom_entries_view.open = function(self, offset, entries)
|
custom_entries_view.open = function(self, offset, entries)
|
||||||
@@ -161,22 +160,19 @@ custom_entries_view.open = function(self, offset, entries)
|
|||||||
height = height,
|
height = height,
|
||||||
zindex = 1001,
|
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
|
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
|
elseif not string.match(config.get().completion.completeopt, 'noselect') then
|
||||||
self:preselect(1)
|
self:_select(1, { behavior = types.cmp.SelectBehavior.Select })
|
||||||
else
|
else
|
||||||
self:draw()
|
self:_select(0, { behavior = types.cmp.SelectBehavior.Select })
|
||||||
end
|
end
|
||||||
self.event:emit('change')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
custom_entries_view.close = function(self)
|
custom_entries_view.close = function(self)
|
||||||
self.prefix = nil
|
self.prefix = nil
|
||||||
self.offset = -1
|
self.offset = -1
|
||||||
|
self.active = false
|
||||||
self.entries = {}
|
self.entries = {}
|
||||||
self.entries_win:close()
|
self.entries_win:close()
|
||||||
end
|
end
|
||||||
@@ -227,19 +223,8 @@ custom_entries_view.info = function(self)
|
|||||||
return self.entries_win:info()
|
return self.entries_win:info()
|
||||||
end
|
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)
|
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
|
local cursor = vim.api.nvim_win_get_cursor(self.entries_win.win)[1] + 1
|
||||||
if not self.entries_win:option('cursorline') then
|
if not self.entries_win:option('cursorline') then
|
||||||
cursor = 1
|
cursor = 1
|
||||||
@@ -251,7 +236,7 @@ custom_entries_view.select_next_item = function(self, option)
|
|||||||
end
|
end
|
||||||
|
|
||||||
custom_entries_view.select_prev_item = function(self, option)
|
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
|
local cursor = vim.api.nvim_win_get_cursor(self.entries_win.win)[1] - 1
|
||||||
if not self.entries_win:option('cursorline') then
|
if not self.entries_win:option('cursorline') then
|
||||||
cursor = #self.entries
|
cursor = #self.entries
|
||||||
@@ -261,36 +246,32 @@ custom_entries_view.select_prev_item = function(self, option)
|
|||||||
end
|
end
|
||||||
|
|
||||||
custom_entries_view.get_first_entry = function(self)
|
custom_entries_view.get_first_entry = function(self)
|
||||||
if self.entries_win:visible() then
|
if self:visible() then
|
||||||
return self.entries[1]
|
return self.entries[1]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
custom_entries_view.get_selected_entry = function(self)
|
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]]
|
return self.entries[vim.api.nvim_win_get_cursor(self.entries_win.win)[1]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
custom_entries_view.get_active_entry = function(self)
|
custom_entries_view.get_active_entry = function(self)
|
||||||
if self.entries_win:visible() and self.entries_win:option('cursorline') then
|
if self:visible() and self.active then
|
||||||
local cursor = vim.api.nvim_win_get_cursor(self.entries_win.win)
|
|
||||||
if cursor[2] == 0 then
|
|
||||||
return self:get_selected_entry()
|
return self:get_selected_entry()
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
custom_entries_view._select = function(self, cursor, option)
|
custom_entries_view._select = function(self, cursor, option)
|
||||||
local is_insert = (option.behavior or types.cmp.SelectBehavior.Insert) == types.cmp.SelectBehavior.Insert
|
local is_insert = (option.behavior or types.cmp.SelectBehavior.Insert) == types.cmp.SelectBehavior.Insert
|
||||||
if is_insert then
|
if is_insert and not self.active 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 ''
|
self.prefix = string.sub(api.get_current_line(), self.offset, api.get_cursor()[2]) or ''
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
|
self.active = cursor > 0 and is_insert
|
||||||
self.entries_win:option('cursorline', cursor > 0)
|
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
|
if is_insert then
|
||||||
self:_insert(self.entries[cursor] and self.entries[cursor]:get_vim_item(self.offset).word or self.prefix)
|
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