diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index c3388f5..5fd31d1 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -61,7 +61,6 @@ body:
-- build = "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false" -- for windows
dependencies = {
"nvim-treesitter/nvim-treesitter",
- "stevearc/dressing.nvim",
"nvim-lua/plenary.nvim",
"MunifTanjim/nui.nvim",
},
diff --git a/.github/workflows/.luarc.json b/.github/workflows/.luarc.json
index f328c1c..b3f2afb 100644
--- a/.github/workflows/.luarc.json
+++ b/.github/workflows/.luarc.json
@@ -14,6 +14,7 @@
"$DEPS_PATH/lazy.nvim/lua",
"$DEPS_PATH/nvim-treesitter/lua",
"$DEPS_PATH/dressing.nvim/lua",
+ "$DEPS_PATH/snacks.nvim/lua",
"$DEPS_PATH/plenary.nvim/lua",
"$DEPS_PATH/nui.nvim/lua",
"$DEPS_PATH/mini.pick/lua",
diff --git a/.github/workflows/lua.yaml b/.github/workflows/lua.yaml
index ffcd73c..1cbf934 100644
--- a/.github/workflows/lua.yaml
+++ b/.github/workflows/lua.yaml
@@ -82,9 +82,10 @@ jobs:
DEPS=(
"folke/neodev.nvim"
"nvim-treesitter/nvim-treesitter"
- "stevearc/dressing.nvim"
"nvim-lua/plenary.nvim"
"MunifTanjim/nui.nvim"
+ "stevearc/dressing.nvim"
+ "folke/snacks.nvim"
"echasnovski/mini.nvim"
"nvim-telescope/telescope.nvim"
"hrsh7th/nvim-cmp"
diff --git a/README.md b/README.md
index bd7b584..ccbd694 100644
--- a/README.md
+++ b/README.md
@@ -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
dependencies = {
"nvim-treesitter/nvim-treesitter",
- "stevearc/dressing.nvim",
"nvim-lua/plenary.nvim",
"MunifTanjim/nui.nvim",
--- 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
"hrsh7th/nvim-cmp", -- autocompletion for avante commands and mentions
"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
"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
Plug 'nvim-treesitter/nvim-treesitter'
-Plug 'stevearc/dressing.nvim'
Plug 'nvim-lua/plenary.nvim'
Plug 'MunifTanjim/nui.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 'HakonHarnes/img-clip.nvim'
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
Plug 'yetone/avante.nvim', { 'branch': 'main', 'do': 'make' }
@@ -178,7 +180,6 @@ add({
monitor = 'main',
depends = {
'nvim-treesitter/nvim-treesitter',
- 'stevearc/dressing.nvim',
'nvim-lua/plenary.nvim',
'MunifTanjim/nui.nvim',
'echasnovski/mini.icons'
@@ -209,7 +210,6 @@ end)
-- Required plugins
use 'nvim-treesitter/nvim-treesitter'
- use 'stevearc/dressing.nvim'
use 'nvim-lua/plenary.nvim'
use 'MunifTanjim/nui.nvim'
use 'MeanderingProgrammer/render-markdown.nvim'
@@ -219,6 +219,8 @@ end)
use 'nvim-tree/nvim-web-devicons' -- or use 'echasnovski/mini.icons'
use 'HakonHarnes/img-clip.nvim'
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
use {
@@ -285,8 +287,18 @@ require('copilot').setup ({
require('render-markdown').setup ({
-- use recommended settings from above
})
-require('avante').setup ({
- -- Your config here!
+require('avante').setup({
+ -- 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:
+
+
+ Native Input Provider (Default)
+
+```lua
+{
+ input = {
+ provider = "native", -- Uses vim.ui.input
+ provider_opts = {},
+ }
+}
+```
+
+
+
+
+ Dressing.nvim Input Provider
+
+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" }
+```
+
+
+
+
+ Snacks.nvim Input Provider (Recommended)
+
+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" }
+```
+
+
+
+
+ Custom Input Provider
+
+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,
+ }
+}
+```
+
+
+
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
diff --git a/README_zh.md b/README_zh.md
index e622010..99d4374 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -82,7 +82,7 @@
-- build = "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false" -- 对于 Windows
dependencies = {
"nvim-treesitter/nvim-treesitter",
- "stevearc/dressing.nvim",
+
"nvim-lua/plenary.nvim",
"MunifTanjim/nui.nvim",
--- 以下依赖项是可选的,
@@ -131,7 +131,7 @@
" 依赖项
Plug 'nvim-treesitter/nvim-treesitter'
-Plug 'stevearc/dressing.nvim'
+
Plug 'nvim-lua/plenary.nvim'
Plug 'MunifTanjim/nui.nvim'
Plug 'MeanderingProgrammer/render-markdown.nvim'
@@ -163,7 +163,7 @@ add({
monitor = 'main',
depends = {
'nvim-treesitter/nvim-treesitter',
- 'stevearc/dressing.nvim',
+
'nvim-lua/plenary.nvim',
'MunifTanjim/nui.nvim',
'echasnovski/mini.icons'
@@ -194,7 +194,7 @@ end)
-- 必需插件
use 'nvim-treesitter/nvim-treesitter'
- use 'stevearc/dressing.nvim'
+
use 'nvim-lua/plenary.nvim'
use 'MunifTanjim/nui.nvim'
use 'MeanderingProgrammer/render-markdown.nvim'
diff --git a/lua/avante/api.lua b/lua/avante/api.lua
index b559cd4..48da87a 100644
--- a/lua/avante/api.lua
+++ b/lua/avante/api.lua
@@ -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
diff --git a/lua/avante/config.lua b/lua/avante/config.lua
index a6c36b8..34cc039 100644
--- a/lua/avante/config.lua
+++ b/lua/avante/config.lua
@@ -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,
diff --git a/lua/avante/health.lua b/lua/avante/health.lua
index 5902a2d..9935eff 100644
--- a/lua/avante/health.lua
+++ b/lua/avante/health.lua
@@ -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
diff --git a/lua/avante/providers/init.lua b/lua/avante/providers/init.lua
index 9682409..d27ec3d 100644
--- a/lua/avante/providers/init.lua
+++ b/lua/avante/providers/init.lua
@@ -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
diff --git a/lua/avante/ui/input/init.lua b/lua/avante/ui/input/init.lua
new file mode 100644
index 0000000..7c92ab8
--- /dev/null
+++ b/lua/avante/ui/input/init.lua
@@ -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
diff --git a/lua/avante/ui/input/providers/dressing.lua b/lua/avante/ui/input/providers/dressing.lua
new file mode 100644
index 0000000..c192546
--- /dev/null
+++ b/lua/avante/ui/input/providers/dressing.lua
@@ -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
diff --git a/lua/avante/ui/input/providers/native.lua b/lua/avante/ui/input/providers/native.lua
new file mode 100644
index 0000000..84792fb
--- /dev/null
+++ b/lua/avante/ui/input/providers/native.lua
@@ -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
diff --git a/lua/avante/ui/input/providers/snacks.lua b/lua/avante/ui/input/providers/snacks.lua
new file mode 100644
index 0000000..a280e95
--- /dev/null
+++ b/lua/avante/ui/input/providers/snacks.lua
@@ -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
diff --git a/lua/avante/ui/selector/providers/snacks.lua b/lua/avante/ui/selector/providers/snacks.lua
index 1940fe2..3cd5fac 100644
--- a/lua/avante/ui/selector/providers/snacks.lua
+++ b/lua/avante/ui/selector/providers/snacks.lua
@@ -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
diff --git a/plugin/avante.lua b/plugin/avante.lua
index c5690b8..96db02d 100644
--- a/plugin/avante.lua
+++ b/plugin/avante.lua
@@ -129,6 +129,15 @@ cmd(
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)
local arg = vim.trim(opts.args or "")
arg = arg == "" and "history" or arg