From 86b63b2a33b4fa45431a35a541e7f02d4d3d523b Mon Sep 17 00:00:00 2001 From: yetone Date: Sat, 22 Mar 2025 00:42:20 +0800 Subject: [PATCH] chores: refine ui (#1663) --- lua/avante/highlights.lua | 13 +++++- lua/avante/init.lua | 10 +++- lua/avante/sidebar.lua | 96 ++++++++++++++++++++++++++++++++++----- lua/avante/utils/init.lua | 23 ++++++++++ 4 files changed, 127 insertions(+), 15 deletions(-) diff --git a/lua/avante/highlights.lua b/lua/avante/highlights.lua index 0fac9ff..7e1e3e9 100644 --- a/lua/avante/highlights.lua +++ b/lua/avante/highlights.lua @@ -25,6 +25,13 @@ local Highlights = { BUTTON_PRIMARY_HOVER = { name = "AvanteButtonPrimaryHover", fg = "#1e222a", bg = "#56b6c2" }, BUTTON_DANGER = { name = "AvanteButtonDanger", fg = "#1e222a", bg = "#ABB2BF" }, BUTTON_DANGER_HOVER = { name = "AvanteButtonDangerHover", fg = "#1e222a", bg = "#e06c75" }, + AVANTE_SIDEBAR_WIN_SEPARATOR = { name = "AvanteSidebarWinSeparator", link = "FloatBorder" }, + AVANTE_SIDEBAR_WIN_HORIZONTAL_SEPARATOR = { + name = "AvanteSidebarWinHorizontalSeparator", + fg_link = "WinSeparator", + bg_link = "NormalFloat", + }, + AVANTE_SIDEBAR_NORMAL = { name = "AvanteSidebarNormal", link = "NormalFloat" }, } Highlights.conflict = { @@ -54,10 +61,14 @@ function M.setup() end) :each(function(_, hl) if not has_set_colors(hl.name) then + local bg = hl.bg + local fg = hl.fg + if hl.bg_link ~= nil then bg = api.nvim_get_hl(0, { name = hl.bg_link }).bg end + if hl.fg_link ~= nil then fg = api.nvim_get_hl(0, { name = hl.fg_link }).fg end api.nvim_set_hl( 0, hl.name, - { fg = hl.fg or nil, bg = hl.bg or nil, link = hl.link or nil, strikethrough = hl.strikethrough } + { fg = fg or nil, bg = bg or nil, link = hl.link or nil, strikethrough = hl.strikethrough } ) end end) diff --git a/lua/avante/init.lua b/lua/avante/init.lua index 0a55e8c..a9ff786 100644 --- a/lua/avante/init.lua +++ b/lua/avante/init.lua @@ -243,14 +243,20 @@ function H.autocmds() if Config.hints.enabled then M.current.selection:setup_autocmds() end end) + local function setup_colors() + require("avante.highlights").setup() + -- local sidebar = require("avante").get() + -- if sidebar then sidebar:setup_colors() end + end + api.nvim_create_autocmd("ColorSchemePre", { group = H.augroup, - callback = function() require("avante.highlights").setup() end, + callback = setup_colors, }) api.nvim_create_autocmd("ColorScheme", { group = H.augroup, - callback = function() require("avante.highlights").setup() end, + callback = setup_colors, }) -- automatically setup Avante filetype to markdown diff --git a/lua/avante/sidebar.lua b/lua/avante/sidebar.lua index 73d1ae9..306f36c 100644 --- a/lua/avante/sidebar.lua +++ b/lua/avante/sidebar.lua @@ -32,6 +32,7 @@ local Sidebar = {} ---@field winid integer ---@field bufnr integer ---@field selection avante.SelectionResult | nil +---@field old_winhl string | nil ---@class avante.Sidebar ---@field id integer @@ -49,7 +50,7 @@ local Sidebar = {} function Sidebar:new(id) return setmetatable({ id = id, - code = { bufnr = 0, winid = 0, selection = nil }, + code = { bufnr = 0, winid = 0, selection = nil, old_winhl = nil }, winids = { result_container = 0, selected_files_container = 0, @@ -130,9 +131,58 @@ function Sidebar:open(opts) end vim.cmd("wincmd =") + return self end +function Sidebar:setup_colors() + self:set_code_winhl() + vim.api.nvim_create_autocmd("WinNew", { + group = self.augroup, + callback = function() + for _, winid in ipairs(vim.api.nvim_list_wins()) do + if not vim.api.nvim_win_is_valid(winid) or self:is_sidebar_winid(winid) then goto continue end + local winhl = vim.wo[winid].winhl + if + winhl:find(Highlights.AVANTE_SIDEBAR_WIN_SEPARATOR) + and not Utils.should_hidden_border(self.code.winid, winid) + then + vim.wo[winid].winhl = self.code.old_winhl or "" + end + ::continue:: + end + self:set_code_winhl() + end, + }) +end + +function Sidebar:set_code_winhl() + if Utils.should_hidden_border(self.code.winid, self.winids.result_container) then + Utils.debug("setting winhl") + local old_winhl = vim.wo[self.code.winid].winhl + if self.code.old_winhl == nil then + self.code.old_winhl = old_winhl + else + old_winhl = self.code.old_winhl + end + local pieces = vim.split(old_winhl or "", ",") + local new_pieces = {} + for _, piece in ipairs(pieces) do + if not piece:find("WinSeparator:") and piece ~= "" then table.insert(new_pieces, piece) end + end + table.insert(new_pieces, "WinSeparator:" .. Highlights.AVANTE_SIDEBAR_WIN_SEPARATOR) + local new_winhl = table.concat(new_pieces, ",") + vim.wo[self.code.winid].winhl = new_winhl + end +end + +function Sidebar:recover_code_winhl() + if self.code.old_winhl ~= nil then + vim.wo[self.code.winid].winhl = self.code.old_winhl + self.code.old_winhl = nil + end +end + ---@class SidebarCloseOptions ---@field goto_code_win? boolean @@ -147,6 +197,8 @@ function Sidebar:close(opts) fn.win_gotoid(self.code.winid) end + self:recover_code_winhl() + vim.cmd("wincmd =") end @@ -1396,13 +1448,15 @@ local base_win_options = { relativenumber = false, winfixwidth = true, list = false, - winhl = "", linebreak = true, breakindent = true, wrap = false, cursorline = false, fillchars = "eob: ", - winhighlight = "CursorLine:Normal,CursorColumn:Normal", + winhl = "CursorLine:Normal,CursorColumn:Normal,WinSeparator:" + .. Highlights.AVANTE_SIDEBAR_WIN_SEPARATOR + .. ",Normal:" + .. Highlights.AVANTE_SIDEBAR_NORMAL, winbar = "", statusline = "", } @@ -1414,14 +1468,24 @@ function Sidebar:render_header(winid, bufnr, header_text, hl, reverse_hl) if not Config.windows.sidebar_header.rounded then header_text = " " .. header_text .. " " end - local winbar_text = "%#Normal#" + local win_width = vim.api.nvim_win_get_width(winid) - if Config.windows.sidebar_header.align == "center" then - winbar_text = winbar_text .. "%=" - elseif Config.windows.sidebar_header.align == "right" then - winbar_text = winbar_text .. "%=" + local padding = math.floor((win_width - #header_text) / 2) + if Config.windows.sidebar_header.align ~= "center" then padding = win_width - #header_text end + + local winbar_text = "%#" .. Highlights.AVANTE_SIDEBAR_WIN_HORIZONTAL_SEPARATOR .. "#" + + if Config.windows.sidebar_header.align ~= "left" then + if not Config.windows.sidebar_header.rounded then winbar_text = winbar_text .. " " end + winbar_text = winbar_text .. string.rep("-", padding) end + -- if Config.windows.sidebar_header.align == "center" then + -- winbar_text = winbar_text .. "%=" + -- elseif Config.windows.sidebar_header.align == "right" then + -- winbar_text = winbar_text .. "%=" + -- end + if Config.windows.sidebar_header.rounded then winbar_text = winbar_text .. "%#" .. reverse_hl .. "#" .. Utils.icon("", "『") .. "%#" .. hl .. "#" else @@ -1431,8 +1495,11 @@ function Sidebar:render_header(winid, bufnr, header_text, hl, reverse_hl) if Config.windows.sidebar_header.rounded then winbar_text = winbar_text .. "%#" .. reverse_hl .. "#" .. Utils.icon("", "』") end - winbar_text = winbar_text .. "%#Normal#" - if Config.windows.sidebar_header.align == "center" then winbar_text = winbar_text .. "%=" end + -- if Config.windows.sidebar_header.align == "center" then winbar_text = winbar_text .. "%=" end + + winbar_text = winbar_text .. "%#" .. Highlights.AVANTE_SIDEBAR_WIN_HORIZONTAL_SEPARATOR .. "#" + if Config.windows.sidebar_header.align ~= "right" then winbar_text = winbar_text .. string.rep("-", padding) end + api.nvim_set_option_value("winbar", winbar_text, { win = winid }) end @@ -1831,7 +1898,7 @@ function Sidebar:on_mount(opts) callback = function(args) local closed_winid = tonumber(args.match) if closed_winid == self.winids.selected_files_container then return end - if not self:is_focused_on(closed_winid) then return end + if not self:is_sidebar_winid(closed_winid) then return end self:close() end, }) @@ -1952,7 +2019,7 @@ function Sidebar:is_focused_on_result() return self:is_open() and self.result_container and self.result_container.winid == api.nvim_get_current_win() end -function Sidebar:is_focused_on(winid) +function Sidebar:is_sidebar_winid(winid) for _, stored_winid in pairs(self.winids) do if stored_winid == winid then return true end end @@ -2354,6 +2421,9 @@ function Sidebar:create_selected_code_container() winid = self.input_container.winid, }, buf_options = buf_options, + win_options = { + winhl = base_win_options.winhl, + }, size = { height = selected_code_size + 3, }, @@ -3113,6 +3183,8 @@ function Sidebar:render(opts) self:on_mount(opts) + self:setup_colors() + return self end diff --git a/lua/avante/utils/init.lua b/lua/avante/utils/init.lua index 32d9a0b..da7efbd 100644 --- a/lua/avante/utils/init.lua +++ b/lua/avante/utils/init.lua @@ -1181,4 +1181,27 @@ function M.random_string(length) return table.concat(result) end +function M.is_left_adjacent(win_a, win_b) + if not vim.api.nvim_win_is_valid(win_a) or not vim.api.nvim_win_is_valid(win_b) then return false end + + local _, col_a = unpack(vim.fn.win_screenpos(win_a)) + local _, col_b = unpack(vim.fn.win_screenpos(win_b)) + local width_a = vim.api.nvim_win_get_width(win_a) + + local right_edge_a = col_a + width_a + + return right_edge_a + 1 == col_b +end + +function M.is_top_adjacent(win_a, win_b) + local row_a, _ = unpack(vim.fn.win_screenpos(win_a)) + local row_b, _ = unpack(vim.fn.win_screenpos(win_b)) + local height_a = vim.api.nvim_win_get_height(win_a) + return row_a + height_a + 1 == row_b +end + +function M.should_hidden_border(win_a, win_b) + return M.is_left_adjacent(win_a, win_b) or M.is_top_adjacent(win_a, win_b) +end + return M