dressing.nvim/lua/dressing/select/init.lua

98 lines
2.7 KiB
Lua

local global_config = require("dressing.config")
local patch = require("dressing.patch")
local util = require("dressing.util")
---@diagnostic disable-next-line: deprecated
local islist = vim.islist or vim.tbl_islist
local M = {}
---@param backends string|string[]
---@return table select module
---@return string name of backend
M.get_backend = function(backends)
if type(backends) ~= "table" then
backends = { backends }
end
for _, backend in ipairs(backends) do
local ok, mod = pcall(require, string.format("dressing.select.%s", backend))
if ok and mod.is_supported() then
return mod, backend
end
end
return require("dressing.select.builtin"), "builtin"
end
local function sanitize_line(line)
return string.gsub(tostring(line), "\n", " ")
end
local function with_sanitize_line(fn)
return function(...)
return sanitize_line(fn(...))
end
end
-- use schedule_wrap to avoid a bug when vim opens
-- (see https://github.com/stevearc/dressing.nvim/issues/15)
-- also to prevent focus problems for providers
-- (see https://github.com/stevearc/dressing.nvim/issues/59)
local select = vim.schedule_wrap(util.make_queued_async_fn(3, function(items, opts, on_choice)
vim.validate({
items = {
items,
function(a)
return type(a) == "table" and islist(a)
end,
"list-like table",
},
on_choice = { on_choice, "function", false },
})
opts = opts or {}
local config = global_config.get_mod_config("select", opts, items)
if not config.enabled then
return patch.original_mods.select(items, opts, on_choice)
end
opts.prompt = sanitize_line(opts.prompt or "Select one of:")
opts.prompt = vim.trim(opts.prompt)
if config.trim_prompt and opts.prompt:sub(-1, -1) == ":" then
opts.prompt = opts.prompt:sub(1, -2)
end
local format_override = config.format_item_override[opts.kind]
if format_override then
opts.format_item = with_sanitize_line(format_override)
elseif opts.format_item then
-- format_item doesn't *technically* have to return a string for the
-- core implementation. We should maintain compatibility by wrapping the
-- return value with tostring
opts.format_item = with_sanitize_line(opts.format_item)
else
opts.format_item = sanitize_line
end
local backend, name = M.get_backend(config.backend)
local winid = vim.api.nvim_get_current_win()
local cursor = vim.api.nvim_win_get_cursor(winid)
backend.select(
config[name],
items,
opts,
vim.schedule_wrap(function(...)
if vim.api.nvim_win_is_valid(winid) then
vim.api.nvim_win_set_cursor(winid, cursor)
end
on_choice(...)
end)
)
end))
setmetatable(M, {
__call = function(_, ...)
return select(...)
end,
})
return M