2024-09-03 05:12:07 -04:00
|
|
|
|
local Utils = require("avante.utils")
|
|
|
|
|
local Config = require("avante.config")
|
|
|
|
|
local Llm = require("avante.llm")
|
2024-09-03 21:47:01 -04:00
|
|
|
|
local Provider = require("avante.providers")
|
2024-09-26 03:45:49 +08:00
|
|
|
|
local RepoMap = require("avante.repo_map")
|
2024-08-17 22:29:05 +08:00
|
|
|
|
|
|
|
|
|
local api = vim.api
|
|
|
|
|
local fn = vim.fn
|
|
|
|
|
|
2024-09-03 05:12:07 -04:00
|
|
|
|
local NAMESPACE = api.nvim_create_namespace("avante_selection")
|
|
|
|
|
local SELECTED_CODE_NAMESPACE = api.nvim_create_namespace("avante_selected_code")
|
2024-08-17 22:29:05 +08:00
|
|
|
|
local PRIORITY = vim.highlight.priorities.user
|
|
|
|
|
|
2024-08-27 13:13:38 -04:00
|
|
|
|
local EDITING_INPUT_START_SPINNER_PATTERN = "AvanteEditingInputStartSpinner"
|
|
|
|
|
local EDITING_INPUT_STOP_SPINNER_PATTERN = "AvanteEditingInputStopSpinner"
|
2024-08-27 22:44:40 +08:00
|
|
|
|
|
2024-08-18 05:36:30 -04:00
|
|
|
|
---@class avante.Selection
|
2024-08-27 22:44:40 +08:00
|
|
|
|
---@field selection avante.SelectionResult | nil
|
|
|
|
|
---@field cursor_pos table | nil
|
|
|
|
|
---@field shortcuts_extmark_id integer | nil
|
2024-08-27 23:47:15 +08:00
|
|
|
|
---@field selected_code_extmark_id integer | nil
|
2024-08-27 22:44:40 +08:00
|
|
|
|
---@field augroup integer | nil
|
|
|
|
|
---@field editing_input_bufnr integer | nil
|
|
|
|
|
---@field editing_input_winid integer | nil
|
|
|
|
|
---@field editing_input_shortcuts_hints_winid integer | nil
|
|
|
|
|
---@field code_winid integer | nil
|
2024-08-17 22:29:05 +08:00
|
|
|
|
local Selection = {}
|
|
|
|
|
|
2024-08-18 05:36:30 -04:00
|
|
|
|
Selection.did_setup = false
|
|
|
|
|
|
2024-08-22 14:46:08 +08:00
|
|
|
|
---@param id integer the tabpage id retrieved from api.nvim_get_current_tabpage()
|
2024-08-18 05:36:30 -04:00
|
|
|
|
function Selection:new(id)
|
2024-08-17 22:29:05 +08:00
|
|
|
|
return setmetatable({
|
2024-08-27 22:44:40 +08:00
|
|
|
|
shortcuts_extmark_id = nil,
|
2024-08-27 23:47:15 +08:00
|
|
|
|
selected_code_extmark_id = nil,
|
2024-08-18 05:36:30 -04:00
|
|
|
|
augroup = api.nvim_create_augroup("avante_selection_" .. id, { clear = true }),
|
2024-08-27 22:44:40 +08:00
|
|
|
|
selection = nil,
|
|
|
|
|
cursor_pos = nil,
|
|
|
|
|
editing_input_bufnr = nil,
|
|
|
|
|
editing_input_winid = nil,
|
|
|
|
|
editing_input_shortcuts_hints_winid = nil,
|
|
|
|
|
code_winid = nil,
|
2024-08-17 22:29:05 +08:00
|
|
|
|
}, { __index = self })
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Selection:get_virt_text_line()
|
2024-09-03 05:12:07 -04:00
|
|
|
|
local current_pos = fn.getpos(".")
|
2024-08-17 22:29:05 +08:00
|
|
|
|
|
|
|
|
|
-- Get the current and start position line numbers
|
|
|
|
|
local current_line = current_pos[2] - 1 -- 0-indexed
|
|
|
|
|
|
|
|
|
|
-- Ensure line numbers are not negative and don't exceed buffer range
|
|
|
|
|
local total_lines = api.nvim_buf_line_count(0)
|
2024-09-03 04:19:54 -04:00
|
|
|
|
if current_line < 0 then current_line = 0 end
|
|
|
|
|
if current_line >= total_lines then current_line = total_lines - 1 end
|
2024-08-17 22:29:05 +08:00
|
|
|
|
|
|
|
|
|
-- Take the first line of the selection to ensure virt_text is always in the top right corner
|
|
|
|
|
return current_line
|
|
|
|
|
end
|
|
|
|
|
|
2024-08-27 22:44:40 +08:00
|
|
|
|
function Selection:show_shortcuts_hints_popup()
|
|
|
|
|
self:close_shortcuts_hints_popup()
|
2024-08-17 22:29:05 +08:00
|
|
|
|
|
2024-08-27 13:13:38 -04:00
|
|
|
|
local hint_text = string.format(" [%s: ask, %s: edit] ", Config.mappings.ask, Config.mappings.edit)
|
2024-08-17 22:29:05 +08:00
|
|
|
|
|
|
|
|
|
local virt_text_line = self:get_virt_text_line()
|
|
|
|
|
|
2024-08-27 22:44:40 +08:00
|
|
|
|
self.shortcuts_extmark_id = api.nvim_buf_set_extmark(0, NAMESPACE, virt_text_line, -1, {
|
2024-09-15 10:53:33 -04:00
|
|
|
|
virt_text = { { hint_text, "AvanteInlineHint" } },
|
2024-08-17 22:29:05 +08:00
|
|
|
|
virt_text_pos = "eol",
|
|
|
|
|
priority = PRIORITY,
|
|
|
|
|
})
|
|
|
|
|
end
|
|
|
|
|
|
2024-08-27 22:44:40 +08:00
|
|
|
|
function Selection:close_shortcuts_hints_popup()
|
|
|
|
|
if self.shortcuts_extmark_id then
|
|
|
|
|
api.nvim_buf_del_extmark(0, NAMESPACE, self.shortcuts_extmark_id)
|
|
|
|
|
self.shortcuts_extmark_id = nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Selection:close_editing_input()
|
|
|
|
|
self:close_editing_input_shortcuts_hints()
|
2024-09-03 14:03:59 +08:00
|
|
|
|
Llm.cancel_inflight_request()
|
2024-09-03 05:12:07 -04:00
|
|
|
|
if api.nvim_get_mode().mode == "i" then vim.cmd([[stopinsert]]) end
|
2024-08-27 22:44:40 +08:00
|
|
|
|
if self.editing_input_winid and api.nvim_win_is_valid(self.editing_input_winid) then
|
|
|
|
|
api.nvim_win_close(self.editing_input_winid, true)
|
|
|
|
|
self.editing_input_winid = nil
|
|
|
|
|
end
|
2024-08-27 23:47:15 +08:00
|
|
|
|
if self.code_winid and api.nvim_win_is_valid(self.code_winid) then
|
|
|
|
|
local code_bufnr = api.nvim_win_get_buf(self.code_winid)
|
|
|
|
|
api.nvim_buf_clear_namespace(code_bufnr, SELECTED_CODE_NAMESPACE, 0, -1)
|
|
|
|
|
if self.selected_code_extmark_id then
|
|
|
|
|
api.nvim_buf_del_extmark(code_bufnr, SELECTED_CODE_NAMESPACE, self.selected_code_extmark_id)
|
|
|
|
|
self.selected_code_extmark_id = nil
|
|
|
|
|
end
|
|
|
|
|
end
|
2024-08-27 22:44:40 +08:00
|
|
|
|
if self.cursor_pos and self.code_winid then
|
|
|
|
|
vim.schedule(function()
|
2024-08-31 12:30:22 +08:00
|
|
|
|
local bufnr = api.nvim_win_get_buf(self.code_winid)
|
|
|
|
|
local line_count = api.nvim_buf_line_count(bufnr)
|
|
|
|
|
local row = math.min(self.cursor_pos[1], line_count)
|
|
|
|
|
local line = api.nvim_buf_get_lines(bufnr, row - 1, row, true)[1] or ""
|
|
|
|
|
local col = math.min(self.cursor_pos[2], #line)
|
|
|
|
|
api.nvim_win_set_cursor(self.code_winid, { row, col })
|
2024-08-27 22:44:40 +08:00
|
|
|
|
end)
|
|
|
|
|
end
|
|
|
|
|
if self.editing_input_bufnr and api.nvim_buf_is_valid(self.editing_input_bufnr) then
|
|
|
|
|
api.nvim_buf_delete(self.editing_input_bufnr, { force = true })
|
|
|
|
|
self.editing_input_bufnr = nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Selection:close_editing_input_shortcuts_hints()
|
|
|
|
|
if self.editing_input_shortcuts_hints_winid and api.nvim_win_is_valid(self.editing_input_shortcuts_hints_winid) then
|
|
|
|
|
api.nvim_win_close(self.editing_input_shortcuts_hints_winid, true)
|
|
|
|
|
self.editing_input_shortcuts_hints_winid = nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Selection:show_editing_input_shortcuts_hints()
|
|
|
|
|
self:close_editing_input_shortcuts_hints()
|
|
|
|
|
|
2024-09-03 04:19:54 -04:00
|
|
|
|
if not self.editing_input_winid or not api.nvim_win_is_valid(self.editing_input_winid) then return end
|
2024-08-27 22:44:40 +08:00
|
|
|
|
|
|
|
|
|
local win_width = api.nvim_win_get_width(self.editing_input_winid)
|
|
|
|
|
local buf_height = api.nvim_buf_line_count(self.editing_input_bufnr)
|
2024-08-28 21:27:55 +08:00
|
|
|
|
-- spinner string: "⡀⠄⠂⠁⠈⠐⠠⢀⣀⢄⢂⢁⢈⢐⢠⣠⢤⢢⢡⢨⢰⣰⢴⢲⢱⢸⣸⢼⢺⢹⣹⢽⢻⣻⢿⣿⣶⣤⣀"
|
2024-08-27 22:44:40 +08:00
|
|
|
|
local spinner_chars = {
|
2024-08-28 21:27:55 +08:00
|
|
|
|
"⡀",
|
2024-08-27 22:44:40 +08:00
|
|
|
|
"⠄",
|
2024-08-28 21:27:55 +08:00
|
|
|
|
"⠂",
|
|
|
|
|
"⠁",
|
|
|
|
|
"⠈",
|
|
|
|
|
"⠐",
|
|
|
|
|
"⠠",
|
|
|
|
|
"⢀",
|
|
|
|
|
"⣀",
|
|
|
|
|
"⢄",
|
|
|
|
|
"⢂",
|
|
|
|
|
"⢁",
|
|
|
|
|
"⢈",
|
|
|
|
|
"⢐",
|
|
|
|
|
"⢠",
|
2024-08-27 22:44:40 +08:00
|
|
|
|
"⣠",
|
2024-08-28 21:27:55 +08:00
|
|
|
|
"⢤",
|
|
|
|
|
"⢢",
|
|
|
|
|
"⢡",
|
|
|
|
|
"⢨",
|
|
|
|
|
"⢰",
|
|
|
|
|
"⣰",
|
|
|
|
|
"⢴",
|
|
|
|
|
"⢲",
|
|
|
|
|
"⢱",
|
|
|
|
|
"⢸",
|
|
|
|
|
"⣸",
|
|
|
|
|
"⢼",
|
|
|
|
|
"⢺",
|
|
|
|
|
"⢹",
|
|
|
|
|
"⣹",
|
|
|
|
|
"⢽",
|
|
|
|
|
"⢻",
|
|
|
|
|
"⣻",
|
|
|
|
|
"⢿",
|
|
|
|
|
"⣿",
|
|
|
|
|
"⣶",
|
|
|
|
|
"⣤",
|
2024-08-27 22:44:40 +08:00
|
|
|
|
"⣀",
|
|
|
|
|
}
|
|
|
|
|
local spinner_index = 1
|
|
|
|
|
local timer = nil
|
|
|
|
|
|
|
|
|
|
local hint_text = (vim.fn.mode() ~= "i" and Config.mappings.submit.normal or Config.mappings.submit.insert)
|
|
|
|
|
.. ": submit"
|
|
|
|
|
|
|
|
|
|
local buf = api.nvim_create_buf(false, true)
|
|
|
|
|
api.nvim_buf_set_lines(buf, 0, -1, false, { hint_text })
|
2024-09-15 10:53:33 -04:00
|
|
|
|
vim.api.nvim_buf_add_highlight(buf, 0, "AvantePopupHint", 0, 0, -1)
|
2024-08-27 22:44:40 +08:00
|
|
|
|
|
|
|
|
|
local function update_spinner()
|
|
|
|
|
spinner_index = (spinner_index % #spinner_chars) + 1
|
|
|
|
|
local spinner = spinner_chars[spinner_index]
|
|
|
|
|
local new_text = spinner .. " " .. hint_text
|
|
|
|
|
|
|
|
|
|
api.nvim_buf_set_lines(buf, 0, -1, false, { new_text })
|
|
|
|
|
|
|
|
|
|
if
|
|
|
|
|
not self.editing_input_shortcuts_hints_winid
|
|
|
|
|
or not api.nvim_win_is_valid(self.editing_input_shortcuts_hints_winid)
|
|
|
|
|
then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local win_config = vim.api.nvim_win_get_config(self.editing_input_shortcuts_hints_winid)
|
|
|
|
|
|
2024-08-28 21:27:55 +08:00
|
|
|
|
local new_width = fn.strdisplaywidth(new_text)
|
|
|
|
|
|
|
|
|
|
if win_config.width ~= new_width then
|
|
|
|
|
win_config.width = new_width
|
|
|
|
|
win_config.col = math.max(win_width - new_width, 0)
|
2024-08-27 22:44:40 +08:00
|
|
|
|
vim.api.nvim_win_set_config(self.editing_input_shortcuts_hints_winid, win_config)
|
|
|
|
|
end
|
2024-08-17 22:29:05 +08:00
|
|
|
|
end
|
2024-08-27 22:44:40 +08:00
|
|
|
|
|
|
|
|
|
local function stop_spinner()
|
|
|
|
|
if timer then
|
|
|
|
|
timer:stop()
|
|
|
|
|
timer:close()
|
|
|
|
|
timer = nil
|
|
|
|
|
end
|
|
|
|
|
api.nvim_buf_set_lines(buf, 0, -1, false, { hint_text })
|
|
|
|
|
|
|
|
|
|
if
|
|
|
|
|
not self.editing_input_shortcuts_hints_winid
|
|
|
|
|
or not api.nvim_win_is_valid(self.editing_input_shortcuts_hints_winid)
|
|
|
|
|
then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local win_config = vim.api.nvim_win_get_config(self.editing_input_shortcuts_hints_winid)
|
|
|
|
|
|
|
|
|
|
if win_config.width ~= #hint_text then
|
|
|
|
|
win_config.width = #hint_text
|
|
|
|
|
win_config.col = math.max(win_width - #hint_text, 0)
|
|
|
|
|
vim.api.nvim_win_set_config(self.editing_input_shortcuts_hints_winid, win_config)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
api.nvim_create_autocmd("User", {
|
2024-08-27 13:13:38 -04:00
|
|
|
|
pattern = EDITING_INPUT_START_SPINNER_PATTERN,
|
2024-08-27 22:44:40 +08:00
|
|
|
|
callback = function()
|
2024-08-27 13:13:38 -04:00
|
|
|
|
timer = vim.uv.new_timer()
|
2024-09-03 04:19:54 -04:00
|
|
|
|
if timer then timer:start(0, 100, vim.schedule_wrap(function() update_spinner() end)) end
|
2024-08-27 22:44:40 +08:00
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
api.nvim_create_autocmd("User", {
|
2024-08-27 13:13:38 -04:00
|
|
|
|
pattern = EDITING_INPUT_STOP_SPINNER_PATTERN,
|
2024-09-03 04:19:54 -04:00
|
|
|
|
callback = function() stop_spinner() end,
|
2024-08-27 22:44:40 +08:00
|
|
|
|
})
|
2024-08-28 21:27:55 +08:00
|
|
|
|
|
|
|
|
|
local width = fn.strdisplaywidth(hint_text)
|
2024-08-27 22:44:40 +08:00
|
|
|
|
|
|
|
|
|
local opts = {
|
|
|
|
|
relative = "win",
|
|
|
|
|
win = self.editing_input_winid,
|
|
|
|
|
width = width,
|
|
|
|
|
height = 1,
|
|
|
|
|
row = buf_height,
|
|
|
|
|
col = math.max(win_width - width, 0),
|
|
|
|
|
style = "minimal",
|
|
|
|
|
border = "none",
|
|
|
|
|
focusable = false,
|
|
|
|
|
zindex = 100,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.editing_input_shortcuts_hints_winid = api.nvim_open_win(buf, false, opts)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Selection:create_editing_input()
|
2024-08-27 23:47:15 +08:00
|
|
|
|
self:close_editing_input()
|
|
|
|
|
|
2024-09-03 21:47:01 -04:00
|
|
|
|
if not vim.g.avante_login or vim.g.avante_login == false then
|
|
|
|
|
api.nvim_exec_autocmds("User", { pattern = Provider.env.REQUEST_LOGIN_PATTERN })
|
|
|
|
|
vim.g.avante_login = true
|
|
|
|
|
end
|
|
|
|
|
|
2024-08-27 22:44:40 +08:00
|
|
|
|
local code_bufnr = api.nvim_get_current_buf()
|
|
|
|
|
local code_wind = api.nvim_get_current_win()
|
|
|
|
|
self.cursor_pos = api.nvim_win_get_cursor(code_wind)
|
|
|
|
|
self.code_winid = code_wind
|
|
|
|
|
local code_lines = api.nvim_buf_get_lines(code_bufnr, 0, -1, false)
|
|
|
|
|
local code_content = table.concat(code_lines, "\n")
|
|
|
|
|
|
|
|
|
|
self.selection = Utils.get_visual_selection_and_range()
|
|
|
|
|
|
2024-10-08 16:29:18 +08:00
|
|
|
|
if self.selection == nil then
|
|
|
|
|
Utils.error("No visual selection found", { once = true, title = "Avante" })
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
2024-08-28 08:46:26 -07:00
|
|
|
|
local start_row
|
|
|
|
|
local start_col
|
|
|
|
|
local end_row
|
|
|
|
|
local end_col
|
|
|
|
|
if vim.fn.mode() == "V" then
|
|
|
|
|
start_row = self.selection.range.start.line - 1
|
|
|
|
|
start_col = 0
|
|
|
|
|
end_row = self.selection.range.finish.line - 1
|
|
|
|
|
end_col = #code_lines[self.selection.range.finish.line]
|
|
|
|
|
else
|
|
|
|
|
start_row = self.selection.range.start.line - 1
|
|
|
|
|
start_col = self.selection.range.start.col - 1
|
|
|
|
|
end_row = self.selection.range.finish.line - 1
|
|
|
|
|
end_col = math.min(self.selection.range.finish.col, #code_lines[self.selection.range.finish.line])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
self.selected_code_extmark_id = api.nvim_buf_set_extmark(code_bufnr, SELECTED_CODE_NAMESPACE, start_row, start_col, {
|
|
|
|
|
hl_group = "Visual",
|
|
|
|
|
hl_mode = "combine",
|
|
|
|
|
end_row = end_row,
|
|
|
|
|
end_col = end_col,
|
|
|
|
|
priority = PRIORITY,
|
|
|
|
|
})
|
2024-08-27 22:44:40 +08:00
|
|
|
|
|
|
|
|
|
local bufnr = api.nvim_create_buf(false, true)
|
|
|
|
|
|
|
|
|
|
self.editing_input_bufnr = bufnr
|
|
|
|
|
|
|
|
|
|
local win_opts = {
|
|
|
|
|
relative = "cursor",
|
|
|
|
|
width = 40,
|
|
|
|
|
height = 2,
|
|
|
|
|
row = 1,
|
|
|
|
|
col = 0,
|
|
|
|
|
style = "minimal",
|
2024-08-27 13:13:38 -04:00
|
|
|
|
border = Config.windows.edit.border,
|
|
|
|
|
title = { { "edit selected block", "FloatTitle" } },
|
2024-08-27 22:44:40 +08:00
|
|
|
|
title_pos = "center",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local winid = api.nvim_open_win(bufnr, true, win_opts)
|
|
|
|
|
|
|
|
|
|
self.editing_input_winid = winid
|
|
|
|
|
|
|
|
|
|
api.nvim_set_option_value("wrap", false, { win = winid })
|
|
|
|
|
api.nvim_set_option_value("cursorline", true, { win = winid })
|
|
|
|
|
api.nvim_set_option_value("modifiable", true, { buf = bufnr })
|
|
|
|
|
|
|
|
|
|
self:show_editing_input_shortcuts_hints()
|
|
|
|
|
|
|
|
|
|
api.nvim_create_autocmd({ "TextChanged", "TextChangedI" }, {
|
|
|
|
|
group = self.augroup,
|
|
|
|
|
buffer = bufnr,
|
2024-09-03 04:19:54 -04:00
|
|
|
|
callback = function() self:show_editing_input_shortcuts_hints() end,
|
2024-08-27 22:44:40 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
api.nvim_create_autocmd("ModeChanged", {
|
|
|
|
|
group = self.augroup,
|
|
|
|
|
pattern = "i:*",
|
|
|
|
|
callback = function()
|
|
|
|
|
local cur_buf = api.nvim_get_current_buf()
|
2024-09-03 04:19:54 -04:00
|
|
|
|
if cur_buf == bufnr then self:show_editing_input_shortcuts_hints() end
|
2024-08-27 22:44:40 +08:00
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
api.nvim_create_autocmd("ModeChanged", {
|
|
|
|
|
group = self.augroup,
|
|
|
|
|
pattern = "*:i",
|
|
|
|
|
callback = function()
|
|
|
|
|
local cur_buf = api.nvim_get_current_buf()
|
2024-09-03 04:19:54 -04:00
|
|
|
|
if cur_buf == bufnr then self:show_editing_input_shortcuts_hints() end
|
2024-08-27 22:44:40 +08:00
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
|
2024-09-02 12:22:48 -04:00
|
|
|
|
---@param input string
|
|
|
|
|
local function submit_input(input)
|
2024-08-27 22:44:40 +08:00
|
|
|
|
local full_response = ""
|
|
|
|
|
local start_line = self.selection.range.start.line
|
|
|
|
|
local finish_line = self.selection.range.finish.line
|
|
|
|
|
|
2024-08-28 22:17:00 +08:00
|
|
|
|
local original_first_line_indentation = Utils.get_indentation(code_lines[self.selection.range.start.line])
|
2024-08-27 22:44:40 +08:00
|
|
|
|
|
2024-08-31 13:29:28 +08:00
|
|
|
|
local need_prepend_indentation = false
|
|
|
|
|
|
2024-08-27 13:13:38 -04:00
|
|
|
|
api.nvim_exec_autocmds("User", { pattern = EDITING_INPUT_START_SPINNER_PATTERN })
|
2024-08-27 22:44:40 +08:00
|
|
|
|
---@type AvanteChunkParser
|
|
|
|
|
local on_chunk = function(chunk)
|
|
|
|
|
full_response = full_response .. chunk
|
2024-09-30 19:38:31 +08:00
|
|
|
|
local response_lines_ = vim.split(full_response, "\n")
|
|
|
|
|
local response_lines = {}
|
|
|
|
|
for i, line in ipairs(response_lines_) do
|
|
|
|
|
if not (string.match(line, "^```") and (i == 1 or i == #response_lines_)) then
|
|
|
|
|
table.insert(response_lines, line)
|
|
|
|
|
end
|
|
|
|
|
end
|
2024-08-31 13:29:28 +08:00
|
|
|
|
if #response_lines == 1 then
|
2024-08-28 22:17:00 +08:00
|
|
|
|
local first_line = response_lines[1]
|
|
|
|
|
local first_line_indentation = Utils.get_indentation(first_line)
|
|
|
|
|
need_prepend_indentation = first_line_indentation ~= original_first_line_indentation
|
|
|
|
|
end
|
|
|
|
|
if need_prepend_indentation then
|
|
|
|
|
for i, line in ipairs(response_lines) do
|
|
|
|
|
response_lines[i] = original_first_line_indentation .. line
|
|
|
|
|
end
|
2024-08-27 22:44:40 +08:00
|
|
|
|
end
|
|
|
|
|
api.nvim_buf_set_lines(code_bufnr, start_line - 1, finish_line, true, response_lines)
|
|
|
|
|
finish_line = start_line + #response_lines - 1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
---@type AvanteCompleteParser
|
|
|
|
|
local on_complete = function(err)
|
|
|
|
|
if err then
|
|
|
|
|
Utils.error(
|
|
|
|
|
"Error occurred while processing the response: " .. vim.inspect(err),
|
|
|
|
|
{ once = true, title = "Avante" }
|
|
|
|
|
)
|
|
|
|
|
return
|
|
|
|
|
end
|
2024-08-27 13:13:38 -04:00
|
|
|
|
api.nvim_exec_autocmds("User", { pattern = EDITING_INPUT_STOP_SPINNER_PATTERN })
|
2024-09-03 04:19:54 -04:00
|
|
|
|
vim.defer_fn(function() self:close_editing_input() end, 0)
|
2024-08-27 22:44:40 +08:00
|
|
|
|
end
|
|
|
|
|
|
2024-08-30 22:21:50 +08:00
|
|
|
|
local filetype = api.nvim_get_option_value("filetype", { buf = code_bufnr })
|
2024-09-23 18:52:26 +08:00
|
|
|
|
local file_ext = api.nvim_buf_get_name(code_bufnr):match("^.+%.(.+)$")
|
|
|
|
|
|
|
|
|
|
local mentions = Utils.extract_mentions(input)
|
|
|
|
|
input = mentions.new_content
|
2024-09-26 03:45:49 +08:00
|
|
|
|
local project_context = mentions.enable_project_context and RepoMap.get_repo_map(file_ext) or nil
|
2024-08-30 22:21:50 +08:00
|
|
|
|
|
2024-09-03 05:12:07 -04:00
|
|
|
|
Llm.stream({
|
2024-09-03 04:09:13 -04:00
|
|
|
|
bufnr = code_bufnr,
|
2024-09-05 02:43:31 -04:00
|
|
|
|
ask = true,
|
2024-09-23 18:52:26 +08:00
|
|
|
|
project_context = vim.json.encode(project_context),
|
2024-08-30 18:53:49 +08:00
|
|
|
|
file_content = code_content,
|
2024-08-30 22:21:50 +08:00
|
|
|
|
code_lang = filetype,
|
2024-08-30 18:53:49 +08:00
|
|
|
|
selected_code = self.selection.content,
|
|
|
|
|
instructions = input,
|
|
|
|
|
mode = "editing",
|
|
|
|
|
on_chunk = on_chunk,
|
|
|
|
|
on_complete = on_complete,
|
2024-09-03 05:12:07 -04:00
|
|
|
|
})
|
2024-08-27 22:44:40 +08:00
|
|
|
|
end
|
|
|
|
|
|
2024-09-02 12:22:48 -04:00
|
|
|
|
---@return string
|
|
|
|
|
local get_bufnr_input = function()
|
|
|
|
|
local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
|
|
|
|
return lines[1] or ""
|
|
|
|
|
end
|
|
|
|
|
|
2024-09-03 04:19:54 -04:00
|
|
|
|
vim.keymap.set(
|
|
|
|
|
"i",
|
|
|
|
|
Config.mappings.submit.insert,
|
|
|
|
|
function() submit_input(get_bufnr_input()) end,
|
|
|
|
|
{ buffer = bufnr, noremap = true, silent = true }
|
|
|
|
|
)
|
|
|
|
|
vim.keymap.set(
|
|
|
|
|
"n",
|
|
|
|
|
Config.mappings.submit.normal,
|
|
|
|
|
function() submit_input(get_bufnr_input()) end,
|
|
|
|
|
{ buffer = bufnr, noremap = true, silent = true }
|
|
|
|
|
)
|
|
|
|
|
vim.keymap.set("n", "<Esc>", function() self:close_editing_input() end, { buffer = bufnr })
|
|
|
|
|
vim.keymap.set("n", "q", function() self:close_editing_input() end, { buffer = bufnr })
|
2024-08-27 22:44:40 +08:00
|
|
|
|
|
|
|
|
|
local quit_id, close_unfocus
|
|
|
|
|
quit_id = api.nvim_create_autocmd("QuitPre", {
|
|
|
|
|
group = self.augroup,
|
|
|
|
|
buffer = bufnr,
|
|
|
|
|
once = true,
|
|
|
|
|
nested = true,
|
|
|
|
|
callback = function()
|
|
|
|
|
self:close_editing_input()
|
|
|
|
|
if not quit_id then
|
|
|
|
|
api.nvim_del_autocmd(quit_id)
|
|
|
|
|
quit_id = nil
|
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
close_unfocus = api.nvim_create_autocmd("WinLeave", {
|
|
|
|
|
group = self.augroup,
|
|
|
|
|
buffer = bufnr,
|
|
|
|
|
callback = function()
|
|
|
|
|
self:close_editing_input()
|
|
|
|
|
if close_unfocus then
|
|
|
|
|
api.nvim_del_autocmd(close_unfocus)
|
|
|
|
|
close_unfocus = nil
|
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
})
|
2024-09-02 12:22:48 -04:00
|
|
|
|
|
2024-09-23 18:52:26 +08:00
|
|
|
|
api.nvim_create_autocmd("InsertEnter", {
|
|
|
|
|
group = self.augroup,
|
|
|
|
|
buffer = bufnr,
|
|
|
|
|
once = true,
|
|
|
|
|
desc = "Setup the completion of helpers in the input buffer",
|
|
|
|
|
callback = function()
|
|
|
|
|
local has_cmp, cmp = pcall(require, "cmp")
|
|
|
|
|
if has_cmp then
|
|
|
|
|
cmp.register_source("avante_mentions", require("cmp_avante.mentions").new(Utils.get_mentions(), bufnr))
|
|
|
|
|
cmp.setup.buffer({
|
|
|
|
|
enabled = true,
|
|
|
|
|
sources = {
|
|
|
|
|
{ name = "avante_mentions" },
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
|
2024-09-02 12:22:48 -04:00
|
|
|
|
api.nvim_create_autocmd("User", {
|
|
|
|
|
pattern = "AvanteEditSubmitted",
|
|
|
|
|
callback = function(ev)
|
2024-09-03 04:19:54 -04:00
|
|
|
|
if ev.data and ev.data.request then submit_input(ev.data.request) end
|
2024-09-02 12:22:48 -04:00
|
|
|
|
end,
|
|
|
|
|
})
|
2024-08-17 22:29:05 +08:00
|
|
|
|
end
|
|
|
|
|
|
2024-08-18 05:36:30 -04:00
|
|
|
|
function Selection:setup_autocmds()
|
|
|
|
|
Selection.did_setup = true
|
|
|
|
|
api.nvim_create_autocmd({ "ModeChanged" }, {
|
2024-08-17 22:29:05 +08:00
|
|
|
|
group = self.augroup,
|
|
|
|
|
pattern = { "n:v", "n:V", "n:" }, -- Entering Visual mode from Normal mode
|
2024-08-23 02:23:45 -04:00
|
|
|
|
callback = function(ev)
|
2024-09-03 04:19:54 -04:00
|
|
|
|
if not Utils.is_sidebar_buffer(ev.buf) then self:show_shortcuts_hints_popup() end
|
2024-08-17 22:29:05 +08:00
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, {
|
|
|
|
|
group = self.augroup,
|
2024-08-23 02:23:45 -04:00
|
|
|
|
callback = function(ev)
|
2024-08-24 00:14:20 +08:00
|
|
|
|
if not Utils.is_sidebar_buffer(ev.buf) then
|
|
|
|
|
if Utils.in_visual_mode() then
|
2024-08-27 22:44:40 +08:00
|
|
|
|
self:show_shortcuts_hints_popup()
|
2024-08-23 02:23:45 -04:00
|
|
|
|
else
|
2024-08-27 22:44:40 +08:00
|
|
|
|
self:close_shortcuts_hints_popup()
|
2024-08-23 02:23:45 -04:00
|
|
|
|
end
|
2024-08-17 22:29:05 +08:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
api.nvim_create_autocmd({ "ModeChanged" }, {
|
|
|
|
|
group = self.augroup,
|
|
|
|
|
pattern = { "v:n", "v:i", "v:c" }, -- Switching from visual mode back to normal, insert, or other modes
|
2024-08-23 02:23:45 -04:00
|
|
|
|
callback = function(ev)
|
2024-09-03 04:19:54 -04:00
|
|
|
|
if not Utils.is_sidebar_buffer(ev.buf) then self:close_shortcuts_hints_popup() end
|
2024-08-17 22:29:05 +08:00
|
|
|
|
end,
|
|
|
|
|
})
|
2024-08-24 00:21:00 +08:00
|
|
|
|
|
|
|
|
|
api.nvim_create_autocmd({ "BufLeave" }, {
|
|
|
|
|
group = self.augroup,
|
|
|
|
|
callback = function(ev)
|
2024-09-03 04:19:54 -04:00
|
|
|
|
if not Utils.is_sidebar_buffer(ev.buf) then self:close_shortcuts_hints_popup() end
|
2024-08-24 00:21:00 +08:00
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
|
2024-08-17 14:14:02 -04:00
|
|
|
|
return self
|
2024-08-17 22:29:05 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Selection:delete_autocmds()
|
2024-09-03 04:19:54 -04:00
|
|
|
|
if self.augroup then api.nvim_del_augroup_by_id(self.augroup) end
|
2024-08-17 22:29:05 +08:00
|
|
|
|
self.augroup = nil
|
2024-08-18 05:36:30 -04:00
|
|
|
|
Selection.did_setup = false
|
2024-08-17 22:29:05 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return Selection
|