Refactor get_active_entry and core.filter (#535)

* Refactor get_active_entry and core.filter

* Refactor source.lua
This commit is contained in:
hrsh7th
2021-11-17 22:38:56 +09:00
committed by GitHub
parent 17d57f96cc
commit 286b9f78d1
3 changed files with 29 additions and 68 deletions

View File

@@ -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
) )

View File

@@ -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')

View File

@@ -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)