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()
sidebar:update_content_with_history()
sidebar:create_todos_container()
sidebar:initialize_token_count()
vim.schedule(function() sidebar:focus_input() end)
end)
end)

View File

@@ -66,6 +66,7 @@ Sidebar.__index = Sidebar
---@field input_hint_window integer | nil
---@field ask_opts AskOptions
---@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()
function Sidebar:new(id)
@@ -97,7 +98,8 @@ function Sidebar:new(id)
input_hint_window = nil,
ask_opts = {},
old_result_lines = {},
-- 缓存相关字段
token_count = nil,
-- Cache-related fields
_cached_history_lines = nil,
_history_cache_invalidated = true,
}, Sidebar)
@@ -137,6 +139,7 @@ function Sidebar:reset()
self.input_container = nil
self.scroll = true
self.old_result_lines = {}
self.token_count = nil
end
---@class SidebarOpenOptions: AskOptions
@@ -259,7 +262,10 @@ function Sidebar:focus()
end
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
function Sidebar:is_open() return Utils.is_valid_container(self.result_container, true) end
@@ -2171,44 +2177,34 @@ function Sidebar:show_input_hint()
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 function show()
local buf = api.nvim_create_buf(false, true)
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 })
-- Get the current window size
local win_width = api.nvim_win_get_width(self.input_container.winid)
local width = #hint_text
-- Set the floating window options
local win_opts = {
relative = "win",
win = self.input_container.winid,
width = width,
height = 1,
row = self:get_input_float_window_row(),
col = math.max(win_width - width, 0), -- Display in the bottom right corner
style = "minimal",
border = "none",
focusable = false,
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()
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 buf = api.nvim_create_buf(false, true)
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 })
-- Get the current window size
local win_width = api.nvim_win_get_width(self.input_container.winid)
local width = #hint_text
-- Create the floating window
self.input_hint_window = api.nvim_open_win(buf, false, {
relative = "win",
win = self.input_container.winid,
width = width,
height = 1,
row = self:get_input_float_window_row(),
col = math.max(win_width - width, 0), -- Display in the bottom right corner
style = "minimal",
border = "none",
focusable = false,
zindex = 100,
})
end
function Sidebar:close_selected_files_hint()
@@ -2248,6 +2244,7 @@ function Sidebar:show_selected_files_hint()
end
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
self.chat_history = Path.history.load(self.code.bufnr)
self._history_cache_invalidated = true
@@ -2541,7 +2538,7 @@ function Sidebar:get_history_messages_for_api(opts)
end
---@param request string
---@param cb fun(opts: AvanteGeneratePromptsOptions): nil
---@param cb? fun(opts: AvanteGeneratePromptsOptions): nil
function Sidebar:get_generate_prompts_options(request, cb)
local filetype = api.nvim_get_option_value("filetype", { buf = self.code.bufnr })
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
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
function Sidebar:create_input_container()
@@ -2968,11 +2971,14 @@ function Sidebar:create_input_container()
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" }, {
group = self.augroup,
buffer = self.input_container.bufnr,
callback = function()
self:show_input_hint()
debounced_show_input_hint()
place_sign_at_first_line(self.input_container.bufnr)
end,
})
@@ -2985,10 +2991,8 @@ function Sidebar:create_input_container()
api.nvim_create_autocmd("WinClosed", {
group = self.augroup,
callback = function(args)
local closed_winid = tonumber(args.match)
if closed_winid == self.input_container.winid then self:close_input_hint() end
end,
pattern = tostring(self.input_container.winid),
callback = function() self:close_input_hint() end,
})
api.nvim_create_autocmd("BufEnter", {
@@ -3002,27 +3006,17 @@ function Sidebar:create_input_container()
api.nvim_create_autocmd("BufLeave", {
group = self.augroup,
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()
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
vim.cmd("noautocmd stopinsert")
self:close_input_hint()
end,
})
-- Close hint when exiting insert mode
-- Update hint on mode change as submit key sequence may be different
api.nvim_create_autocmd("ModeChanged", {
group = self.augroup,
pattern = "i:*",
callback = function()
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,
buffer = self.input_container.bufnr,
callback = function() self:show_input_hint() end,
})
api.nvim_create_autocmd("WinEnter", {
@@ -3045,9 +3039,6 @@ function Sidebar:create_input_container()
end,
})
-- Clear hint when leaving the window
self.input_container:on(event.BufLeave, function() self:close_input_hint() end, {})
self:refresh_winids()
end