From abdf4b8e4bf664923ed0dc3d6287f57ef87e7cc7 Mon Sep 17 00:00:00 2001 From: hrsh7th Date: Thu, 23 Sep 2021 17:09:18 +0900 Subject: [PATCH] compat --- lua/cmp/core.lua | 6 +- lua/cmp/view.lua | 50 +++--- lua/cmp/view/entries_view.lua | 221 --------------------------- lua/cmp/view/native_entries_view.lua | 16 +- 4 files changed, 42 insertions(+), 251 deletions(-) delete mode 100644 lua/cmp/view/entries_view.lua diff --git a/lua/cmp/core.lua b/lua/cmp/core.lua index 1bb771554..3ff26b8e4 100644 --- a/lua/cmp/core.lua +++ b/lua/cmp/core.lua @@ -150,7 +150,11 @@ end ---Check auto-completion core.on_change = function(self, event) - if self.suspending or self.view:active() then + local ignore = false + ignore = ignore or self.suspending + ignore = ignore or (vim.fn.pumvisible() == 1 and (vim.v.completed_item).word) + if ignore then + self:get_context({ reason = types.cmp.ContextReason.Auto }) return end diff --git a/lua/cmp/view.lua b/lua/cmp/view.lua index d5ae256d5..754338f18 100644 --- a/lua/cmp/view.lua +++ b/lua/cmp/view.lua @@ -3,13 +3,13 @@ local async = require('cmp.utils.async') local event = require('cmp.utils.event') local keymap = require('cmp.utils.keymap') local docs_view = require('cmp.view.docs_view') -local entries_view = require('cmp.view.entries_view') +local custom_entries_view = require('cmp.view.custom_entries_view') local native_entries_view = require('cmp.view.native_entries_view') local ghost_text_view = require('cmp.view.ghost_text_view') ---@class cmp.View ---@field public event cmp.Event ----@field public resolve_dedup cmp.AsyncDedup +---@field public change_dedup cmp.AsyncDedup ---@field public entries_view cmp.EntriesView ---@field public docs_view cmp.DocsView ---@field public ghost_text_view cmp.GhostTextView @@ -18,8 +18,8 @@ local view = {} ---Create menu view.new = function() local self = setmetatable({}, { __index = view }) - self.resolve_dedup = async.dedup() - self.entries_view = entries_view.new() + self.change_dedup = async.dedup() + self.entries_view = custom_entries_view.new() self.entries_view = native_entries_view.new() self.docs_view = docs_view.new() self.ghost_text_view = ghost_text_view.new() @@ -91,10 +91,6 @@ view.visible = function(self) return self.entries_view:visible() end -view.active = function(self) - return self.entries_view:active() -end - view.scroll_docs = function(self, delta) self.docs_view:scroll(delta) end @@ -107,34 +103,42 @@ view.select_prev_item = function(self) self.entries_view:select_prev_item() end +---Get first entry +---@param self cmp.Entry|nil +view.get_first_entry = function(self) + return self.entries_view:get_first_entry() +end + ---Get current selected entry ---@return cmp.Entry|nil view.get_selected_entry = function(self) return self.entries_view:get_selected_entry() end ----Get first entry ----@param self cmp.Entry|nil -view.get_first_entry = function(self) - return self.entries_view:get_first_entry() +view.get_active_entry = function(self) + return self.entries_view:get_active_entry() end ---On entry change view.on_entry_change = function(self) local e = self:get_selected_entry() - if e then - for _, c in ipairs(config.get().confirmation.get_commit_characters(e:get_commit_characters())) do - keymap.listen('i', c, function(...) - self.event:emit('keymap', ...) + self.ghost_text_view:show(e or self:get_first_entry()) + + vim.schedule(self.change_dedup(function() + if e then + for _, c in ipairs(config.get().confirmation.get_commit_characters(e:get_commit_characters())) do + keymap.listen('i', c, function(...) + self.event:emit('keymap', ...) + end) + end + e:resolve(function() + self.docs_view:open(e, self.entries_view:info()) end) + else + self.docs_view:close() end - e:resolve(self.resolve_dedup(function() - self.docs_view:open(e, self.entries_view:info()) - end)) - else - self.docs_view:close() - end - self.ghost_text_view:show(e or self:get_first_entry()) + end)) end return view + diff --git a/lua/cmp/view/entries_view.lua b/lua/cmp/view/entries_view.lua deleted file mode 100644 index ec709d9a9..000000000 --- a/lua/cmp/view/entries_view.lua +++ /dev/null @@ -1,221 +0,0 @@ -local event = require('cmp.utils.event') -local window = require('cmp.utils.window') - ----@class cmp.EntriesView ----@field public entries_win cmp.Window ----@field public offset number ----@field public entries cmp.Entry[] ----@field public marks table[] ----@field public event cmp.Event -local entries_view = {} - -entries_view.ns = vim.api.nvim_create_namespace('cmp.view.entries_view') - -entries_view.new = function() - local self = setmetatable({}, { __index = entries_view }) - self.entries_win = window.new() - self.entries_win:option('conceallevel', 2) - self.entries_win:option('concealcursor', 'n') - self.entries_win:option('foldenable', false) - self.entries_win:option('wrap', false) - self.entries_win:option('scrolloff', 0) - self.entries_win:option('winhighlight', 'Normal:Pmenu,FloatBorder:Pmenu,CursorLine:PmenuSel') - self.event = event.new() - self.offset = -1 - self.entries = {} - self.marks = {} - - vim.api.nvim_set_decoration_provider(entries_view.ns, { - on_win = function(_, winid) - return winid == self.entries_win.win - end, - on_line = function(_, winid, bufnr, row) - if winid == self.entries_win.win then - for _, mark in ipairs(self.marks[row + 1]) do - vim.api.nvim_buf_set_extmark(bufnr, entries_view.ns, row, mark.col, { - end_line = row, - end_col = mark.col + mark.length, - hl_group = mark.hl_group, - hl_mode = 'combine', - ephemeral = true, - }) - end - for _, m in ipairs(self.entries[row + 1].matches or {}) do - vim.api.nvim_buf_set_extmark(bufnr, entries_view.ns, row, m.word_match_start, { - end_line = row, - end_col = m.word_match_end + 1, - hl_group = m.fuzzy and 'CmpItemAbbrMatchFuzzy' or 'CmpItemAbbrMatch', - hl_mode = 'combine', - ephemeral = true, - }) - end - end - end, - }) - - return self -end - -entries_view.open = function(self, offset, entries) - self.offset = offset - self.entries = {} - self.marks = {} - - if #entries > 0 then - local dedup = {} - local abbrs = { width = 0, texts = {}, widths = {}, hl_groups = {} } - local kinds = { width = 0, texts = {}, widths = {}, hl_groups = {} } - local menus = { width = 0, texts = {}, widths = {}, hl_groups = {} } - for _, e in ipairs(entries) do - local i = #self.entries + 1 - local item = e:get_vim_item(offset) - if item.dup == 1 or not dedup[item.abbr] then - dedup[item.abbr] = true - - table.insert(self.entries, e) - - abbrs.texts[i] = item.abbr - abbrs.hl_groups[i] = e:is_deprecated() and 'CmpItemAbbrDeprecated' or 'CmpItemAbbr' - abbrs.widths[i] = vim.str_utfindex(abbrs.texts[i]) - abbrs.width = math.max(abbrs.width, abbrs.widths[i]) - - kinds.texts[i] = (item.kind or '') - kinds.hl_groups[i] = 'CmpItemKind' - kinds.widths[i] = vim.str_utfindex(kinds.texts[i]) - kinds.width = math.max(kinds.width, kinds.widths[i]) - - menus.texts[i] = (item.menu or '') - menus.widths[i] = vim.str_utfindex(kinds.texts[i]) - menus.width = math.max(kinds.width, kinds.widths[i]) - menus.hl_groups[i] = 'CmpItemMenu' - end - end - - local lines = {} - local width = 0 - for i = 1, #self.entries do - self.marks[i] = {} - local off = 1 - local parts = { '' } - for _, part in ipairs({ abbrs, kinds, menus }) do - if #part.texts[i] > 0 then - local text = part.texts[i] .. string.rep(' ', part.width - part.widths[i]) - table.insert(parts, text) - table.insert(self.marks[i], { - col = off, - length = #part.texts[i], - hl_group = part.hl_groups[i], - }) - off = off + #text + 1 - end - end - table.insert(parts, '') - lines[i] = table.concat(parts, ' ') - width = math.max(width, vim.str_utfindex(lines[i])) - end - vim.api.nvim_buf_set_lines(self.entries_win.buf, 0, -1, false, lines) - - local height = vim.api.nvim_get_option('pumheight') - height = height == 0 and #self.entries or height - height = math.min(height, #self.entries) - height = math.min(height, vim.o.lines - vim.fn.screenrow()) - - if width < 1 or height < 1 then - return - end - - local delta = vim.api.nvim_win_get_cursor(0)[2] + 1 - self.offset - self.entries_win:open({ - relative = 'editor', - style = 'minimal', - row = vim.fn.screenrow(), - col = vim.fn.screencol() - 1 - delta - 1, - width = width, - height = height, - zindex = 1001 - }) - vim.api.nvim_win_set_cursor(self.entries_win.win, { 1, 0 }) - self.entries_win:option('cursorline', false) - else - self:close() - end - self.event:emit('change') -end - -entries_view.close = function(self) - self.entries_win:close() -end - -entries_view.visible = function(self) - return self.entries_win:visible() -end - -entries_view.info = function(self) - return self.entries_win:info() -end - -entries_view.select_next_item = function(self) - if self.entries_win:visible() then - local cursor = vim.api.nvim_win_get_cursor(self.entries_win.win)[1] - local word = self.prefix - if not self.entries_win:option('cursorline') then - self.prefix = string.sub(vim.api.nvim_get_current_line(), self.offset, vim.api.nvim_win_get_cursor(0)[2]) - self.entries_win:option('cursorline', true) - vim.api.nvim_win_set_cursor(self.entries_win.win, { 1, 0 }) - word = self.entries[1]:get_word() - elseif cursor == #self.entries then - self.entries_win:option('cursorline', false) - vim.api.nvim_win_set_cursor(self.entries_win.win, { 1, 0 }) - else - self.entries_win:option('cursorline', true) - vim.api.nvim_win_set_cursor(self.entries_win.win, { cursor + 1, 0 }) - word = self.entries[cursor + 1]:get_word() - end - self:insert(word) - self.entries_win:update() - self.event:emit('change') - end -end - -entries_view.select_prev_item = function(self) - if self.entries_win:visible() then - local cursor = vim.api.nvim_win_get_cursor(self.entries_win.win)[1] - local word = self.prefix - if not self.entries_win:option('cursorline') then - self.prefix = string.sub(vim.api.nvim_get_current_line(), self.offset, vim.api.nvim_win_get_cursor(0)[2]) - self.entries_win:option('cursorline', true) - vim.api.nvim_win_set_cursor(self.entries_win.win, { #self.entries, 0 }) - word = self.entries[#self.entries]:get_word() - elseif cursor == 1 then - self.entries_win:option('cursorline', false) - vim.api.nvim_win_set_cursor(self.entries_win.win, { 1, 0 }) - else - self.entries_win:option('cursorline', true) - vim.api.nvim_win_set_cursor(self.entries_win.win, { cursor - 1, 0 }) - word = self.entries[cursor - 1]:get_word() - end - self:insert(word) - self.entries_win:update() - self.event:emit('change') - end -end - -entries_view.get_first_entry = function(self) - if self.entries_win:visible() then - return self.entries[1] - end -end - -entries_view.get_selected_entry = function(self) - if self.entries_win:visible() and self.entries_win:option('cursorline') then - return self.entries[vim.api.nvim_win_get_cursor(self.entries_win.win)[1]] - end -end - -entries_view.insert = function(self, word) - local cursor = vim.api.nvim_win_get_cursor(0) - vim.api.nvim_buf_set_text(0, cursor[1] - 1, self.offset - 1, cursor[1] - 1, cursor[2], { word }) - vim.api.nvim_win_set_cursor(0, { cursor[1], self.offset + #word - 1 }) -end - -return entries_view diff --git a/lua/cmp/view/native_entries_view.lua b/lua/cmp/view/native_entries_view.lua index 8952a4e97..e6dd8a2f6 100644 --- a/lua/cmp/view/native_entries_view.lua +++ b/lua/cmp/view/native_entries_view.lua @@ -11,9 +11,9 @@ local native_entries_view = {} native_entries_view.new = function() local self = setmetatable({}, { __index = native_entries_view }) self.event = event.new() - autocmd.subscribe('CompleteChanged', vim.schedule(function() + autocmd.subscribe('CompleteChanged', function() self.event:emit('change') - end)) + end) return self end @@ -48,10 +48,6 @@ native_entries_view.visible = function(_) return vim.fn.pumvisible() == 1 end -native_entries_view.active = function(self) - return (vim.v.completed_item or {}).word and self:visible() -end - native_entries_view.info = function(self) if self:visible() then local info = vim.fn.pum_getpos() @@ -91,5 +87,13 @@ native_entries_view.get_selected_entry = function(self) end end +native_entries_view.get_active_entry = function(self) + if self:visible() then + if (vim.v.completed_item or {}).word then + return self:get_selected_entry() + end + end +end + return native_entries_view