fix: slow typing in input window and other input hint optimizations (#2418)

This commit is contained in:
Dmitry Torokhov
2025-07-07 01:45:35 -07:00
committed by GitHub
parent 014010b022
commit b051ce449a
2 changed files with 54 additions and 62 deletions

View File

@@ -245,6 +245,7 @@ function M.select_history()
local sidebar = require("avante").get() local sidebar = require("avante").get()
sidebar:update_content_with_history() sidebar:update_content_with_history()
sidebar:create_todos_container() sidebar:create_todos_container()
sidebar:initialize_token_count()
vim.schedule(function() sidebar:focus_input() end) vim.schedule(function() sidebar:focus_input() end)
end) end)
end) end)

View File

@@ -66,6 +66,7 @@ Sidebar.__index = Sidebar
---@field input_hint_window integer | nil ---@field input_hint_window integer | nil
---@field ask_opts AskOptions ---@field ask_opts AskOptions
---@field old_result_lines avante.ui.Line[] ---@field old_result_lines avante.ui.Line[]
---@field token_count integer | nil
---@param id integer the tabpage id retrieved from api.nvim_get_current_tabpage() ---@param id integer the tabpage id retrieved from api.nvim_get_current_tabpage()
function Sidebar:new(id) function Sidebar:new(id)
@@ -97,7 +98,8 @@ function Sidebar:new(id)
input_hint_window = nil, input_hint_window = nil,
ask_opts = {}, ask_opts = {},
old_result_lines = {}, old_result_lines = {},
-- 缓存相关字段 token_count = nil,
-- Cache-related fields
_cached_history_lines = nil, _cached_history_lines = nil,
_history_cache_invalidated = true, _history_cache_invalidated = true,
}, Sidebar) }, Sidebar)
@@ -137,6 +139,7 @@ function Sidebar:reset()
self.input_container = nil self.input_container = nil
self.scroll = true self.scroll = true
self.old_result_lines = {} self.old_result_lines = {}
self.token_count = nil
end end
---@class SidebarOpenOptions: AskOptions ---@class SidebarOpenOptions: AskOptions
@@ -259,7 +262,10 @@ function Sidebar:focus()
end end
function Sidebar:focus_input() function Sidebar:focus_input()
if Utils.is_valid_container(self.input_container, true) then api.nvim_set_current_win(self.input_container.winid) end if Utils.is_valid_container(self.input_container, true) then
api.nvim_set_current_win(self.input_container.winid)
self:show_input_hint()
end
end end
function Sidebar:is_open() return Utils.is_valid_container(self.result_container, true) end function Sidebar:is_open() return Utils.is_valid_container(self.result_container, true) end
@@ -2171,8 +2177,13 @@ function Sidebar:show_input_hint()
self:close_input_hint() -- Close the existing hint window self:close_input_hint() -- Close the existing hint window
local hint_text = (fn.mode() ~= "i" and Config.mappings.submit.normal or Config.mappings.submit.insert) .. ": submit" local hint_text = (fn.mode() ~= "i" and Config.mappings.submit.normal or Config.mappings.submit.insert) .. ": submit"
if Config.behaviour.enable_token_counting then
local input_value = table.concat(api.nvim_buf_get_lines(self.input_container.bufnr, 0, -1, false), "\n")
if self.token_count == nil then self:initialize_token_count() end
local tokens = self.token_count + Utils.tokens.calculate_tokens(input_value)
hint_text = "Tokens: " .. tostring(tokens) .. "; " .. hint_text
end
local function show()
local buf = api.nvim_create_buf(false, true) local buf = api.nvim_create_buf(false, true)
api.nvim_buf_set_lines(buf, 0, -1, false, { hint_text }) api.nvim_buf_set_lines(buf, 0, -1, false, { hint_text })
api.nvim_buf_set_extmark(buf, INPUT_HINT_NAMESPACE, 0, 0, { hl_group = "AvantePopupHint", end_col = #hint_text }) api.nvim_buf_set_extmark(buf, INPUT_HINT_NAMESPACE, 0, 0, { hl_group = "AvantePopupHint", end_col = #hint_text })
@@ -2181,8 +2192,8 @@ function Sidebar:show_input_hint()
local win_width = api.nvim_win_get_width(self.input_container.winid) local win_width = api.nvim_win_get_width(self.input_container.winid)
local width = #hint_text local width = #hint_text
-- Set the floating window options -- Create the floating window
local win_opts = { self.input_hint_window = api.nvim_open_win(buf, false, {
relative = "win", relative = "win",
win = self.input_container.winid, win = self.input_container.winid,
width = width, width = width,
@@ -2193,22 +2204,7 @@ function Sidebar:show_input_hint()
border = "none", border = "none",
focusable = false, focusable = false,
zindex = 100, zindex = 100,
} })
-- Create the floating window
self.input_hint_window = api.nvim_open_win(buf, false, win_opts)
end
if Config.behaviour.enable_token_counting then
local input_value = table.concat(api.nvim_buf_get_lines(self.input_container.bufnr, 0, -1, false), "\n")
self:get_generate_prompts_options(input_value, function(generate_prompts_options)
local tokens = Llm.calculate_tokens(generate_prompts_options) + Utils.tokens.calculate_tokens(input_value)
hint_text = "Tokens: " .. tostring(tokens) .. "; " .. hint_text
show()
end)
else
show()
end
end end
function Sidebar:close_selected_files_hint() function Sidebar:close_selected_files_hint()
@@ -2248,6 +2244,7 @@ function Sidebar:show_selected_files_hint()
end end
function Sidebar:reload_chat_history() function Sidebar:reload_chat_history()
self.token_count = nil
if not self.code.bufnr or not api.nvim_buf_is_valid(self.code.bufnr) then return end if not self.code.bufnr or not api.nvim_buf_is_valid(self.code.bufnr) then return end
self.chat_history = Path.history.load(self.code.bufnr) self.chat_history = Path.history.load(self.code.bufnr)
self._history_cache_invalidated = true self._history_cache_invalidated = true
@@ -2541,7 +2538,7 @@ function Sidebar:get_history_messages_for_api(opts)
end end
---@param request string ---@param request string
---@param cb fun(opts: AvanteGeneratePromptsOptions): nil ---@param cb? fun(opts: AvanteGeneratePromptsOptions): nil
function Sidebar:get_generate_prompts_options(request, cb) function Sidebar:get_generate_prompts_options(request, cb)
local filetype = api.nvim_get_option_value("filetype", { buf = self.code.bufnr }) local filetype = api.nvim_get_option_value("filetype", { buf = self.code.bufnr })
local file_ext = nil local file_ext = nil
@@ -2634,7 +2631,13 @@ function Sidebar:get_generate_prompts_options(request, cb)
if self.chat_history.memory then prompts_opts.memory = self.chat_history.memory.content end if self.chat_history.memory then prompts_opts.memory = self.chat_history.memory.content end
cb(prompts_opts) if Config.behaviour.enable_token_counting then self.token_count = Llm.calculate_tokens(prompts_opts) end
if cb then cb(prompts_opts) end
end
function Sidebar:initialize_token_count()
if Config.behaviour.enable_token_counting then self:get_generate_prompts_options("") end
end end
function Sidebar:create_input_container() function Sidebar:create_input_container()
@@ -2968,11 +2971,14 @@ function Sidebar:create_input_container()
callback = function() end, callback = function() end,
}) })
local debounced_show_input_hint = Utils.debounce(function()
if vim.api.nvim_win_is_valid(self.input_container.winid) then self:show_input_hint() end
end, 200)
api.nvim_create_autocmd({ "TextChanged", "TextChangedI", "VimResized" }, { api.nvim_create_autocmd({ "TextChanged", "TextChangedI", "VimResized" }, {
group = self.augroup, group = self.augroup,
buffer = self.input_container.bufnr, buffer = self.input_container.bufnr,
callback = function() callback = function()
self:show_input_hint() debounced_show_input_hint()
place_sign_at_first_line(self.input_container.bufnr) place_sign_at_first_line(self.input_container.bufnr)
end, end,
}) })
@@ -2985,10 +2991,8 @@ function Sidebar:create_input_container()
api.nvim_create_autocmd("WinClosed", { api.nvim_create_autocmd("WinClosed", {
group = self.augroup, group = self.augroup,
callback = function(args) pattern = tostring(self.input_container.winid),
local closed_winid = tonumber(args.match) callback = function() self:close_input_hint() end,
if closed_winid == self.input_container.winid then self:close_input_hint() end
end,
}) })
api.nvim_create_autocmd("BufEnter", { api.nvim_create_autocmd("BufEnter", {
@@ -3002,27 +3006,17 @@ function Sidebar:create_input_container()
api.nvim_create_autocmd("BufLeave", { api.nvim_create_autocmd("BufLeave", {
group = self.augroup, group = self.augroup,
buffer = self.input_container.bufnr, buffer = self.input_container.bufnr,
callback = function() vim.cmd("noautocmd stopinsert") end,
})
-- Show hint in insert mode
api.nvim_create_autocmd("ModeChanged", {
group = self.augroup,
pattern = "*:i",
callback = function() callback = function()
local cur_buf = api.nvim_get_current_buf() vim.cmd("noautocmd stopinsert")
if self.input_container and cur_buf == self.input_container.bufnr then self:show_input_hint() end self:close_input_hint()
end, end,
}) })
-- Close hint when exiting insert mode -- Update hint on mode change as submit key sequence may be different
api.nvim_create_autocmd("ModeChanged", { api.nvim_create_autocmd("ModeChanged", {
group = self.augroup, group = self.augroup,
pattern = "i:*", buffer = self.input_container.bufnr,
callback = function() callback = function() self:show_input_hint() end,
local cur_buf = api.nvim_get_current_buf()
if self.input_container and cur_buf == self.input_container.bufnr then self:show_input_hint() end
end,
}) })
api.nvim_create_autocmd("WinEnter", { api.nvim_create_autocmd("WinEnter", {
@@ -3045,9 +3039,6 @@ function Sidebar:create_input_container()
end, end,
}) })
-- Clear hint when leaving the window
self.input_container:on(event.BufLeave, function() self:close_input_hint() end, {})
self:refresh_winids() self:refresh_winids()
end end