@@ -4,6 +4,8 @@ local Llm = require("avante.llm")
local Provider = require ( " avante.providers " )
local RepoMap = require ( " avante.repo_map " )
local PromptInput = require ( " avante.ui.prompt_input " )
local SelectionResult = require ( " avante.selection_result " )
local Range = require ( " avante.range " )
local api = vim.api
local fn = vim.fn
@@ -19,6 +21,7 @@ local PRIORITY = vim.highlight.priorities.user
---@field selected_code_extmark_id integer | nil
---@field augroup integer | nil
---@field code_winid integer | nil
---@field code_bufnr integer | nil
---@field prompt_input avante.ui.PromptInput | nil
local Selection = { }
Selection.__index = Selection
@@ -34,6 +37,7 @@ function Selection:new(id)
selection = nil ,
cursor_pos = nil ,
code_winid = nil ,
code_bufnr = nil ,
prompt_input = nil ,
} , Selection )
end
@@ -88,7 +92,7 @@ function Selection:close_editing_input()
self.selected_code_extmark_id = nil
end
end
if self.cursor_pos and self.code_winid then
if self.cursor_pos and self.code_winid and api.nvim_win_is_valid ( self.code_winid ) then
vim.schedule ( function ( )
local bufnr = api.nvim_win_get_buf ( self.code_winid )
local line_count = api.nvim_buf_line_count ( bufnr )
@@ -100,53 +104,21 @@ function Selection:close_editing_input()
end
end
function Selection : create_editing _input( )
self : close_editing_input ( )
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
local code_bufnr = api.nvim_get_current_buf ( )
local code_winid = api.nvim_get_current_win ( )
self.cursor_pos = api.nvim_win_get_cursor ( code_winid )
self.code_winid = code_winid
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 ( )
if self.selection == nil then
Utils.error ( " No visual selection found " , { once = true , title = " Avante " } )
function Selection : submit _input( input )
if not input then
Utils.error ( " No input provided " , { once = true , title = " Avante " } )
return
end
local start_row
local start_col
local end_row
local end_col
if vim.fn . mode ( ) == " V " the n
start_row = self.selection . range.start . lnum - 1
start_col = 0
end_row = self.selection . range.finish . lnum - 1
end_col = # code_lines [ self.selection . range.finish . lnum ]
else
start_row = self.selection . range.start . lnum - 1
start_col = self.selection . range.start . col - 1
end_row = self.selection . range.finish . lnum - 1
end_col = math.min ( self.selection . range.finish . col , # code_lines [ self.selection . range.finish . lnum ] )
if self.prompt_input and self.prompt_input . spinner_active then
Utils.error (
" Please wait for the previous request to finish before submitting another " ,
{ once = true , title = " Avante " }
)
retur n
end
local code_lines = api.nvim_buf_get_lines ( self.code_bufnr , 0 , - 1 , false )
local code_content = table.concat ( code_lines , " \n " )
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 ,
} )
local function submit_input ( input )
local full_response = " "
local start_line = self.selection . range.start . lnum
local finish_line = self.selection . range.finish . lnum
@@ -155,10 +127,10 @@ function Selection:create_editing_input()
local need_prepend_indentation = false
self.prompt_input : start_spinner ( )
if self.prompt_input then self.prompt_input : start_spinner ( ) end
---@type AvanteLLMStartCallback
local function on_start ( start_opts ) end
local function on_start ( _ ) end
---@type AvanteLLMChunkCallback
local function on_chunk ( chunk )
@@ -189,7 +161,7 @@ function Selection:create_editing_input()
response_lines [ i ] = original_first_line_indentation .. line
end
end
api.nvim_buf_set_lines ( code_bufnr , start_line - 1 , finish_line , true , response_lines )
api.nvim_buf_set_lines ( self. code_bufnr, start_line - 1 , finish_line , true , response_lines )
finish_line = start_line + # response_lines - 1
end
@@ -206,19 +178,19 @@ function Selection:create_editing_input()
)
return
end
self.prompt_input : stop_spinner ( )
if self.prompt_input then self.prompt_input : stop_spinner ( ) end
vim.defer_fn ( function ( ) self : close_editing_input ( ) end , 0 )
Utils.debug ( " full response: " , full_response )
end
local filetype = api.nvim_get_option_value ( " filetype " , { buf = code_bufnr } )
local file_ext = api.nvim_buf_get_name ( code_bufnr ) : match ( " ^.+%.(.+)$ " )
local filetype = api.nvim_get_option_value ( " filetype " , { buf = self. code_bufnr } )
local file_ext = api.nvim_buf_get_name ( self. code_bufnr) : match ( " ^.+%.(.+)$ " )
local mentions = Utils.extract_mentions ( input )
input = mentions.new_content
local project_context = mentions.enable_project_context and RepoMap.get_repo_map ( file_ext ) or nil
local diagnostics = Utils.get_current_selection_diagnostics ( code_bufnr , self.selection )
local diagnostics = Utils.get_current_selection_diagnostics ( self. code_bufnr, self.selection )
---@type AvanteSelectedCode | nil
local selected_code = nil
@@ -246,8 +218,69 @@ function Selection:create_editing_input()
} )
end
---@param request? string
---@param line1? integer
---@param line2? integer
function Selection : create_editing_input ( request , line1 , line2 )
self : close_editing_input ( )
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
self.code_bufnr = api.nvim_get_current_buf ( )
self.code_winid = api.nvim_get_current_win ( )
self.cursor_pos = api.nvim_win_get_cursor ( self.code_winid )
local code_lines = api.nvim_buf_get_lines ( self.code_bufnr , 0 , - 1 , false )
if line1 ~= nil and line2 ~= nil then
local filepath = vim.fn . expand ( " %:p " )
local filetype = Utils.get_filetype ( filepath )
local content_lines = vim.list_slice ( code_lines , line1 , line2 )
local content = table.concat ( content_lines , " \n " )
local range = Range : new (
{ lnum = line1 , col = # content_lines [ 1 ] } ,
{ lnum = line2 , col = # content_lines [ # content_lines ] }
)
self.selection = SelectionResult : new ( filepath , filetype , content , range )
else
self.selection = Utils.get_visual_selection_and_range ( )
end
if self.selection == nil then
Utils.error ( " No visual selection found " , { once = true , title = " Avante " } )
return
end
local start_row
local start_col
local end_row
local end_col
if vim.fn . mode ( ) == " V " then
start_row = self.selection . range.start . lnum - 1
start_col = 0
end_row = self.selection . range.finish . lnum - 1
end_col = # code_lines [ self.selection . range.finish . lnum ]
else
start_row = self.selection . range.start . lnum - 1
start_col = self.selection . range.start . col - 1
end_row = self.selection . range.finish . lnum - 1
end_col = math.min ( self.selection . range.finish . col , # code_lines [ self.selection . range.finish . lnum ] )
end
self.selected_code_extmark_id =
api.nvim_buf_set_extmark ( self.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 ,
} )
local prompt_input = PromptInput : new ( {
submi t_c allback = submit_inpu t,
defaul t_v alue = reques t,
submit_callback = function ( input ) self : submit_input ( input ) end ,
cancel_callback = function ( ) self : close_editing_input ( ) end ,
win_opts = {
border = Config.windows . edit.border ,
@@ -285,6 +318,13 @@ end
function Selection : setup_autocmds ( )
Selection.did_setup = true
api.nvim_create_autocmd ( " User " , {
group = self.augroup ,
pattern = " AvanteEditSubmitted " ,
callback = function ( ev ) self : submit_input ( ev.data . request ) end ,
} )
api.nvim_create_autocmd ( { " ModeChanged " } , {
group = self.augroup ,
pattern = { " n:v " , " n:V " , " n: " } , -- Entering Visual mode from Normal mode