feat!: more layout options for input and builtin select (#19)
Removed the row & col options for input and select.builtin. If you want to tweak the values sent to nvim_open_win, use the `override` function. Changes: * min_width/height and max_width/height can be a list of values. Useful for mixing raw integers (e.g. for cols) and floats (e.g. for % of total) * can specify an exact width or height for the windows * when using relative = 'win' or 'editor', the row & col will by default be calculated to center the floating win
This commit is contained in:
parent
b6f5a92ef4
commit
1e529b8cdb
|
@ -11,21 +11,29 @@ local default_config = {
|
|||
|
||||
-- These are passed to nvim_open_win
|
||||
anchor = "SW",
|
||||
relative = "cursor",
|
||||
row = 0,
|
||||
col = 0,
|
||||
border = "rounded",
|
||||
-- 'editor' and 'win' will default to being centered
|
||||
relative = "cursor",
|
||||
|
||||
-- These can be integers or a float between 0 and 1 (e.g. 0.4 for 40%)
|
||||
prefer_width = 40,
|
||||
max_width = nil,
|
||||
min_width = 20,
|
||||
width = nil,
|
||||
-- min_width and max_width can be a list of mixed types.
|
||||
-- min_width = {20, 0.2} means "the greater of 20 columns or 20% of total"
|
||||
max_width = { 140, 0.9 },
|
||||
min_width = { 20, 0.2 },
|
||||
|
||||
-- Window transparency (0-100)
|
||||
winblend = 10,
|
||||
-- Change default highlight groups (see :help winhl)
|
||||
winhighlight = "",
|
||||
|
||||
override = function(conf)
|
||||
-- This is the config that will be passed to nvim_open_win.
|
||||
-- Change values here to customize the layout
|
||||
return conf
|
||||
end,
|
||||
|
||||
-- see :help dressing_get_config
|
||||
get_config = nil,
|
||||
},
|
||||
|
@ -76,10 +84,9 @@ local default_config = {
|
|||
builtin = {
|
||||
-- These are passed to nvim_open_win
|
||||
anchor = "NW",
|
||||
relative = "cursor",
|
||||
row = 0,
|
||||
col = 0,
|
||||
border = "rounded",
|
||||
-- 'editor' and 'win' will default to being centered
|
||||
relative = "editor",
|
||||
|
||||
-- Window transparency (0-100)
|
||||
winblend = 10,
|
||||
|
@ -87,12 +94,20 @@ local default_config = {
|
|||
winhighlight = "",
|
||||
|
||||
-- These can be integers or a float between 0 and 1 (e.g. 0.4 for 40%)
|
||||
-- the min_ and max_ options can be a list of mixed types.
|
||||
-- max_width = {140, 0.8} means "the lesser of 140 columns or 80% of total"
|
||||
width = nil,
|
||||
max_width = 0.8,
|
||||
min_width = 40,
|
||||
max_width = { 140, 0.8 },
|
||||
min_width = { 40, 0.2 },
|
||||
height = nil,
|
||||
max_height = 0.9,
|
||||
min_height = 10,
|
||||
min_height = { 10, 0.2 },
|
||||
|
||||
override = function(conf)
|
||||
-- This is the config that will be passed to nvim_open_win.
|
||||
-- Change values here to customize the layout
|
||||
return conf
|
||||
end,
|
||||
},
|
||||
|
||||
-- Used to override format_item. See :help dressing-format
|
||||
|
@ -107,6 +122,19 @@ local M = vim.deepcopy(default_config)
|
|||
|
||||
M.update = function(opts)
|
||||
local newconf = vim.tbl_deep_extend("force", default_config, opts or {})
|
||||
|
||||
if
|
||||
newconf.input.row
|
||||
or newconf.input.col
|
||||
or newconf.select.builtin.row
|
||||
or newconf.select.builtin.col
|
||||
then
|
||||
vim.notify(
|
||||
"Deprecated: Dressing row and col are no longer used. Use the override to customize layout (:help dressing)",
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
end
|
||||
|
||||
for k, v in pairs(newconf) do
|
||||
M[k] = v
|
||||
end
|
||||
|
|
|
@ -162,6 +162,74 @@ M.trigger_completion = function()
|
|||
end
|
||||
end
|
||||
|
||||
local function create_or_update_win(config, prompt, opts)
|
||||
local parent_win = 0
|
||||
local winopt
|
||||
local win_conf
|
||||
-- If the previous window is still open and valid, we're going to update it
|
||||
if context.winid and vim.api.nvim_win_is_valid(context.winid) then
|
||||
win_conf = vim.api.nvim_win_get_config(context.winid)
|
||||
parent_win = win_conf.win
|
||||
winopt = {
|
||||
relative = win_conf.relative,
|
||||
win = win_conf.win,
|
||||
}
|
||||
else
|
||||
winopt = {
|
||||
relative = config.relative,
|
||||
anchor = config.anchor,
|
||||
border = config.border,
|
||||
height = 1,
|
||||
style = "minimal",
|
||||
noautocmd = true,
|
||||
}
|
||||
end
|
||||
-- First calculate the desired base width of the modal
|
||||
local prefer_width = util.calculate_width(
|
||||
config.relative,
|
||||
config.prefer_width,
|
||||
config,
|
||||
parent_win
|
||||
)
|
||||
-- Then expand the width to fit the prompt and default value
|
||||
prefer_width = math.max(prefer_width, 4 + vim.api.nvim_strwidth(prompt))
|
||||
if opts.default then
|
||||
prefer_width = math.max(prefer_width, 2 + vim.api.nvim_strwidth(opts.default))
|
||||
end
|
||||
-- Then recalculate to clamp final value to min/max
|
||||
local width = util.calculate_width(config.relative, prefer_width, config, parent_win)
|
||||
winopt.row = util.calculate_row(config.relative, 1, parent_win)
|
||||
winopt.col = util.calculate_col(config.relative, width, parent_win)
|
||||
winopt.width = width
|
||||
|
||||
if win_conf and config.relative == "cursor" then
|
||||
-- If we're cursor-relative we should actually not adjust the row/col to
|
||||
-- prevent jumping. Also remove related args.
|
||||
if config.relative == "cursor" then
|
||||
winopt.row = nil
|
||||
winopt.col = nil
|
||||
winopt.relative = nil
|
||||
winopt.win = nil
|
||||
end
|
||||
end
|
||||
|
||||
winopt = config.override(winopt) or winopt
|
||||
|
||||
-- If the floating win was already open
|
||||
if win_conf then
|
||||
-- Make sure the previous on_confirm callback is called with nil
|
||||
vim.schedule(context.on_confirm)
|
||||
vim.api.nvim_win_set_config(context.winid, winopt)
|
||||
local start_in_insert = context.start_in_insert
|
||||
return context.winid, start_in_insert
|
||||
else
|
||||
local start_in_insert = string.sub(vim.api.nvim_get_mode().mode, 1, 1) == "i"
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
local winid = vim.api.nvim_open_win(bufnr, true, winopt)
|
||||
return winid, start_in_insert
|
||||
end
|
||||
end
|
||||
|
||||
setmetatable(M, {
|
||||
-- use schedule_wrap to avoid a bug when vim opens
|
||||
-- (see https://github.com/stevearc/dressing.nvim/issues/15)
|
||||
|
@ -178,40 +246,7 @@ setmetatable(M, {
|
|||
-- Create or update the window
|
||||
local prompt = opts.prompt or config.default_prompt
|
||||
|
||||
-- First calculate the desired base width of the modal
|
||||
local prefer_width = util.calculate_width(config.prefer_width, config)
|
||||
-- Then expand the width to fit the prompt and default value
|
||||
prefer_width = math.max(prefer_width, 4 + vim.api.nvim_strwidth(prompt))
|
||||
if opts.default then
|
||||
prefer_width = math.max(prefer_width, 2 + vim.api.nvim_strwidth(opts.default))
|
||||
end
|
||||
-- Then recalculate to clamp final value to min/max
|
||||
local width = util.calculate_width(prefer_width, config)
|
||||
local winopt = {
|
||||
relative = config.relative,
|
||||
anchor = config.anchor,
|
||||
row = config.row,
|
||||
col = config.col,
|
||||
border = config.border,
|
||||
width = width,
|
||||
height = 1,
|
||||
style = "minimal",
|
||||
noautocmd = true,
|
||||
}
|
||||
local winid, bufnr, start_in_insert
|
||||
-- If the input window is already open, hijack it
|
||||
if context.winid and vim.api.nvim_win_is_valid(context.winid) then
|
||||
winid = context.winid
|
||||
-- Make sure the previous on_confirm callback is called with nil
|
||||
vim.schedule(context.on_confirm)
|
||||
vim.api.nvim_win_set_width(winid, width)
|
||||
bufnr = vim.api.nvim_win_get_buf(winid)
|
||||
start_in_insert = context.start_in_insert
|
||||
else
|
||||
start_in_insert = string.sub(vim.api.nvim_get_mode().mode, 1, 1) == "i"
|
||||
bufnr = vim.api.nvim_create_buf(false, true)
|
||||
winid = vim.api.nvim_open_win(bufnr, true, winopt)
|
||||
end
|
||||
local winid, start_in_insert = create_or_update_win(config, prompt, opts)
|
||||
context = {
|
||||
winid = winid,
|
||||
on_confirm = on_confirm,
|
||||
|
@ -221,6 +256,7 @@ setmetatable(M, {
|
|||
}
|
||||
vim.api.nvim_win_set_option(winid, "winblend", config.winblend)
|
||||
vim.api.nvim_win_set_option(winid, "winhighlight", config.winhighlight)
|
||||
local bufnr = vim.api.nvim_win_get_buf(winid)
|
||||
|
||||
-- Finish setting up the buffer
|
||||
vim.api.nvim_buf_set_option(bufnr, "swapfile", false)
|
||||
|
|
|
@ -31,18 +31,22 @@ M.select = function(config, items, opts, on_choice)
|
|||
for i = 0, #lines - 1, 1 do
|
||||
vim.api.nvim_buf_add_highlight(bufnr, ns, "DressingSelectText", i, 0, -1)
|
||||
end
|
||||
local width = util.calculate_width(max_width, config)
|
||||
local width = util.calculate_width(config.relative, max_width, config, 0)
|
||||
local height = util.calculate_height(config.relative, #lines, config, 0)
|
||||
local row = util.calculate_row(config.relative, height, 0)
|
||||
local col = util.calculate_col(config.relative, width, 0)
|
||||
local winopt = {
|
||||
relative = config.relative,
|
||||
anchor = config.anchor,
|
||||
row = config.row,
|
||||
col = config.col,
|
||||
row = row,
|
||||
col = col,
|
||||
border = config.border,
|
||||
width = width,
|
||||
height = util.calculate_height(#lines, config),
|
||||
height = height,
|
||||
zindex = 150,
|
||||
style = "minimal",
|
||||
}
|
||||
winopt = config.override(winopt) or winopt
|
||||
local winnr = vim.api.nvim_open_win(bufnr, true, winopt)
|
||||
vim.api.nvim_win_set_option(winnr, "winblend", config.winblend)
|
||||
vim.api.nvim_win_set_option(winnr, "winhighlight", config.winhighlight)
|
||||
|
|
|
@ -13,33 +13,84 @@ local function calc_float(value, max_value)
|
|||
end
|
||||
end
|
||||
|
||||
local function calc_list(values, max_value, aggregator, limit)
|
||||
local ret = limit
|
||||
if type(values) == "table" then
|
||||
for _, v in ipairs(values) do
|
||||
ret = aggregator(ret, calc_float(v, max_value))
|
||||
end
|
||||
return ret
|
||||
else
|
||||
ret = aggregator(ret, calc_float(values, max_value))
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local function calculate_dim(desired_size, size, min_size, max_size, total_size)
|
||||
local ret = calc_float(size, total_size)
|
||||
local min_val = calc_list(min_size, total_size, math.max, 1)
|
||||
local max_val = calc_list(max_size, total_size, math.min, total_size)
|
||||
if not ret then
|
||||
ret = calc_float(desired_size, total_size)
|
||||
if not desired_size then
|
||||
ret = (min_val + max_val) / 2
|
||||
else
|
||||
ret = calc_float(desired_size, total_size)
|
||||
end
|
||||
end
|
||||
ret = math.min(ret, calc_float(max_size, total_size) or total_size)
|
||||
ret = math.max(ret, calc_float(min_size, total_size) or 1)
|
||||
ret = math.min(ret, max_val)
|
||||
ret = math.max(ret, min_val)
|
||||
return math.floor(ret)
|
||||
end
|
||||
|
||||
M.calculate_width = function(desired_width, config)
|
||||
local function get_max_width(relative, winid)
|
||||
if relative == "editor" then
|
||||
return vim.o.columns
|
||||
else
|
||||
return vim.api.nvim_win_get_width(winid or 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_max_height(relative, winid)
|
||||
if relative == "editor" then
|
||||
return vim.o.lines - vim.o.cmdheight
|
||||
else
|
||||
return vim.api.nvim_win_get_height(winid or 0)
|
||||
end
|
||||
end
|
||||
|
||||
M.calculate_col = function(relative, width, winid)
|
||||
if relative == "cursor" then
|
||||
return 1
|
||||
else
|
||||
return math.floor((get_max_width(relative, winid) - width) / 2)
|
||||
end
|
||||
end
|
||||
|
||||
M.calculate_row = function(relative, height, winid)
|
||||
if relative == "cursor" then
|
||||
return 1
|
||||
else
|
||||
return math.floor((get_max_height(relative, winid) - height) / 2)
|
||||
end
|
||||
end
|
||||
|
||||
M.calculate_width = function(relative, desired_width, config, winid)
|
||||
return calculate_dim(
|
||||
desired_width,
|
||||
config.width,
|
||||
config.min_width,
|
||||
config.max_width,
|
||||
vim.o.columns
|
||||
get_max_width(relative, winid)
|
||||
)
|
||||
end
|
||||
|
||||
M.calculate_height = function(desired_height, config)
|
||||
M.calculate_height = function(relative, desired_height, config, winid)
|
||||
return calculate_dim(
|
||||
desired_height,
|
||||
config.height,
|
||||
config.min_height,
|
||||
config.max_height,
|
||||
vim.o.lines - vim.o.cmdheight
|
||||
get_max_height(relative, winid)
|
||||
)
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue