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

@@ -61,7 +61,6 @@ body:
-- build = "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false" -- for windows -- build = "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false" -- for windows
dependencies = { dependencies = {
"nvim-treesitter/nvim-treesitter", "nvim-treesitter/nvim-treesitter",
"stevearc/dressing.nvim",
"nvim-lua/plenary.nvim", "nvim-lua/plenary.nvim",
"MunifTanjim/nui.nvim", "MunifTanjim/nui.nvim",
}, },

View File

@@ -14,6 +14,7 @@
"$DEPS_PATH/lazy.nvim/lua", "$DEPS_PATH/lazy.nvim/lua",
"$DEPS_PATH/nvim-treesitter/lua", "$DEPS_PATH/nvim-treesitter/lua",
"$DEPS_PATH/dressing.nvim/lua", "$DEPS_PATH/dressing.nvim/lua",
"$DEPS_PATH/snacks.nvim/lua",
"$DEPS_PATH/plenary.nvim/lua", "$DEPS_PATH/plenary.nvim/lua",
"$DEPS_PATH/nui.nvim/lua", "$DEPS_PATH/nui.nvim/lua",
"$DEPS_PATH/mini.pick/lua", "$DEPS_PATH/mini.pick/lua",

View File

@@ -82,9 +82,10 @@ jobs:
DEPS=( DEPS=(
"folke/neodev.nvim" "folke/neodev.nvim"
"nvim-treesitter/nvim-treesitter" "nvim-treesitter/nvim-treesitter"
"stevearc/dressing.nvim"
"nvim-lua/plenary.nvim" "nvim-lua/plenary.nvim"
"MunifTanjim/nui.nvim" "MunifTanjim/nui.nvim"
"stevearc/dressing.nvim"
"folke/snacks.nvim"
"echasnovski/mini.nvim" "echasnovski/mini.nvim"
"nvim-telescope/telescope.nvim" "nvim-telescope/telescope.nvim"
"hrsh7th/nvim-cmp" "hrsh7th/nvim-cmp"

113
README.md
View File

@@ -97,7 +97,6 @@ For building binary if you wish to build from source, then `cargo` is required.
-- build = "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false" -- for windows -- build = "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false" -- for windows
dependencies = { dependencies = {
"nvim-treesitter/nvim-treesitter", "nvim-treesitter/nvim-treesitter",
"stevearc/dressing.nvim",
"nvim-lua/plenary.nvim", "nvim-lua/plenary.nvim",
"MunifTanjim/nui.nvim", "MunifTanjim/nui.nvim",
--- The below dependencies are optional, --- The below dependencies are optional,
@@ -105,6 +104,8 @@ For building binary if you wish to build from source, then `cargo` is required.
"nvim-telescope/telescope.nvim", -- for file_selector provider telescope "nvim-telescope/telescope.nvim", -- for file_selector provider telescope
"hrsh7th/nvim-cmp", -- autocompletion for avante commands and mentions "hrsh7th/nvim-cmp", -- autocompletion for avante commands and mentions
"ibhagwan/fzf-lua", -- for file_selector provider fzf "ibhagwan/fzf-lua", -- for file_selector provider fzf
"stevearc/dressing.nvim", -- for input provider dressing
"folke/snacks.nvim", -- for input provider snacks
"nvim-tree/nvim-web-devicons", -- or echasnovski/mini.icons "nvim-tree/nvim-web-devicons", -- or echasnovski/mini.icons
"zbirenbaum/copilot.lua", -- for providers='copilot' "zbirenbaum/copilot.lua", -- for providers='copilot'
{ {
@@ -146,7 +147,6 @@ For building binary if you wish to build from source, then `cargo` is required.
" Deps " Deps
Plug 'nvim-treesitter/nvim-treesitter' Plug 'nvim-treesitter/nvim-treesitter'
Plug 'stevearc/dressing.nvim'
Plug 'nvim-lua/plenary.nvim' Plug 'nvim-lua/plenary.nvim'
Plug 'MunifTanjim/nui.nvim' Plug 'MunifTanjim/nui.nvim'
Plug 'MeanderingProgrammer/render-markdown.nvim' Plug 'MeanderingProgrammer/render-markdown.nvim'
@@ -156,6 +156,8 @@ Plug 'hrsh7th/nvim-cmp'
Plug 'nvim-tree/nvim-web-devicons' "or Plug 'echasnovski/mini.icons' Plug 'nvim-tree/nvim-web-devicons' "or Plug 'echasnovski/mini.icons'
Plug 'HakonHarnes/img-clip.nvim' Plug 'HakonHarnes/img-clip.nvim'
Plug 'zbirenbaum/copilot.lua' Plug 'zbirenbaum/copilot.lua'
Plug 'stevearc/dressing.nvim' " for enhanced input UI
Plug 'folke/snacks.nvim' " for modern input UI
" Yay, pass source=true if you want to build from source " Yay, pass source=true if you want to build from source
Plug 'yetone/avante.nvim', { 'branch': 'main', 'do': 'make' } Plug 'yetone/avante.nvim', { 'branch': 'main', 'do': 'make' }
@@ -178,7 +180,6 @@ add({
monitor = 'main', monitor = 'main',
depends = { depends = {
'nvim-treesitter/nvim-treesitter', 'nvim-treesitter/nvim-treesitter',
'stevearc/dressing.nvim',
'nvim-lua/plenary.nvim', 'nvim-lua/plenary.nvim',
'MunifTanjim/nui.nvim', 'MunifTanjim/nui.nvim',
'echasnovski/mini.icons' 'echasnovski/mini.icons'
@@ -209,7 +210,6 @@ end)
-- Required plugins -- Required plugins
use 'nvim-treesitter/nvim-treesitter' use 'nvim-treesitter/nvim-treesitter'
use 'stevearc/dressing.nvim'
use 'nvim-lua/plenary.nvim' use 'nvim-lua/plenary.nvim'
use 'MunifTanjim/nui.nvim' use 'MunifTanjim/nui.nvim'
use 'MeanderingProgrammer/render-markdown.nvim' use 'MeanderingProgrammer/render-markdown.nvim'
@@ -219,6 +219,8 @@ end)
use 'nvim-tree/nvim-web-devicons' -- or use 'echasnovski/mini.icons' use 'nvim-tree/nvim-web-devicons' -- or use 'echasnovski/mini.icons'
use 'HakonHarnes/img-clip.nvim' use 'HakonHarnes/img-clip.nvim'
use 'zbirenbaum/copilot.lua' use 'zbirenbaum/copilot.lua'
use 'stevearc/dressing.nvim' -- for enhanced input UI
use 'folke/snacks.nvim' -- for modern input UI
-- Avante.nvim with build process -- Avante.nvim with build process
use { use {
@@ -285,8 +287,18 @@ require('copilot').setup ({
require('render-markdown').setup ({ require('render-markdown').setup ({
-- use recommended settings from above -- use recommended settings from above
}) })
require('avante').setup ({ require('avante').setup({
-- Your config here! -- Example: Using snacks.nvim as input provider
input = {
provider = "snacks", -- "native" | "dressing" | "snacks"
provider_opts = {
-- Snacks input configuration
title = "Avante Input",
icon = " ",
placeholder = "Enter your API key...",
},
},
-- Your other config here!
}) })
``` ```
@@ -497,6 +509,95 @@ To create a customized selector provider, you can specify a customized function
} }
``` ```
### Input Provider Configuration
Avante.nvim supports multiple input providers for user input (like API key entry). You can configure which provider to use:
<details>
<summary>Native Input Provider (Default)</summary>
```lua
{
input = {
provider = "native", -- Uses vim.ui.input
provider_opts = {},
}
}
```
</details>
<details>
<summary>Dressing.nvim Input Provider</summary>
For enhanced input UI with better styling and features:
```lua
{
input = {
provider = "dressing",
provider_opts = {},
}
}
```
You'll need to install dressing.nvim:
```lua
-- With lazy.nvim
{ "stevearc/dressing.nvim" }
```
</details>
<details>
<summary>Snacks.nvim Input Provider (Recommended)</summary>
For modern, feature-rich input UI:
```lua
{
input = {
provider = "snacks",
provider_opts = {
-- Additional snacks.input options
title = "Avante Input",
icon = " ",
},
}
}
```
You'll need to install snacks.nvim:
```lua
-- With lazy.nvim
{ "folke/snacks.nvim" }
```
</details>
<details>
<summary>Custom Input Provider</summary>
To create a customized input provider, you can specify a function:
```lua
{
input = {
---@param input avante.ui.Input
provider = function(input)
local title = input.title ---@type string
local default = input.default ---@type string
local conceal = input.conceal ---@type boolean
local on_submit = input.on_submit ---@type fun(result: string|nil): nil
--- your customized input logic here
end,
}
}
```
</details>
Choose a selector other that native, the default as that currently has an issue Choose a selector other that native, the default as that currently has an issue
For lazyvim users copy the full config for blink.cmp from the website or extend the options For lazyvim users copy the full config for blink.cmp from the website or extend the options

View File

@@ -82,7 +82,7 @@
-- build = "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false" -- 对于 Windows -- build = "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false" -- 对于 Windows
dependencies = { dependencies = {
"nvim-treesitter/nvim-treesitter", "nvim-treesitter/nvim-treesitter",
"stevearc/dressing.nvim",
"nvim-lua/plenary.nvim", "nvim-lua/plenary.nvim",
"MunifTanjim/nui.nvim", "MunifTanjim/nui.nvim",
--- 以下依赖项是可选的, --- 以下依赖项是可选的,
@@ -131,7 +131,7 @@
" 依赖项 " 依赖项
Plug 'nvim-treesitter/nvim-treesitter' Plug 'nvim-treesitter/nvim-treesitter'
Plug 'stevearc/dressing.nvim'
Plug 'nvim-lua/plenary.nvim' Plug 'nvim-lua/plenary.nvim'
Plug 'MunifTanjim/nui.nvim' Plug 'MunifTanjim/nui.nvim'
Plug 'MeanderingProgrammer/render-markdown.nvim' Plug 'MeanderingProgrammer/render-markdown.nvim'
@@ -163,7 +163,7 @@ add({
monitor = 'main', monitor = 'main',
depends = { depends = {
'nvim-treesitter/nvim-treesitter', 'nvim-treesitter/nvim-treesitter',
'stevearc/dressing.nvim',
'nvim-lua/plenary.nvim', 'nvim-lua/plenary.nvim',
'MunifTanjim/nui.nvim', 'MunifTanjim/nui.nvim',
'echasnovski/mini.icons' 'echasnovski/mini.icons'
@@ -194,7 +194,7 @@ end)
-- 必需插件 -- 必需插件
use 'nvim-treesitter/nvim-treesitter' use 'nvim-treesitter/nvim-treesitter'
use 'stevearc/dressing.nvim'
use 'nvim-lua/plenary.nvim' use 'nvim-lua/plenary.nvim'
use 'MunifTanjim/nui.nvim' use 'MunifTanjim/nui.nvim'
use 'MeanderingProgrammer/render-markdown.nvim' use 'MeanderingProgrammer/render-markdown.nvim'

View File

@@ -20,6 +20,15 @@ function M.switch_selector_provider(target_provider)
}) })
end 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 ---@param target avante.ProviderName
function M.switch_provider(target) require("avante.providers").refresh(target) end 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. ---we add a default var_accessor for this table to config values.
---@alias WebSearchEngineProviderResponseBodyFormatter fun(body: table): (string, string?) ---@alias WebSearchEngineProviderResponseBodyFormatter fun(body: table): (string, string?)
---@alias avante.InputProvider "native" | "dressing" | "snacks" | fun(input: avante.ui.Input): nil
local Utils = require("avante.utils") local Utils = require("avante.utils")
@@ -556,6 +557,10 @@ M._defaults = {
provider_opts = {}, provider_opts = {},
exclude_auto_select = {}, -- List of items to exclude from auto selection exclude_auto_select = {}, -- List of items to exclude from auto selection
}, },
input = {
provider = "native",
provider_opts = {},
},
suggestion = { suggestion = {
debounce = 600, debounce = 600,
throttle = 600, throttle = 600,

View File

@@ -12,10 +12,6 @@ function M.check()
path = "nvim-treesitter/nvim-treesitter", path = "nvim-treesitter/nvim-treesitter",
module = "nvim-treesitter", module = "nvim-treesitter",
}, },
["dressing.nvim"] = {
path = "stevearc/dressing.nvim",
module = "dressing",
},
["plenary.nvim"] = { ["plenary.nvim"] = {
path = "nvim-lua/plenary.nvim", path = "nvim-lua/plenary.nvim",
module = "plenary", 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") H.warn("No icons plugin found (nvim-web-devicons or mini.icons). Icons will not be displayed")
end 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 -- Check Copilot if configured
if Config.provider and Config.provider == "copilot" then if Config.provider and Config.provider == "copilot" then
if Utils.has("copilot.lua") or Utils.has("copilot.vim") or Utils.has("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 Config = require("avante.config")
local Utils = require("avante.utils") 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 ---@class avante.Providers
---@field openai AvanteProviderFunctor ---@field openai AvanteProviderFunctor
---@field claude AvanteProviderFunctor ---@field claude AvanteProviderFunctor
@@ -78,7 +71,7 @@ function E.setup(opts)
end end
end end
local function mount_dressing_buffer() local function mount_input_ui()
vim.defer_fn(function() vim.defer_fn(function()
-- only mount if given buffer is not of buftype ministarter, dashboard, alpha, qf -- only mount if given buffer is not of buftype ministarter, dashboard, alpha, qf
local exclude_filetypes = { local exclude_filetypes = {
@@ -93,46 +86,30 @@ function E.setup(opts)
"gitcommit", "gitcommit",
"gitrebase", "gitrebase",
"DressingInput", "DressingInput",
"snacks_input",
"noice", "noice",
} }
if not vim.tbl_contains(exclude_filetypes, vim.bo.filetype) and not opts.provider.is_env_set() then 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() local Input = require("avante.ui.input")
vim.ui.input({ default = "", prompt = "Enter " .. var .. ": " }, on_confirm) local input = Input:new({
for _, winid in ipairs(api.nvim_list_wins()) do provider = Config.input.provider,
local bufnr = api.nvim_win_get_buf(winid) title = "Enter " .. var .. ": ",
if vim.bo[bufnr].filetype == DressingConfig.filetype then default = "",
DressingState.input_winid = winid conceal = true, -- Password input should be concealed
DressingState.input_bufnr = bufnr provider_opts = Config.input.provider_opts,
vim.wo[winid].conceallevel = 2 on_submit = on_confirm,
vim.wo[winid].concealcursor = "nvi" })
break input:open()
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
)
end end
end, 200) end, 200)
end end
if refresh then return mount_dressing_buffer() end if refresh then return mount_input_ui() end
api.nvim_create_autocmd("User", { api.nvim_create_autocmd("User", {
pattern = E.REQUEST_LOGIN_PATTERN, pattern = E.REQUEST_LOGIN_PATTERN,
callback = mount_dressing_buffer, callback = mount_input_ui,
}) })
end 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, preview = selector.get_preview_content and "preview" or nil,
layout = { layout = {
preset = "default", preset = "default",
preview = selector.get_preview_content ~= nil,
}, },
confirm = function(picker) confirm = function(picker)
if completed then return end if completed then return end

View File

@@ -129,6 +129,15 @@ cmd(
desc = "avante: switch selector provider", desc = "avante: switch selector provider",
} }
) )
cmd("SwitchInputProvider", function(opts) require("avante.api").switch_input_provider(vim.trim(opts.args or "")) end, {
nargs = 1,
desc = "avante: switch input provider",
complete = function(_, line, _)
local prefix = line:match("AvanteSwitchInputProvider%s*(.*)$") or ""
local providers = { "native", "dressing", "snacks" }
return vim.tbl_filter(function(key) return key:find(prefix, 1, true) == 1 end, providers)
end,
})
cmd("Clear", function(opts) cmd("Clear", function(opts)
local arg = vim.trim(opts.args or "") local arg = vim.trim(opts.args or "")
arg = arg == "" and "history" or arg arg = arg == "" and "history" or arg