feat: allow custom input provider, removing dressing.nvim (#2173)

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: yetone <yetoneful@gmail.com>
This commit is contained in:
Avinash Thakur
2025-06-06 20:34:35 +05:30
committed by GitHub
parent a537945573
commit ec0f4f9ae0
15 changed files with 329 additions and 54 deletions

View File

@@ -20,6 +20,15 @@ function M.switch_selector_provider(target_provider)
})
end
---@param target_provider avante.InputProvider
function M.switch_input_provider(target_provider)
require("avante.config").override({
input = {
provider = target_provider,
},
})
end
---@param target avante.ProviderName
function M.switch_provider(target) require("avante.providers").refresh(target) end

View File

@@ -2,6 +2,7 @@
---we add a default var_accessor for this table to config values.
---@alias WebSearchEngineProviderResponseBodyFormatter fun(body: table): (string, string?)
---@alias avante.InputProvider "native" | "dressing" | "snacks" | fun(input: avante.ui.Input): nil
local Utils = require("avante.utils")
@@ -556,6 +557,10 @@ M._defaults = {
provider_opts = {},
exclude_auto_select = {}, -- List of items to exclude from auto selection
},
input = {
provider = "native",
provider_opts = {},
},
suggestion = {
debounce = 600,
throttle = 600,

View File

@@ -12,10 +12,6 @@ function M.check()
path = "nvim-treesitter/nvim-treesitter",
module = "nvim-treesitter",
},
["dressing.nvim"] = {
path = "stevearc/dressing.nvim",
module = "dressing",
},
["plenary.nvim"] = {
path = "nvim-lua/plenary.nvim",
module = "plenary",
@@ -41,6 +37,24 @@ function M.check()
H.warn("No icons plugin found (nvim-web-devicons or mini.icons). Icons will not be displayed")
end
-- Check input UI provider
local input_provider = Config.input and Config.input.provider or "native"
if input_provider == "dressing" then
if Utils.has("dressing.nvim") or Utils.has("dressing") then
H.ok("Found configured input provider: dressing.nvim")
else
H.error("Input provider is set to 'dressing' but dressing.nvim is not installed")
end
elseif input_provider == "snacks" then
if Utils.has("snacks.nvim") or Utils.has("snacks") then
H.ok("Found configured input provider: snacks.nvim")
else
H.error("Input provider is set to 'snacks' but snacks.nvim is not installed")
end
else
H.ok("Using native input provider (no additional dependencies required)")
end
-- Check Copilot if configured
if Config.provider and Config.provider == "copilot" then
if Utils.has("copilot.lua") or Utils.has("copilot.vim") or Utils.has("copilot") then

View File

@@ -3,13 +3,6 @@ local api, fn = vim.api, vim.fn
local Config = require("avante.config")
local Utils = require("avante.utils")
local DressingConfig = {
conceal_char = "*",
filetype = "DressingInput",
close_window = function() require("dressing.input").close() end,
}
local DressingState = { winid = nil, input_winid = nil, input_bufnr = nil }
---@class avante.Providers
---@field openai AvanteProviderFunctor
---@field claude AvanteProviderFunctor
@@ -78,7 +71,7 @@ function E.setup(opts)
end
end
local function mount_dressing_buffer()
local function mount_input_ui()
vim.defer_fn(function()
-- only mount if given buffer is not of buftype ministarter, dashboard, alpha, qf
local exclude_filetypes = {
@@ -93,46 +86,30 @@ function E.setup(opts)
"gitcommit",
"gitrebase",
"DressingInput",
"snacks_input",
"noice",
}
if not vim.tbl_contains(exclude_filetypes, vim.bo.filetype) and not opts.provider.is_env_set() then
DressingState.winid = api.nvim_get_current_win()
vim.ui.input({ default = "", prompt = "Enter " .. var .. ": " }, on_confirm)
for _, winid in ipairs(api.nvim_list_wins()) do
local bufnr = api.nvim_win_get_buf(winid)
if vim.bo[bufnr].filetype == DressingConfig.filetype then
DressingState.input_winid = winid
DressingState.input_bufnr = bufnr
vim.wo[winid].conceallevel = 2
vim.wo[winid].concealcursor = "nvi"
break
end
end
local prompt_length = api.nvim_strwidth(fn.prompt_getprompt(DressingState.input_bufnr))
api.nvim_buf_call(
DressingState.input_bufnr,
function()
vim.cmd(string.format(
[[
syn region SecretValue start=/^/ms=s+%s end=/$/ contains=SecretChar
syn match SecretChar /./ contained conceal %s
]],
prompt_length,
"cchar=*"
))
end
)
local Input = require("avante.ui.input")
local input = Input:new({
provider = Config.input.provider,
title = "Enter " .. var .. ": ",
default = "",
conceal = true, -- Password input should be concealed
provider_opts = Config.input.provider_opts,
on_submit = on_confirm,
})
input:open()
end
end, 200)
end
if refresh then return mount_dressing_buffer() end
if refresh then return mount_input_ui() end
api.nvim_create_autocmd("User", {
pattern = E.REQUEST_LOGIN_PATTERN,
callback = mount_dressing_buffer,
callback = mount_input_ui,
})
end

View File

@@ -0,0 +1,48 @@
local Utils = require("avante.utils")
---@class avante.ui.InputOption
---@field provider avante.InputProvider
---@field title string
---@field default string | nil
---@field completion string | nil
---@field provider_opts table | nil
---@field on_submit fun(result: string | nil)
---@field conceal boolean | nil -- Whether to conceal input (for passwords)
---@class avante.ui.Input
---@field provider avante.InputProvider
---@field title string
---@field default string | nil
---@field completion string | nil
---@field provider_opts table | nil
---@field on_submit fun(result: string | nil)
---@field conceal boolean | nil
local Input = {}
Input.__index = Input
---@param opts avante.ui.InputOption
function Input:new(opts)
local o = {}
setmetatable(o, Input)
o.provider = opts.provider
o.title = opts.title
o.default = opts.default or ""
o.completion = opts.completion
o.provider_opts = opts.provider_opts or {}
o.on_submit = opts.on_submit
o.conceal = opts.conceal or false
return o
end
function Input:open()
if type(self.provider) == "function" then
self.provider(self)
return
end
local ok, provider = pcall(require, "avante.ui.input.providers." .. self.provider)
if not ok then Utils.error("Unknown input provider: " .. self.provider) end
provider.show(self)
end
return Input

View File

@@ -0,0 +1,66 @@
local api = vim.api
local fn = vim.fn
local M = {}
---@param input avante.ui.Input
function M.show(input)
local ok, dressing_input = pcall(require, "dressing.input")
if not ok then
vim.notify("dressing.nvim not found, falling back to native input", vim.log.levels.WARN)
require("avante.ui.input.providers.native").show(input)
return
end
-- Store state for concealing functionality
local state = { winid = nil, input_winid = nil, input_bufnr = nil }
local function setup_concealing()
if not input.conceal then return end
vim.defer_fn(function()
-- Find the dressing input window
for _, winid in ipairs(api.nvim_list_wins()) do
local bufnr = api.nvim_win_get_buf(winid)
if vim.bo[bufnr].filetype == "DressingInput" then
state.input_winid = winid
state.input_bufnr = bufnr
vim.wo[winid].conceallevel = 2
vim.wo[winid].concealcursor = "nvi"
-- Set up concealing syntax
local prompt_length = api.nvim_strwidth(fn.prompt_getprompt(state.input_bufnr))
api.nvim_buf_call(
state.input_bufnr,
function()
vim.cmd(string.format(
[[
syn region SecretValue start=/^/ms=s+%s end=/$/ contains=SecretChar
syn match SecretChar /./ contained conceal cchar=*
]],
prompt_length
))
end
)
break
end
end
end, 50)
end
-- Enhanced functionality for concealed input
vim.ui.input({
prompt = input.title,
default = input.default,
completion = input.completion,
}, function(result)
input.on_submit(result)
-- Close the dressing input window after submission if we have concealing
if input.conceal then pcall(dressing_input.close) end
end)
-- Set up concealing if needed
setup_concealing()
end
return M

View File

@@ -0,0 +1,23 @@
local M = {}
---@param input avante.ui.Input
function M.show(input)
local opts = {
prompt = input.title,
default = input.default,
completion = input.completion,
}
-- Note: Native vim.ui.input doesn't support concealing
-- For password input, users should use dressing or snacks providers
if input.conceal then
vim.notify_once(
"Native input provider doesn't support concealed input. Consider using 'dressing' or 'snacks' provider for password input.",
vim.log.levels.WARN
)
end
vim.ui.input(opts, input.on_submit)
end
return M

View File

@@ -0,0 +1,23 @@
local M = {}
---@param input avante.ui.Input
function M.show(input)
local ok, snacks_input = pcall(require, "snacks.input")
if not ok then
vim.notify("snacks.nvim not found, falling back to native input", vim.log.levels.WARN)
require("avante.ui.input.providers.native").show(input)
return
end
local opts = vim.tbl_deep_extend("force", {
prompt = input.title,
default = input.default,
}, input.provider_opts)
-- Add concealing support if needed
if input.conceal then opts.password = true end
snacks_input(opts, input.on_submit)
end
return M

View File

@@ -37,7 +37,6 @@ function M.show(selector)
preview = selector.get_preview_content and "preview" or nil,
layout = {
preset = "default",
preview = selector.get_preview_content ~= nil,
},
confirm = function(picker)
if completed then return end