From 58af2b7f928528c16819239ba435803aa8a9d9ea Mon Sep 17 00:00:00 2001 From: Aaron Pham Date: Sun, 18 Aug 2024 06:07:29 -0400 Subject: [PATCH] fix(ui): use dressing.nvim for better input support (#58) * fix(ui): use dressing.nvim for better input support Signed-off-by: Aaron Pham * chore: add small docs on setting up dependencies Signed-off-by: Aaron Pham * chore: update docs Signed-off-by: Aaron Pham * revert: add back quick docs for setup Signed-off-by: Aaron Pham * chore: update readme Signed-off-by: Aaron Pham * Update lua/avante/ui/dressing.lua * Update lua/avante/ui/dressing.lua --------- Signed-off-by: Aaron Pham --- README.md | 10 +++-- lua/avante/ai_bot.lua | 88 ++++++-------------------------------- lua/avante/diff.lua | 10 ++--- lua/avante/ui/dressing.lua | 62 +++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 84 deletions(-) create mode 100644 lua/avante/ui/dressing.lua diff --git a/README.md b/README.md index 0826204..8213a08 100644 --- a/README.md +++ b/README.md @@ -25,18 +25,22 @@ Install `avante.nvim` using [lazy.nvim](https://github.com/folke/lazy.nvim): { "yetone/avante.nvim", event = "VeryLazy", - opts = {}, build = "make", + opts = { + -- add any opts here + }, dependencies = { "nvim-tree/nvim-web-devicons", + "stevearc/dressing.nvim", + "nvim-lua/plenary.nvim", { "grapp-dev/nui-components.nvim", dependencies = { "MunifTanjim/nui.nvim" } }, - "nvim-lua/plenary.nvim", - { -- Optional + --- The below is optional, make sure to setup it properly if you have lazy=true + { 'MeanderingProgrammer/render-markdown.nvim', opts = { file_types = { "markdown", "Avante" }, diff --git a/lua/avante/ai_bot.lua b/lua/avante/ai_bot.lua index 8c5d0de..5e33f43 100644 --- a/lua/avante/ai_bot.lua +++ b/lua/avante/ai_bot.lua @@ -2,8 +2,6 @@ local fn = vim.fn local api = vim.api local curl = require("plenary.curl") -local Input = require("nui.input") -local Event = require("nui.utils.autocmd").event local Utils = require("avante.utils") local Config = require("avante.config") @@ -30,43 +28,6 @@ E = setmetatable(E, { end, }) --- courtesy of https://github.com/MunifTanjim/nui.nvim/wiki/nui.input -local SecretInput = Input:extend("SecretInput") - -function SecretInput:init(popup_options, options) - assert( - not options.conceal_char or vim.api.nvim_strwidth(options.conceal_char) == 1, - "conceal_char must be a single char" - ) - - popup_options.win_options = vim.tbl_deep_extend("force", popup_options.win_options or {}, { - conceallevel = 2, - concealcursor = "nvi", - }) - - SecretInput.super.init(self, popup_options, options) - - self._.conceal_char = type(options.conceal_char) == "nil" and "*" or options.conceal_char -end - -function SecretInput:mount() - SecretInput.super.mount(self) - - local conceal_char = self._.conceal_char - local prompt_length = vim.api.nvim_strwidth(vim.fn.prompt_getprompt(self.bufnr)) - - vim.api.nvim_buf_call(self.bufnr, function() - vim.cmd(string.format( - [[ - syn region SecretValue start=/^/ms=s+%s end=/$/ contains=SecretChar - syn match SecretChar /./ contained conceal %s - ]], - prompt_length, - conceal_char and "cchar=" .. (conceal_char or "*") or "" - )) - end) -end - --- return the environment variable name for the given provider ---@param provider? Provider ---@return string the envvar key @@ -78,45 +39,29 @@ E.key = function(provider) end E.setup = function(var) + local Dressing = require("avante.ui.dressing") + if E._once then return end - local input = SecretInput({ - position = "50%", - size = { - width = 40, - }, - border = { - style = "single", - text = { - top = "Enter " .. var, - top_align = "center", - }, - }, - win_options = { - winhighlight = "Normal:Normal,FloatBorder:Normal", - }, - }, { - prompt = "> ", - default_value = "", - on_submit = function(value) + ---@param value string + ---@return nil + local function on_confirm(value) + if value then vim.fn.setenv(var, value) - end, - on_close = function() + E._once = true + else if not E[Config.provider] then vim.notify_once("Failed to set " .. var .. ". Avante won't work as expected", vim.log.levels.WARN) end - end, - }) + end + end api.nvim_create_autocmd({ "BufEnter", "BufWinEnter" }, { pattern = "*", + once = true, callback = function() - if E._once then - return - end - vim.defer_fn(function() -- only mount if given buffer is not of buftype ministarter, dashboard, alpha, qf local exclude_buftypes = { "dashboard", "alpha", "qf", "nofile" } @@ -135,20 +80,11 @@ E.setup = function(var) not vim.tbl_contains(exclude_buftypes, vim.bo.buftype) and not vim.tbl_contains(exclude_filetypes, vim.bo.filetype) then - E._once = true - input:mount() + Dressing.initialize_input_buffer({ opts = { prompt = "Enter " .. var .. ": " }, on_confirm = on_confirm }) end end, 200) end, }) - - input:map("n", "", function() - input:unmount() - end, { noremap = true }) - - input:on(Event.BufLeave, function() - input:unmount() - end) end local system_prompt = [[ diff --git a/lua/avante/diff.lua b/lua/avante/diff.lua index 827acb4..4a7ef1d 100644 --- a/lua/avante/diff.lua +++ b/lua/avante/diff.lua @@ -525,20 +525,20 @@ function M.setup() set_plug_mappings() - api.nvim_create_augroup(AUGROUP_NAME, { clear = true }) + local augroup = api.nvim_create_augroup(AUGROUP_NAME, { clear = true }) api.nvim_create_autocmd("ColorScheme", { - group = AUGROUP_NAME, + group = augroup, callback = function() set_highlights(Config.diff.highlights) end, }) api.nvim_create_autocmd("User", { - group = AUGROUP_NAME, + group = augroup, pattern = "AvanteConflictDetected", callback = function() local bufnr = api.nvim_get_current_buf() - vim.diagnostic.enable(not vim.diagnostic.is_enabled(), { bufnr = bufnr }) + vim.diagnostic.enable(false, { bufnr = bufnr }) setup_buffer_mappings(bufnr) end, }) @@ -548,7 +548,7 @@ function M.setup() pattern = "AvanteConflictResolved", callback = function() local bufnr = api.nvim_get_current_buf() - vim.diagnostic.enable(not vim.diagnostic.is_enabled(), { bufnr = bufnr }) + vim.diagnostic.enable(true, { bufnr = bufnr }) clear_buffer_mappings(bufnr) end, }) diff --git a/lua/avante/ui/dressing.lua b/lua/avante/ui/dressing.lua new file mode 100644 index 0000000..ff62cdf --- /dev/null +++ b/lua/avante/ui/dressing.lua @@ -0,0 +1,62 @@ +local api, fn = vim.api, vim.fn + +---@class avante.Dressing +local H = {} + +local C = { + filetype = "DressingInput", + conceal_char = "*", + close_window = function() + require("dressing.input").close() + end, +} + +---@class avante.DressingState +local state = { + winid = nil, ---@type integer + input_winid = nil, ---@type integer + input_bufnr = nil, ---@type integer +} + +---@param options {opts: table, on_confirm: fun(value: string): nil} See vim.ui.input for more info +H.initialize_input_buffer = function(options) + state.winid = api.nvim_get_current_win() + vim.ui.input(vim.tbl_deep_extend("force", { default = "" }, options.opts), options.on_confirm) + for _, winid in ipairs(api.nvim_list_wins()) do + local bufnr = api.nvim_win_get_buf(winid) + if vim.bo[bufnr].filetype == C.filetype then + state.input_winid = winid + state.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(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 %s + ]], + prompt_length, + "cchar=*" + )) + end) +end + +---@param switch_buffer? boolean To switch back original buffer, default to tru +H.teardown = function(switch_buffer) + switch_buffer = switch_buffer or true + + if state.input_winid and api.nvim_win_is_valid(state.input_winid) then + C.close_window() + state.input_winid = nil + if switch_buffer then + pcall(api.nvim_set_current_win, state.winid) + end + end +end + +return H