* perf(context): reduce use of `cmd` and `fn` * perf(float): reduce use of `cmd` and `fn` * perf(init): reduce use of `cmd` and `fn` * perf(menu): reduce use of `cmd` and `fn` * perf(plugin): reduce use of `cmd` and `fn` * docs(README): reduce use of `cmd` and `fn`
139 lines
3.7 KiB
Lua
139 lines
3.7 KiB
Lua
local async = require('cmp.utils.async')
|
|
local config = require('cmp.config')
|
|
|
|
---@class cmp.Float
|
|
---@field public entry cmp.Entry|nil
|
|
---@field public buf number|nil
|
|
---@field public win number|nil
|
|
local float = {}
|
|
|
|
---Create new floating window module
|
|
float.new = function()
|
|
local self = setmetatable({}, { __index = float })
|
|
self.entry = nil
|
|
self.win = nil
|
|
self.buf = nil
|
|
return self
|
|
end
|
|
|
|
---Show floating window
|
|
---@param e cmp.Entry
|
|
float.show = function(self, e)
|
|
float.close.stop()
|
|
|
|
local documentation = config.get().documentation
|
|
if not documentation then
|
|
return
|
|
end
|
|
|
|
local pum = vim.fn.pum_getpos() or {}
|
|
if not pum.col then
|
|
return self:close()
|
|
end
|
|
|
|
local right_space = vim.o.columns - (pum.col + pum.width + (pum.scrollbar and 1 or 0)) - 1
|
|
local left_space = pum.col - 1
|
|
local maxwidth = math.min(documentation.maxwidth, math.max(left_space, right_space))
|
|
|
|
-- update buffer content if needed.
|
|
if not self.entry or e.id ~= self.entry.id then
|
|
local documents = e:get_documentation()
|
|
if #documents == 0 then
|
|
return self:close()
|
|
end
|
|
|
|
self.entry = e
|
|
self.buf = vim.api.nvim_create_buf(false, true)
|
|
vim.api.nvim_buf_set_option(self.buf, 'bufhidden', 'wipe')
|
|
vim.lsp.util.stylize_markdown(self.buf, documents, {
|
|
max_width = maxwidth,
|
|
max_height = documentation.maxheight,
|
|
})
|
|
end
|
|
|
|
local width, height = vim.lsp.util._make_floating_popup_size(vim.api.nvim_buf_get_lines(self.buf, 0, -1, false), {
|
|
max_width = maxwidth,
|
|
max_height = documentation.maxheight,
|
|
})
|
|
if width <= 0 or height <= 0 then
|
|
return self:close()
|
|
end
|
|
|
|
local right_col = pum.col + pum.width + (pum.scrollbar and 1 or 0)
|
|
local left_col = pum.col - width - 3 -- TODO: Why is this needed -3?
|
|
|
|
local col
|
|
if right_space >= width and left_space >= width then
|
|
if right_space < left_space then
|
|
col = left_col
|
|
else
|
|
col = right_col
|
|
end
|
|
elseif right_space >= width then
|
|
col = right_col
|
|
elseif left_space >= width then
|
|
col = left_col
|
|
else
|
|
return self:close()
|
|
end
|
|
|
|
local style = {
|
|
relative = 'editor',
|
|
style = 'minimal',
|
|
width = width,
|
|
height = height,
|
|
row = pum.row,
|
|
col = col,
|
|
border = documentation.border,
|
|
}
|
|
|
|
if self.win and vim.api.nvim_win_is_valid(self.win) then
|
|
vim.api.nvim_win_set_buf(self.win, self.buf)
|
|
vim.api.nvim_win_set_config(self.win, style)
|
|
else
|
|
self.win = vim.api.nvim_open_win(self.buf, false, style)
|
|
vim.api.nvim_win_set_option(self.win, 'conceallevel', 2)
|
|
vim.api.nvim_win_set_option(self.win, 'concealcursor', 'n')
|
|
vim.api.nvim_win_set_option(self.win, 'winhighlight', config.get().documentation.winhighlight)
|
|
vim.api.nvim_win_set_option(self.win, 'foldenable', false)
|
|
vim.api.nvim_win_set_option(self.win, 'wrap', true)
|
|
vim.api.nvim_win_set_option(self.win, 'scrolloff', 0)
|
|
end
|
|
end
|
|
|
|
---Close floating window
|
|
float.close = async.throttle(
|
|
vim.schedule_wrap(function(self)
|
|
if self:is_visible() then
|
|
vim.api.nvim_win_close(self.win, true)
|
|
end
|
|
self.entry = nil
|
|
self.buf = nil
|
|
self.win = nil
|
|
end),
|
|
20
|
|
)
|
|
|
|
float.scroll = function(self, delta)
|
|
if self:is_visible() then
|
|
local info = vim.fn.getwininfo(self.win)[1] or {}
|
|
local buf = vim.api.nvim_win_get_buf(self.win)
|
|
local top = info.topline or 1
|
|
top = top + delta
|
|
top = math.max(top, 1)
|
|
top = math.min(top, vim.api.nvim_buf_line_count(buf) - info.height + 1)
|
|
|
|
vim.defer_fn(function()
|
|
vim.api.nvim_buf_call(buf, function()
|
|
vim.api.nvim_command('normal! ' .. top .. 'zt')
|
|
end)
|
|
end, 0)
|
|
end
|
|
end
|
|
|
|
float.is_visible = function(self)
|
|
return self.win and vim.api.nvim_win_is_valid(self.win)
|
|
end
|
|
|
|
return float
|