Files
nvim-cmp/lua/cmp/view.lua
hrsh7th ada9ddeff7 Use floating window for completion menus (#224)
* WIP

* WIP

* Fix #226

* Insert text

* Emulate vim native

* テキトウ

* Tekito

* Move scrollbar impl

* aaa

* Ignore unexpected event

* fix

* fix scroll

* Refactor (conflict...)

* Fix bug

* Positive integer

* Refactor a bit

* Fix for pumheight=0

* fx

* Improve matching highlight

* Improve colorscheme handling

* fmt

* Add cmp.visible

* Fix pum pos

* ABBR_MARGIN

* Fix cel calculation

* up

* refactor

* fix

* a

* a

* compat

* Remove current completion state

* Fix ghost text

* Add feature toggle

* highlight customization

* Update

* Add breaking change announcement

* Add README.md

* Remove unused function

* extmark ephemeral ghost text

* Support native comp

* Fix docs  pos

* a

* Remove if native menu visible

* theme async

* Improvement idea: option to disables insert on select item (#240)

* use ghost text instead of insertion on prev/next item

* add disables_insert_on_selection option

* move disable_insert_on_select option as argumet on

* update README

* use an enum behavior to disable insert on select

* Adopt contribution

* Preselect

* Improve

* Change configuration option

* a

* Improve

* Improve

* Implement proper <C-e> behavior to native/custom

* Support <C-c> maybe

* Improve docs view

* Improve

* Avoid syntax leak

* TODO: refactor

* Fix

* Revert win pos

* fmt

* ghost text remaining

* Don't use italic by default

* bottom

* dedup by label

* Ignore events

* up

* Hacky native view partial support

* up

* perf

* improve

* more cache

* fmt

* Fix format option

* fmt

* recheck

* Fix

* Improve

* Improve

* compat

* implement redraw

* improve

* up

* fmt/lint

* immediate ghost text

* source timeout

* up

* Support multibyte

* disable highlight

* up

* improve

* fmt

* fmt

* fix

* fix

* up

* up

* Use screenpos

* Add undojoin check

* Fix height

* matcher bug

* Fix dot-repeat

* Remove undojoin

* macro

* Support dot-repeat

* MacroSafe

* Default item count is 200

* fmt

Co-authored-by: Eric Puentes <eric.puentes@mercadolibre.com.co>
2021-10-08 18:27:33 +09:00

207 lines
5.3 KiB
Lua

local config = require('cmp.config')
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 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 private resolve_dedup cmp.AsyncDedup
---@field private native_entries_view cmp.NativeEntriesView
---@field private custom_entries_view cmp.CustomEntriesView
---@field private change_dedup cmp.AsyncDedup
---@field private docs_view cmp.DocsView
---@field private ghost_text_view cmp.GhostTextView
local view = {}
---Create menu
view.new = function()
local self = setmetatable({}, { __index = view })
self.resolve_dedup = async.dedup()
self.custom_entries_view = custom_entries_view.new()
self.native_entries_view = native_entries_view.new()
self.docs_view = docs_view.new()
self.ghost_text_view = ghost_text_view.new()
self.event = event.new()
return self
end
---Return the view components are available or not.
---@return boolean
view.ready = function(self)
return self:_get_entries_view():ready()
end
---Redraw menu.
view.redraw = function(self)
self:_get_entries_view():redraw()
end
---Open menu
---@param ctx cmp.Context
---@param sources cmp.Source[]
view.open = function(self, ctx, sources)
local entries = {}
-- check the source triggered by character
local has_triggered_by_symbol_source = false
for _, s in ipairs(sources) do
if #s:get_entries(ctx) > 0 then
if s.is_triggered_by_symbol then
has_triggered_by_symbol_source = true
break
end
end
end
-- create filtered entries.
local offset = ctx.cursor.col
for i, s in ipairs(sources) do
if s.offset <= offset then
if not has_triggered_by_symbol_source or s.is_triggered_by_symbol then
-- source order priority bonus.
local priority = s:get_config().priority or ((#sources - (i - 1)) * config.get().sorting.priority_weight)
for _, e in ipairs(s:get_entries(ctx)) do
e.score = e.score + priority
table.insert(entries, e)
offset = math.min(offset, e:get_offset())
end
end
end
end
-- sort.
local comparetors = config.get().sorting.comparators
table.sort(entries, function(e1, e2)
for _, fn in ipairs(comparetors) do
local diff = fn(e1, e2)
if diff ~= nil then
return diff
end
end
end)
-- open
if #entries > 0 then
self:_get_entries_view():open(offset, entries)
else
self:close()
end
end
---Close menu
view.close = function(self)
self:_get_entries_view():close()
self.docs_view:close()
self.ghost_text_view:hide()
end
---Abort menu
view.abort = function(self)
self:_get_entries_view():abort()
self.docs_view:close()
self.ghost_text_view:hide()
end
---Return the view is visible or not.
---@return boolean
view.visible = function(self)
return self:_get_entries_view():visible()
end
---Scroll documentation window if possible.
---@param delta number
view.scroll_docs = function(self, delta)
self.docs_view:scroll(delta)
end
---Select prev menu item.
---@param option cmp.SelectOption
view.select_next_item = function(self, option)
self:_get_entries_view():select_next_item(option)
end
---Select prev menu item.
---@param option cmp.SelectOption
view.select_prev_item = function(self, option)
self:_get_entries_view():select_prev_item(option)
end
---Get first entry
---@param self cmp.Entry|nil
view.get_first_entry = function(self)
return self:_get_entries_view():get_first_entry()
end
---Get current selected entry
---@return cmp.Entry|nil
view.get_selected_entry = function(self)
return self:_get_entries_view():get_selected_entry()
end
---Get current active entry
---@return cmp.Entry|nil
view.get_active_entry = function(self)
return self:_get_entries_view():get_active_entry()
end
---Return current configured entries_view
---@return cmp.CustomEntriesView|cmp.NativeEntriesView
view._get_entries_view = function(self)
local c = config.get()
self.native_entries_view.event:clear()
self.custom_entries_view.event:clear()
if c.experimental.native_menu then
self.native_entries_view.event:on('change', function()
self:on_entry_change()
end)
return self.native_entries_view
else
self.custom_entries_view.event:on('change', function()
self:on_entry_change()
end)
return self.custom_entries_view
end
end
---On entry change
view.on_entry_change = async.throttle(
vim.schedule_wrap(function(self)
if not self:visible() then
return
end
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', ...)
end)
end
e:resolve(vim.schedule_wrap(self.resolve_dedup(function()
if not self:visible() then
return
end
self.docs_view:open(e, self:_get_entries_view():info())
end)))
else
self.docs_view:close()
end
e = e or self:get_first_entry()
if e then
self.ghost_text_view:show(e)
else
self.ghost_text_view:hide()
end
end),
20
)
return view