fix: slow typing in input window and other input hint optimizations (#2418)
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user