chore: run stylua [generated] (#460)
* chore: add stylua Signed-off-by: Aaron Pham <contact@aarnphm.xyz> * chore: running stylua Signed-off-by: Aaron Pham <contact@aarnphm.xyz> --------- Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
This commit is contained in:
parent
4ad913435c
commit
e8c71d931e
2
Makefile
2
Makefile
@ -59,4 +59,4 @@ stylecheck:
|
||||
stylua --check lua/
|
||||
|
||||
stylefix:
|
||||
stylua lua/
|
||||
stylua lua/ plugin/
|
||||
|
@ -1,5 +1,5 @@
|
||||
local Config = require("avante.config")
|
||||
local Utils = require("avante.utils")
|
||||
local Config = require "avante.config"
|
||||
local Utils = require "avante.utils"
|
||||
|
||||
---@class avante.ApiToggle
|
||||
---@operator call(): boolean
|
||||
@ -17,18 +17,12 @@ local Utils = require("avante.utils")
|
||||
local M = {}
|
||||
|
||||
---@param target Provider
|
||||
M.switch_provider = function(target)
|
||||
require("avante.providers").refresh(target)
|
||||
end
|
||||
M.switch_provider = function(target) require("avante.providers").refresh(target) end
|
||||
|
||||
---@param question? string
|
||||
M.ask = function(question)
|
||||
if not require("avante").toggle() then
|
||||
return false
|
||||
end
|
||||
if question == nil or question == "" then
|
||||
return true
|
||||
end
|
||||
if not require("avante").toggle() then return false end
|
||||
if question == nil or question == "" then return true end
|
||||
vim.api.nvim_exec_autocmds("User", { pattern = "AvanteInputSubmitted", data = { request = question } })
|
||||
return true
|
||||
end
|
||||
@ -36,9 +30,7 @@ end
|
||||
---@param question? string
|
||||
M.edit = function(question)
|
||||
local _, selection = require("avante").get()
|
||||
if not selection then
|
||||
return
|
||||
end
|
||||
if not selection then return end
|
||||
selection:create_editing_input()
|
||||
if question ~= nil or question ~= "" then
|
||||
vim.api.nvim_exec_autocmds("User", { pattern = "AvanteEditSubmitted", data = { request = question } })
|
||||
@ -53,23 +45,15 @@ end
|
||||
|
||||
M.refresh = function()
|
||||
local sidebar = require("avante").get()
|
||||
if not sidebar then
|
||||
return
|
||||
end
|
||||
if not sidebar:is_open() then
|
||||
return
|
||||
end
|
||||
if not sidebar then return end
|
||||
if not sidebar:is_open() then return end
|
||||
local curbuf = vim.api.nvim_get_current_buf()
|
||||
|
||||
local focused = sidebar.result.bufnr == curbuf or sidebar.input.bufnr == curbuf
|
||||
if focused or not sidebar:is_open() then
|
||||
return
|
||||
end
|
||||
if focused or not sidebar:is_open() then return end
|
||||
local listed = vim.api.nvim_get_option_value("buflisted", { buf = curbuf })
|
||||
|
||||
if Utils.is_sidebar_buffer(curbuf) or not listed then
|
||||
return
|
||||
end
|
||||
if Utils.is_sidebar_buffer(curbuf) or not listed then return end
|
||||
|
||||
local curwin = vim.api.nvim_get_current_win()
|
||||
|
||||
@ -81,7 +65,7 @@ end
|
||||
|
||||
return setmetatable(M, {
|
||||
__index = function(t, k)
|
||||
local module = require("avante")
|
||||
local module = require "avante"
|
||||
---@class AvailableApi: ApiCaller
|
||||
---@field api? boolean
|
||||
local has = module[k]
|
||||
|
@ -1,9 +1,9 @@
|
||||
---NOTE: this module is inspired by https://github.com/HakonHarnes/img-clip.nvim/tree/main
|
||||
---@see https://github.com/ekickx/clipboard-image.nvim/blob/main/lua/clipboard-image/paste.lua
|
||||
|
||||
local Path = require("plenary.path")
|
||||
local Utils = require("avante.utils")
|
||||
local Config = require("avante.config")
|
||||
local Path = require "plenary.path"
|
||||
local Utils = require "avante.utils"
|
||||
local Config = require "avante.config"
|
||||
---@module "img-clip"
|
||||
local ImgClip = nil
|
||||
|
||||
@ -18,10 +18,8 @@ local paste_directory = nil
|
||||
|
||||
---@return Path
|
||||
local function get_paste_directory()
|
||||
if paste_directory then
|
||||
return paste_directory
|
||||
end
|
||||
paste_directory = Path:new(Config.history.storage_path):joinpath("pasted_images")
|
||||
if paste_directory then return paste_directory end
|
||||
paste_directory = Path:new(Config.history.storage_path):joinpath "pasted_images"
|
||||
return paste_directory
|
||||
end
|
||||
|
||||
@ -30,21 +28,15 @@ M.support_paste_image = Config.support_paste_image
|
||||
M.setup = function()
|
||||
get_paste_directory()
|
||||
|
||||
if not paste_directory:exists() then
|
||||
paste_directory:mkdir({ parent = true })
|
||||
end
|
||||
if not paste_directory:exists() then paste_directory:mkdir { parent = true } end
|
||||
|
||||
if M.support_paste_image() and ImgClip == nil then
|
||||
ImgClip = require("img-clip")
|
||||
end
|
||||
if M.support_paste_image() and ImgClip == nil then ImgClip = require "img-clip" end
|
||||
end
|
||||
|
||||
---@param line? string
|
||||
M.paste_image = function(line)
|
||||
line = line or nil
|
||||
if not Config.support_paste_image(true) then
|
||||
return false
|
||||
end
|
||||
if not Config.support_paste_image(true) then return false end
|
||||
|
||||
local opts = {
|
||||
dir_path = paste_directory:absolute(),
|
||||
@ -54,9 +46,7 @@ M.paste_image = function(line)
|
||||
},
|
||||
}
|
||||
|
||||
if vim.fn.has("wsl") > 0 or vim.fn.has("win32") > 0 then
|
||||
opts.use_absolute_path = true
|
||||
end
|
||||
if vim.fn.has "wsl" > 0 or vim.fn.has "win32" > 0 then opts.use_absolute_path = true end
|
||||
|
||||
return ImgClip.paste_image(opts, line)
|
||||
end
|
||||
@ -75,7 +65,7 @@ M.get_base64_content = function(filepath)
|
||||
if output.code == 0 then
|
||||
return output.stdout
|
||||
else
|
||||
error("Failed to convert image to base64")
|
||||
error "Failed to convert image to base64"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---NOTE: user will be merged with defaults and
|
||||
---we add a default var_accessor for this table to config values.
|
||||
|
||||
local Utils = require("avante.utils")
|
||||
local Utils = require "avante.utils"
|
||||
|
||||
---@class avante.CoreConfig: avante.Config
|
||||
local M = {}
|
||||
@ -100,7 +100,7 @@ You are an excellent programming expert.
|
||||
support_paste_from_clipboard = false,
|
||||
},
|
||||
history = {
|
||||
storage_path = vim.fn.stdpath("state") .. "/avante",
|
||||
storage_path = vim.fn.stdpath "state" .. "/avante",
|
||||
paste = {
|
||||
extension = "png",
|
||||
filename = "pasted-%Y-%m-%d-%H-%M-%S",
|
||||
@ -188,7 +188,7 @@ M.providers = {}
|
||||
|
||||
---@param opts? avante.Config
|
||||
function M.setup(opts)
|
||||
vim.validate({ opts = { opts, "table", true } })
|
||||
vim.validate { opts = { opts, "table", true } }
|
||||
|
||||
M.options = vim.tbl_deep_extend(
|
||||
"force",
|
||||
@ -207,16 +207,14 @@ function M.setup(opts)
|
||||
end
|
||||
M.providers = vim
|
||||
.iter(M.defaults)
|
||||
:filter(function(_, value)
|
||||
return type(value) == "table" and value.endpoint ~= nil
|
||||
end)
|
||||
:filter(function(_, value) return type(value) == "table" and value.endpoint ~= nil end)
|
||||
:fold({}, function(acc, k)
|
||||
acc = vim.list_extend({}, acc)
|
||||
acc = vim.list_extend(acc, { k })
|
||||
return acc
|
||||
end)
|
||||
|
||||
vim.validate({ provider = { M.options.provider, "string", false } })
|
||||
vim.validate { provider = { M.options.provider, "string", false } }
|
||||
|
||||
M.diff = vim.tbl_deep_extend(
|
||||
"force",
|
||||
@ -229,14 +227,14 @@ function M.setup(opts)
|
||||
for k, v in pairs(M.options.vendors) do
|
||||
M.options.vendors[k] = type(v) == "function" and v() or v
|
||||
end
|
||||
vim.validate({ vendors = { M.options.vendors, "table", true } })
|
||||
vim.validate { vendors = { M.options.vendors, "table", true } }
|
||||
M.providers = vim.list_extend(M.providers, vim.tbl_keys(M.options.vendors))
|
||||
end
|
||||
end
|
||||
|
||||
---@param opts? avante.Config
|
||||
function M.override(opts)
|
||||
vim.validate({ opts = { opts, "table", true } })
|
||||
vim.validate { opts = { opts, "table", true } }
|
||||
|
||||
M.options = vim.tbl_deep_extend("force", M.options, opts or {})
|
||||
if not M.options.silent_warning then
|
||||
@ -254,41 +252,31 @@ function M.override(opts)
|
||||
if next(M.options.vendors) ~= nil then
|
||||
for k, v in pairs(M.options.vendors) do
|
||||
M.options.vendors[k] = type(v) == "function" and v() or v
|
||||
if not vim.tbl_contains(M.providers, k) then
|
||||
M.providers = vim.list_extend(M.providers, { k })
|
||||
end
|
||||
if not vim.tbl_contains(M.providers, k) then M.providers = vim.list_extend(M.providers, { k }) end
|
||||
end
|
||||
vim.validate({ vendors = { M.options.vendors, "table", true } })
|
||||
vim.validate { vendors = { M.options.vendors, "table", true } }
|
||||
end
|
||||
end
|
||||
|
||||
M = setmetatable(M, {
|
||||
__index = function(_, k)
|
||||
if M.options[k] then
|
||||
return M.options[k]
|
||||
end
|
||||
if M.options[k] then return M.options[k] end
|
||||
end,
|
||||
})
|
||||
|
||||
---@param skip_warning? boolean
|
||||
M.support_paste_image = function(skip_warning)
|
||||
skip_warning = skip_warning or M.silent_warning
|
||||
if skip_warning then
|
||||
return
|
||||
end
|
||||
if skip_warning then return end
|
||||
|
||||
return Utils.has("img-clip.nvim") or Utils.has("img-clip")
|
||||
return Utils.has "img-clip.nvim" or Utils.has "img-clip"
|
||||
end
|
||||
|
||||
M.get_window_width = function()
|
||||
return math.ceil(vim.o.columns * (M.windows.width / 100))
|
||||
end
|
||||
M.get_window_width = function() return math.ceil(vim.o.columns * (M.windows.width / 100)) end
|
||||
|
||||
---@param provider Provider
|
||||
---@return boolean
|
||||
M.has_provider = function(provider)
|
||||
return M.options[provider] ~= nil or M.vendors[provider] ~= nil
|
||||
end
|
||||
M.has_provider = function(provider) return M.options[provider] ~= nil or M.vendors[provider] ~= nil end
|
||||
|
||||
---get supported providers
|
||||
---@param provider Provider
|
||||
|
@ -1,8 +1,8 @@
|
||||
local api = vim.api
|
||||
|
||||
local Config = require("avante.config")
|
||||
local Utils = require("avante.utils")
|
||||
local Highlights = require("avante.highlights")
|
||||
local Config = require "avante.config"
|
||||
local Utils = require "avante.utils"
|
||||
local Highlights = require "avante.highlights"
|
||||
|
||||
local H = {}
|
||||
local M = {}
|
||||
@ -82,8 +82,8 @@ local INCOMING_HL = "AvanteConflictIncoming"
|
||||
local CURRENT_LABEL_HL = "AvanteConflictCurrentLabel"
|
||||
local INCOMING_LABEL_HL = "AvanteConflictIncomingLabel"
|
||||
local PRIORITY = vim.highlight.priorities.user
|
||||
local NAMESPACE = api.nvim_create_namespace("avante-conflict")
|
||||
local KEYBINDING_NAMESPACE = api.nvim_create_namespace("avante-conflict-keybinding")
|
||||
local NAMESPACE = api.nvim_create_namespace "avante-conflict"
|
||||
local KEYBINDING_NAMESPACE = api.nvim_create_namespace "avante-conflict-keybinding"
|
||||
local AUGROUP_NAME = "avante_conflicts"
|
||||
|
||||
local conflict_start = "^<<<<<<<"
|
||||
@ -96,9 +96,7 @@ local conflict_end = "^>>>>>>>"
|
||||
local function create_visited_buffers()
|
||||
return setmetatable({}, {
|
||||
__index = function(t, k)
|
||||
if type(k) == "number" then
|
||||
return t[api.nvim_buf_get_name(k)]
|
||||
end
|
||||
if type(k) == "number" then return t[api.nvim_buf_get_name(k)] end
|
||||
end,
|
||||
})
|
||||
end
|
||||
@ -114,14 +112,10 @@ local visited_buffers = create_visited_buffers()
|
||||
---@param buf integer
|
||||
---@param positions ConflictPosition[]
|
||||
local function update_visited_buffers(buf, positions)
|
||||
if not buf or not api.nvim_buf_is_valid(buf) then
|
||||
return
|
||||
end
|
||||
if not buf or not api.nvim_buf_is_valid(buf) then return end
|
||||
local name = api.nvim_buf_get_name(buf)
|
||||
-- If this buffer is not in the list
|
||||
if not visited_buffers[name] then
|
||||
return
|
||||
end
|
||||
if not visited_buffers[name] then return end
|
||||
visited_buffers[name].bufnr = buf
|
||||
visited_buffers[name].tick = vim.b[buf].changedtick
|
||||
visited_buffers[name].positions = positions
|
||||
@ -139,9 +133,7 @@ end
|
||||
---@param range_end integer
|
||||
---@return integer? extmark_id
|
||||
local function hl_range(bufnr, hl, range_start, range_end)
|
||||
if not range_start or not range_end then
|
||||
return
|
||||
end
|
||||
if not range_start or not range_end then return end
|
||||
return api.nvim_buf_set_extmark(bufnr, NAMESPACE, range_start, 0, {
|
||||
hl_group = hl,
|
||||
hl_eol = true,
|
||||
@ -246,26 +238,20 @@ end
|
||||
---@return ConflictPosition?
|
||||
local function find_position(bufnr, comparator, opts)
|
||||
local match = visited_buffers[bufnr]
|
||||
if not match then
|
||||
return
|
||||
end
|
||||
if not match then return end
|
||||
local line = Utils.get_cursor_pos()
|
||||
line = line - 1 -- Convert to 0-based for position comparison
|
||||
|
||||
if opts and opts.reverse then
|
||||
for i = #match.positions, 1, -1 do
|
||||
local position = match.positions[i]
|
||||
if comparator(line, position) then
|
||||
return position
|
||||
end
|
||||
if comparator(line, position) then return position end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
for _, position in ipairs(match.positions) do
|
||||
if comparator(line, position) then
|
||||
return position
|
||||
end
|
||||
if comparator(line, position) then return position end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
@ -274,17 +260,16 @@ end
|
||||
---@param bufnr integer
|
||||
---@return ConflictPosition?
|
||||
local function get_current_position(bufnr)
|
||||
return find_position(bufnr, function(line, position)
|
||||
return position.current.range_start <= line and position.incoming.range_end >= line
|
||||
end)
|
||||
return find_position(
|
||||
bufnr,
|
||||
function(line, position) return position.current.range_start <= line and position.incoming.range_end >= line end
|
||||
)
|
||||
end
|
||||
|
||||
---@param position ConflictPosition?
|
||||
---@param side ConflictSide
|
||||
local function set_cursor(position, side)
|
||||
if not position then
|
||||
return
|
||||
end
|
||||
if not position then return end
|
||||
local target = side == SIDES.OURS and position.current or position.incoming
|
||||
api.nvim_win_set_cursor(0, { target.range_start + 1, 0 })
|
||||
end
|
||||
@ -356,9 +341,7 @@ end
|
||||
---@param range_end integer?
|
||||
function M.process(bufnr, range_start, range_end)
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
if visited_buffers[bufnr] and visited_buffers[bufnr].tick == vim.b[bufnr].changedtick then
|
||||
return
|
||||
end
|
||||
if visited_buffers[bufnr] and visited_buffers[bufnr].tick == vim.b[bufnr].changedtick then return end
|
||||
parse_buffer(bufnr, range_start, range_end)
|
||||
end
|
||||
|
||||
@ -369,44 +352,29 @@ end
|
||||
---@param bufnr integer given buffer id
|
||||
H.setup_buffer_mappings = function(bufnr)
|
||||
---@param desc string
|
||||
local function opts(desc)
|
||||
return { silent = true, buffer = bufnr, desc = "avante(conflict): " .. desc }
|
||||
end
|
||||
local function opts(desc) return { silent = true, buffer = bufnr, desc = "avante(conflict): " .. desc } end
|
||||
|
||||
vim.keymap.set({ "n", "v" }, Config.diff.mappings.ours, function()
|
||||
M.choose("ours")
|
||||
end, opts("choose ours"))
|
||||
vim.keymap.set({ "n", "v" }, Config.diff.mappings.both, function()
|
||||
M.choose("both")
|
||||
end, opts("choose both"))
|
||||
vim.keymap.set({ "n", "v" }, Config.diff.mappings.theirs, function()
|
||||
M.choose("theirs")
|
||||
end, opts("choose theirs"))
|
||||
vim.keymap.set({ "n", "v" }, Config.diff.mappings.all_theirs, function()
|
||||
M.choose("all_theirs")
|
||||
end, opts("choose all theirs"))
|
||||
vim.keymap.set("n", Config.diff.mappings.cursor, function()
|
||||
M.choose("cursor")
|
||||
end, opts("choose under cursor"))
|
||||
vim.keymap.set("n", Config.diff.mappings.prev, function()
|
||||
M.find_prev("ours")
|
||||
end, opts("previous conflict"))
|
||||
vim.keymap.set("n", Config.diff.mappings.next, function()
|
||||
M.find_next("ours")
|
||||
end, opts("next conflict"))
|
||||
vim.keymap.set({ "n", "v" }, Config.diff.mappings.ours, function() M.choose "ours" end, opts "choose ours")
|
||||
vim.keymap.set({ "n", "v" }, Config.diff.mappings.both, function() M.choose "both" end, opts "choose both")
|
||||
vim.keymap.set({ "n", "v" }, Config.diff.mappings.theirs, function() M.choose "theirs" end, opts "choose theirs")
|
||||
vim.keymap.set(
|
||||
{ "n", "v" },
|
||||
Config.diff.mappings.all_theirs,
|
||||
function() M.choose "all_theirs" end,
|
||||
opts "choose all theirs"
|
||||
)
|
||||
vim.keymap.set("n", Config.diff.mappings.cursor, function() M.choose "cursor" end, opts "choose under cursor")
|
||||
vim.keymap.set("n", Config.diff.mappings.prev, function() M.find_prev "ours" end, opts "previous conflict")
|
||||
vim.keymap.set("n", Config.diff.mappings.next, function() M.find_next "ours" end, opts "next conflict")
|
||||
|
||||
vim.b[bufnr].avante_conflict_mappings_set = true
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
H.clear_buffer_mappings = function(bufnr)
|
||||
if not bufnr or not vim.b[bufnr].avante_conflict_mappings_set then
|
||||
return
|
||||
end
|
||||
if not bufnr or not vim.b[bufnr].avante_conflict_mappings_set then return end
|
||||
for _, mapping in pairs(Config.diff.mappings) do
|
||||
if vim.fn.hasmapto(mapping, "n") > 0 then
|
||||
api.nvim_buf_del_keymap(bufnr, "n", mapping)
|
||||
end
|
||||
if vim.fn.hasmapto(mapping, "n") > 0 then api.nvim_buf_del_keymap(bufnr, "n", mapping) end
|
||||
end
|
||||
vim.b[bufnr].avante_conflict_mappings_set = false
|
||||
end
|
||||
@ -422,7 +390,7 @@ function M.setup()
|
||||
callback = function(ev)
|
||||
vim.diagnostic.enable(false, { bufnr = ev.buf })
|
||||
if vim.lsp.inlay_hint then
|
||||
previous_inlay_enabled = vim.lsp.inlay_hint.is_enabled({ bufnr = ev.buf })
|
||||
previous_inlay_enabled = vim.lsp.inlay_hint.is_enabled { bufnr = ev.buf }
|
||||
vim.lsp.inlay_hint.enable(false, { bufnr = ev.buf })
|
||||
end
|
||||
H.setup_buffer_mappings(ev.buf)
|
||||
@ -443,13 +411,9 @@ function M.setup()
|
||||
})
|
||||
|
||||
api.nvim_set_decoration_provider(NAMESPACE, {
|
||||
on_buf = function(_, bufnr, _)
|
||||
return Utils.is_valid_buf(bufnr)
|
||||
end,
|
||||
on_buf = function(_, bufnr, _) return Utils.is_valid_buf(bufnr) end,
|
||||
on_win = function(_, _, bufnr, _, _)
|
||||
if visited_buffers[bufnr] then
|
||||
M.process(bufnr)
|
||||
end
|
||||
if visited_buffers[bufnr] then M.process(bufnr) end
|
||||
end,
|
||||
})
|
||||
end
|
||||
@ -460,9 +424,7 @@ end
|
||||
---@param items table<string, integer|string>[]
|
||||
---@param visited_buf ConflictBufferCache
|
||||
local function quickfix_items_from_positions(item, items, visited_buf)
|
||||
if vim.tbl_isempty(visited_buf.positions) then
|
||||
return
|
||||
end
|
||||
if vim.tbl_isempty(visited_buf.positions) then return end
|
||||
for _, pos in ipairs(visited_buf.positions) do
|
||||
for key, value in pairs(pos) do
|
||||
if vim.tbl_contains({ name_map.ours, name_map.theirs, name_map.base }, key) and not vim.tbl_isempty(value) then
|
||||
@ -502,9 +464,7 @@ end
|
||||
|
||||
---@param bufnr integer?
|
||||
function M.clear(bufnr)
|
||||
if bufnr and not api.nvim_buf_is_valid(bufnr) then
|
||||
return
|
||||
end
|
||||
if bufnr and not api.nvim_buf_is_valid(bufnr) then return end
|
||||
bufnr = bufnr or 0
|
||||
api.nvim_buf_clear_namespace(bufnr, NAMESPACE, 0, -1)
|
||||
api.nvim_buf_clear_namespace(bufnr, KEYBINDING_NAMESPACE, 0, -1)
|
||||
@ -512,17 +472,20 @@ end
|
||||
|
||||
---@param side ConflictSide
|
||||
function M.find_next(side)
|
||||
local pos = find_position(0, function(line, position)
|
||||
return position.current.range_start >= line and position.incoming.range_end >= line
|
||||
end)
|
||||
local pos = find_position(
|
||||
0,
|
||||
function(line, position) return position.current.range_start >= line and position.incoming.range_end >= line end
|
||||
)
|
||||
set_cursor(pos, side)
|
||||
end
|
||||
|
||||
---@param side ConflictSide
|
||||
function M.find_prev(side)
|
||||
local pos = find_position(0, function(line, position)
|
||||
return position.current.range_start <= line and position.incoming.range_end <= line
|
||||
end, { reverse = true })
|
||||
local pos = find_position(
|
||||
0,
|
||||
function(line, position) return position.current.range_start <= line and position.incoming.range_end <= line end,
|
||||
{ reverse = true }
|
||||
)
|
||||
set_cursor(pos, side)
|
||||
end
|
||||
|
||||
@ -552,25 +515,19 @@ function M.choose(side)
|
||||
end, 50)
|
||||
if Config.diff.autojump then
|
||||
M.find_next(side)
|
||||
vim.cmd([[normal! zz]])
|
||||
vim.cmd [[normal! zz]]
|
||||
end
|
||||
return
|
||||
end
|
||||
local position = get_current_position(bufnr)
|
||||
if not position then
|
||||
return
|
||||
end
|
||||
if not position then return end
|
||||
if side == SIDES.ALL_THEIRS then
|
||||
---@diagnostic disable-next-line: unused-local
|
||||
local pos = find_position(bufnr, function(line, pos)
|
||||
return true
|
||||
end)
|
||||
local pos = find_position(bufnr, function(line, pos) return true end)
|
||||
while pos ~= nil do
|
||||
M.process_position(bufnr, "theirs", pos, false)
|
||||
---@diagnostic disable-next-line: unused-local
|
||||
pos = find_position(bufnr, function(line, pos_)
|
||||
return true
|
||||
end)
|
||||
pos = find_position(bufnr, function(line, pos_) return true end)
|
||||
end
|
||||
else
|
||||
M.process_position(bufnr, side, position, true)
|
||||
@ -593,7 +550,7 @@ function M.process_position(bufnr, side, position, enable_autojump)
|
||||
lines = {}
|
||||
elseif side == SIDES.CURSOR then
|
||||
local cursor_line = Utils.get_cursor_pos()
|
||||
for _, pos in ipairs({ SIDES.OURS, SIDES.THEIRS, SIDES.BASE }) do
|
||||
for _, pos in ipairs { SIDES.OURS, SIDES.THEIRS, SIDES.BASE } do
|
||||
local data = position[name_map[pos]] or {}
|
||||
if data.range_start and data.range_start + 1 <= cursor_line and data.range_end + 1 >= cursor_line then
|
||||
side = pos
|
||||
@ -601,9 +558,7 @@ function M.process_position(bufnr, side, position, enable_autojump)
|
||||
break
|
||||
end
|
||||
end
|
||||
if side == SIDES.CURSOR then
|
||||
return
|
||||
end
|
||||
if side == SIDES.CURSOR then return end
|
||||
else
|
||||
return
|
||||
end
|
||||
@ -617,20 +572,16 @@ function M.process_position(bufnr, side, position, enable_autojump)
|
||||
parse_buffer(bufnr)
|
||||
if enable_autojump and Config.diff.autojump then
|
||||
M.find_next(side)
|
||||
vim.cmd([[normal! zz]])
|
||||
vim.cmd [[normal! zz]]
|
||||
end
|
||||
end
|
||||
|
||||
function M.conflict_count(bufnr)
|
||||
if bufnr and not api.nvim_buf_is_valid(bufnr) then
|
||||
return 0
|
||||
end
|
||||
if bufnr and not api.nvim_buf_is_valid(bufnr) then return 0 end
|
||||
bufnr = bufnr or 0
|
||||
|
||||
local name = api.nvim_buf_get_name(bufnr)
|
||||
if not visited_buffers[name] then
|
||||
return 0
|
||||
end
|
||||
if not visited_buffers[name] then return 0 end
|
||||
|
||||
return #visited_buffers[name].positions
|
||||
end
|
||||
|
@ -1,7 +1,7 @@
|
||||
local api = vim.api
|
||||
|
||||
local Config = require("avante.config")
|
||||
local bit = require("bit")
|
||||
local Config = require "avante.config"
|
||||
local bit = require "bit"
|
||||
local rshift, band = bit.rshift, bit.band
|
||||
|
||||
local Highlights = {
|
||||
@ -29,8 +29,8 @@ local H = {}
|
||||
|
||||
local M = {}
|
||||
|
||||
M.input_ns = api.nvim_create_namespace("avante_input")
|
||||
M.hint_ns = api.nvim_create_namespace("avante_hint")
|
||||
M.input_ns = api.nvim_create_namespace "avante_input"
|
||||
M.hint_ns = api.nvim_create_namespace "avante_hint"
|
||||
|
||||
local function has_set_colors(hl_group)
|
||||
local hl = api.nvim_get_hl(0, { name = hl_group })
|
||||
@ -46,7 +46,7 @@ M.setup = function()
|
||||
.iter(Highlights)
|
||||
:filter(function(k, _)
|
||||
-- return all uppercase key with underscore or fully uppercase key
|
||||
return k:match("^%u+_") or k:match("^%u+$")
|
||||
return k:match "^%u+_" or k:match "^%u+$"
|
||||
end)
|
||||
:each(function(_, hl)
|
||||
if not has_set_colors(hl.name) then
|
||||
@ -114,7 +114,7 @@ setmetatable(M, {
|
||||
---@param rgb_24bit number 24-bit RGB value
|
||||
---@return {r: integer, g: integer, b: integer} with keys 'r', 'g', 'b' in [0,255]
|
||||
H.decode_24bit_rgb = function(rgb_24bit)
|
||||
vim.validate({ rgb_24bit = { rgb_24bit, "n", true } })
|
||||
vim.validate { rgb_24bit = { rgb_24bit, "n", true } }
|
||||
local r = band(rshift(rgb_24bit, 16), 255)
|
||||
local g = band(rshift(rgb_24bit, 8), 255)
|
||||
local b = band(rgb_24bit, 255)
|
||||
@ -123,9 +123,7 @@ end
|
||||
|
||||
---@param attr integer
|
||||
---@param percent integer
|
||||
H.alter = function(attr, percent)
|
||||
return math.floor(attr * (100 + percent) / 100)
|
||||
end
|
||||
H.alter = function(attr, percent) return math.floor(attr * (100 + percent) / 100) end
|
||||
|
||||
---@source https://stackoverflow.com/q/5560248
|
||||
---@see https://stackoverflow.com/a/37797380
|
||||
@ -135,9 +133,7 @@ end
|
||||
---@return string
|
||||
H.shade_color = function(color, percent)
|
||||
local rgb = H.decode_24bit_rgb(color)
|
||||
if not rgb.r or not rgb.g or not rgb.b then
|
||||
return "NONE"
|
||||
end
|
||||
if not rgb.r or not rgb.g or not rgb.b then return "NONE" end
|
||||
local r, g, b = H.alter(rgb.r, percent), H.alter(rgb.g, percent), H.alter(rgb.b, percent)
|
||||
r, g, b = math.min(r, 255), math.min(g, 255), math.min(b, 255)
|
||||
return string.format("#%02x%02x%02x", r, g, b)
|
||||
|
@ -1,11 +1,11 @@
|
||||
local api = vim.api
|
||||
|
||||
local Utils = require("avante.utils")
|
||||
local Sidebar = require("avante.sidebar")
|
||||
local Selection = require("avante.selection")
|
||||
local Suggestion = require("avante.suggestion")
|
||||
local Config = require("avante.config")
|
||||
local Diff = require("avante.diff")
|
||||
local Utils = require "avante.utils"
|
||||
local Sidebar = require "avante.sidebar"
|
||||
local Selection = require "avante.selection"
|
||||
local Suggestion = require "avante.suggestion"
|
||||
local Config = require "avante.config"
|
||||
local Diff = require "avante.diff"
|
||||
|
||||
---@class Avante
|
||||
local M = {
|
||||
@ -32,97 +32,78 @@ H.commands = function()
|
||||
api.nvim_create_user_command("Avante" .. n, c, o)
|
||||
end
|
||||
|
||||
cmd("Ask", function(opts)
|
||||
require("avante.api").ask(vim.trim(opts.args))
|
||||
end, { desc = "avante: ask AI for code suggestions", nargs = "*" })
|
||||
cmd("Toggle", function()
|
||||
M.toggle()
|
||||
end, { desc = "avante: toggle AI panel" })
|
||||
cmd("Edit", function(opts)
|
||||
require("avante.api").edit(vim.trim(opts.args))
|
||||
end, { desc = "avante: edit selected block", nargs = "*" })
|
||||
cmd("Refresh", function()
|
||||
require("avante.api").refresh()
|
||||
end, { desc = "avante: refresh windows" })
|
||||
cmd("Build", function()
|
||||
M.build()
|
||||
end, { desc = "avante: build dependencies" })
|
||||
cmd("SwitchProvider", function(opts)
|
||||
require("avante.api").switch_provider(vim.trim(opts.args or ""))
|
||||
end, {
|
||||
cmd(
|
||||
"Ask",
|
||||
function(opts) require("avante.api").ask(vim.trim(opts.args)) end,
|
||||
{ desc = "avante: ask AI for code suggestions", nargs = "*" }
|
||||
)
|
||||
cmd("Toggle", function() M.toggle() end, { desc = "avante: toggle AI panel" })
|
||||
cmd(
|
||||
"Edit",
|
||||
function(opts) require("avante.api").edit(vim.trim(opts.args)) end,
|
||||
{ desc = "avante: edit selected block", nargs = "*" }
|
||||
)
|
||||
cmd("Refresh", function() require("avante.api").refresh() end, { desc = "avante: refresh windows" })
|
||||
cmd("Build", function() M.build() end, { desc = "avante: build dependencies" })
|
||||
cmd("SwitchProvider", function(opts) require("avante.api").switch_provider(vim.trim(opts.args or "")) end, {
|
||||
nargs = 1,
|
||||
desc = "avante: switch provider",
|
||||
complete = function(_, line, _)
|
||||
local prefix = line:match("AvanteSwitchProvider%s*(.*)$") or ""
|
||||
local prefix = line:match "AvanteSwitchProvider%s*(.*)$" or ""
|
||||
---@param key string
|
||||
return vim.tbl_filter(function(key)
|
||||
return key:find(prefix, 1, true) == 1
|
||||
end, Config.providers)
|
||||
return vim.tbl_filter(function(key) return key:find(prefix, 1, true) == 1 end, Config.providers)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
H.keymaps = function()
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteAsk)", function()
|
||||
require("avante.api").ask()
|
||||
end, { noremap = true })
|
||||
vim.keymap.set("v", "<Plug>(AvanteEdit)", function()
|
||||
require("avante.api").edit()
|
||||
end, { noremap = true })
|
||||
vim.keymap.set("n", "<Plug>(AvanteRefresh)", function()
|
||||
require("avante.api").refresh()
|
||||
end, { noremap = true })
|
||||
vim.keymap.set("n", "<Plug>(AvanteToggle)", function()
|
||||
M.toggle()
|
||||
end, { noremap = true })
|
||||
vim.keymap.set("n", "<Plug>(AvanteToggleDebug)", function()
|
||||
M.toggle.debug()
|
||||
end)
|
||||
vim.keymap.set("n", "<Plug>(AvanteToggleHint)", function()
|
||||
M.toggle.hint()
|
||||
end)
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteAsk)", function() require("avante.api").ask() end, { noremap = true })
|
||||
vim.keymap.set("v", "<Plug>(AvanteEdit)", function() require("avante.api").edit() end, { noremap = true })
|
||||
vim.keymap.set("n", "<Plug>(AvanteRefresh)", function() require("avante.api").refresh() end, { noremap = true })
|
||||
vim.keymap.set("n", "<Plug>(AvanteToggle)", function() M.toggle() end, { noremap = true })
|
||||
vim.keymap.set("n", "<Plug>(AvanteToggleDebug)", function() M.toggle.debug() end)
|
||||
vim.keymap.set("n", "<Plug>(AvanteToggleHint)", function() M.toggle.hint() end)
|
||||
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteConflictOurs)", function()
|
||||
Diff.choose("ours")
|
||||
end)
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteConflictBoth)", function()
|
||||
Diff.choose("both")
|
||||
end)
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteConflictTheirs)", function()
|
||||
Diff.choose("theirs")
|
||||
end)
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteConflictAllTheirs)", function()
|
||||
Diff.choose("all_theirs")
|
||||
end)
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteConflictCursor)", function()
|
||||
Diff.choose("cursor")
|
||||
end)
|
||||
vim.keymap.set("n", "<Plug>(AvanteConflictNextConflict)", function()
|
||||
Diff.find_next("ours")
|
||||
end)
|
||||
vim.keymap.set("n", "<Plug>(AvanteConflictPrevConflict)", function()
|
||||
Diff.find_prev("ours")
|
||||
end)
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteConflictOurs)", function() Diff.choose "ours" end)
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteConflictBoth)", function() Diff.choose "both" end)
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteConflictTheirs)", function() Diff.choose "theirs" end)
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteConflictAllTheirs)", function() Diff.choose "all_theirs" end)
|
||||
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteConflictCursor)", function() Diff.choose "cursor" end)
|
||||
vim.keymap.set("n", "<Plug>(AvanteConflictNextConflict)", function() Diff.find_next "ours" end)
|
||||
vim.keymap.set("n", "<Plug>(AvanteConflictPrevConflict)", function() Diff.find_prev "ours" end)
|
||||
|
||||
if Config.behaviour.auto_set_keymaps then
|
||||
Utils.safe_keymap_set({ "n", "v" }, Config.mappings.ask, function()
|
||||
require("avante.api").ask()
|
||||
end, { desc = "avante: ask" })
|
||||
Utils.safe_keymap_set("v", Config.mappings.edit, function()
|
||||
require("avante.api").edit()
|
||||
end, { desc = "avante: edit" })
|
||||
Utils.safe_keymap_set("n", Config.mappings.refresh, function()
|
||||
require("avante.api").refresh()
|
||||
end, { desc = "avante: refresh" })
|
||||
Utils.safe_keymap_set("n", Config.mappings.toggle.default, function()
|
||||
M.toggle()
|
||||
end, { desc = "avante: toggle" })
|
||||
Utils.safe_keymap_set("n", Config.mappings.toggle.debug, function()
|
||||
M.toggle.debug()
|
||||
end, { desc = "avante: toggle debug" })
|
||||
Utils.safe_keymap_set("n", Config.mappings.toggle.hint, function()
|
||||
M.toggle.hint()
|
||||
end, { desc = "avante: toggle hint" })
|
||||
Utils.safe_keymap_set(
|
||||
{ "n", "v" },
|
||||
Config.mappings.ask,
|
||||
function() require("avante.api").ask() end,
|
||||
{ desc = "avante: ask" }
|
||||
)
|
||||
Utils.safe_keymap_set(
|
||||
"v",
|
||||
Config.mappings.edit,
|
||||
function() require("avante.api").edit() end,
|
||||
{ desc = "avante: edit" }
|
||||
)
|
||||
Utils.safe_keymap_set(
|
||||
"n",
|
||||
Config.mappings.refresh,
|
||||
function() require("avante.api").refresh() end,
|
||||
{ desc = "avante: refresh" }
|
||||
)
|
||||
Utils.safe_keymap_set("n", Config.mappings.toggle.default, function() M.toggle() end, { desc = "avante: toggle" })
|
||||
Utils.safe_keymap_set(
|
||||
"n",
|
||||
Config.mappings.toggle.debug,
|
||||
function() M.toggle.debug() end,
|
||||
{ desc = "avante: toggle debug" }
|
||||
)
|
||||
Utils.safe_keymap_set(
|
||||
"n",
|
||||
Config.mappings.toggle.hint,
|
||||
function() M.toggle.hint() end,
|
||||
{ desc = "avante: toggle hint" }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@ -131,15 +112,11 @@ end
|
||||
|
||||
H.api = function(fun)
|
||||
return setmetatable({ api = true }, {
|
||||
__call = function(...)
|
||||
return fun(...)
|
||||
end,
|
||||
__call = function(...) return fun(...) end,
|
||||
}) --[[@as ApiCaller]]
|
||||
end
|
||||
|
||||
H.signs = function()
|
||||
vim.fn.sign_define("AvanteInputPromptSign", { text = Config.windows.input.prefix })
|
||||
end
|
||||
H.signs = function() vim.fn.sign_define("AvanteInputPromptSign", { text = Config.windows.input.prefix }) end
|
||||
|
||||
H.augroup = api.nvim_create_augroup("avante_autocmds", { clear = true })
|
||||
|
||||
@ -148,9 +125,7 @@ H.autocmds = function()
|
||||
|
||||
if ok then
|
||||
local name = "avante.nvim"
|
||||
local load_path = function()
|
||||
require("avante_lib").load()
|
||||
end
|
||||
local load_path = function() require("avante_lib").load() end
|
||||
|
||||
if LazyConfig.plugins[name] and LazyConfig.plugins[name]._.loaded then
|
||||
vim.schedule(load_path)
|
||||
@ -179,9 +154,7 @@ H.autocmds = function()
|
||||
callback = function(ev)
|
||||
local tab = tonumber(ev.file)
|
||||
M._init(tab or api.nvim_get_current_tabpage())
|
||||
if Config.hints.enabled and not M.current.selection.did_setup then
|
||||
M.current.selection:setup_autocmds()
|
||||
end
|
||||
if Config.hints.enabled and not M.current.selection.did_setup then M.current.selection:setup_autocmds() end
|
||||
end,
|
||||
})
|
||||
|
||||
@ -189,12 +162,8 @@ H.autocmds = function()
|
||||
group = H.augroup,
|
||||
callback = function()
|
||||
local sidebar = M.get()
|
||||
if not sidebar then
|
||||
return
|
||||
end
|
||||
if not sidebar:is_open() then
|
||||
return
|
||||
end
|
||||
if not sidebar then return end
|
||||
if not sidebar:is_open() then return end
|
||||
sidebar:resize()
|
||||
end,
|
||||
})
|
||||
@ -206,43 +175,33 @@ H.autocmds = function()
|
||||
local tab = tonumber(ev.file)
|
||||
local s = M.sidebars[tab]
|
||||
local sl = M.selections[tab]
|
||||
if s then
|
||||
s:reset()
|
||||
end
|
||||
if sl then
|
||||
sl:delete_autocmds()
|
||||
end
|
||||
if tab ~= nil then
|
||||
M.sidebars[tab] = nil
|
||||
end
|
||||
if s then s:reset() end
|
||||
if sl then sl:delete_autocmds() end
|
||||
if tab ~= nil then M.sidebars[tab] = nil end
|
||||
end,
|
||||
})
|
||||
|
||||
vim.schedule(function()
|
||||
M._init(api.nvim_get_current_tabpage())
|
||||
if Config.hints.enabled then
|
||||
M.current.selection:setup_autocmds()
|
||||
end
|
||||
if Config.hints.enabled then M.current.selection:setup_autocmds() end
|
||||
end)
|
||||
|
||||
api.nvim_create_autocmd("ColorSchemePre", {
|
||||
group = H.augroup,
|
||||
callback = function()
|
||||
require("avante.highlights").setup()
|
||||
end,
|
||||
callback = function() require("avante.highlights").setup() end,
|
||||
})
|
||||
|
||||
-- automatically setup Avante filetype to markdown
|
||||
vim.treesitter.language.register("markdown", "Avante")
|
||||
|
||||
vim.filetype.add({
|
||||
vim.filetype.add {
|
||||
extension = {
|
||||
["avanterules"] = "jinja",
|
||||
},
|
||||
pattern = {
|
||||
["%.avanterules%.[%w_.-]+"] = "jinja",
|
||||
},
|
||||
})
|
||||
}
|
||||
end
|
||||
|
||||
---@param current boolean? false to disable setting current, otherwise use this to track across tabs.
|
||||
@ -284,25 +243,17 @@ end
|
||||
|
||||
M.toggle = { api = true }
|
||||
|
||||
M.toggle.debug = H.api(Utils.toggle_wrap({
|
||||
M.toggle.debug = H.api(Utils.toggle_wrap {
|
||||
name = "debug",
|
||||
get = function()
|
||||
return Config.debug
|
||||
end,
|
||||
set = function(state)
|
||||
Config.override({ debug = state })
|
||||
end,
|
||||
}))
|
||||
get = function() return Config.debug end,
|
||||
set = function(state) Config.override { debug = state } end,
|
||||
})
|
||||
|
||||
M.toggle.hint = H.api(Utils.toggle_wrap({
|
||||
M.toggle.hint = H.api(Utils.toggle_wrap {
|
||||
name = "hint",
|
||||
get = function()
|
||||
return Config.hints.enabled
|
||||
end,
|
||||
set = function(state)
|
||||
Config.override({ hints = { enabled = state } })
|
||||
end,
|
||||
}))
|
||||
get = function() return Config.hints.enabled end,
|
||||
set = function(state) Config.override { hints = { enabled = state } } end,
|
||||
})
|
||||
|
||||
setmetatable(M.toggle, {
|
||||
__index = M.toggle,
|
||||
@ -322,9 +273,7 @@ setmetatable(M.toggle, {
|
||||
local function to_windows_path(path)
|
||||
local winpath = path:gsub("/", "\\")
|
||||
|
||||
if winpath:match("^%a:") then
|
||||
winpath = winpath:sub(1, 2):upper() .. winpath:sub(3)
|
||||
end
|
||||
if winpath:match "^%a:" then winpath = winpath:sub(1, 2):upper() .. winpath:sub(3) end
|
||||
|
||||
winpath = winpath:gsub("\\$", "")
|
||||
|
||||
@ -336,9 +285,7 @@ M.build = H.api(function()
|
||||
local git_root = vim.fs.find(".git", { path = dirname, upward = true })[1]
|
||||
local build_directory = git_root and vim.fn.fnamemodify(git_root, ":h") or (dirname .. "/../../")
|
||||
|
||||
if not vim.fn.executable("cargo") then
|
||||
error("Building avante.nvim requires cargo to be installed.", 2)
|
||||
end
|
||||
if not vim.fn.executable "cargo" then error("Building avante.nvim requires cargo to be installed.", 2) end
|
||||
|
||||
---@type string[]
|
||||
local cmd
|
||||
@ -372,9 +319,7 @@ function M.setup(opts)
|
||||
---but most of the other functionality will only be called once from lazy.nvim
|
||||
Config.setup(opts)
|
||||
|
||||
if M.did_setup then
|
||||
return
|
||||
end
|
||||
if M.did_setup then return end
|
||||
|
||||
require("avante.path").setup()
|
||||
require("avante.highlights").setup()
|
||||
|
@ -1,11 +1,11 @@
|
||||
local api = vim.api
|
||||
|
||||
local curl = require("plenary.curl")
|
||||
local curl = require "plenary.curl"
|
||||
|
||||
local Utils = require("avante.utils")
|
||||
local Config = require("avante.config")
|
||||
local Path = require("avante.path")
|
||||
local P = require("avante.providers")
|
||||
local Utils = require "avante.utils"
|
||||
local Config = require "avante.config"
|
||||
local Path = require "avante.path"
|
||||
local P = require "avante.providers"
|
||||
|
||||
---@class avante.LLM
|
||||
local M = {}
|
||||
@ -44,10 +44,10 @@ M.stream = function(opts)
|
||||
-- Check if the instructions contains an image path
|
||||
local image_paths = {}
|
||||
local original_instructions = opts.instructions
|
||||
if opts.instructions:match("image: ") then
|
||||
if opts.instructions:match "image: " then
|
||||
local lines = vim.split(opts.instructions, "\n")
|
||||
for i, line in ipairs(lines) do
|
||||
if line:match("^image: ") then
|
||||
if line:match "^image: " then
|
||||
local image_path = line:gsub("^image: ", "")
|
||||
table.insert(image_paths, image_path)
|
||||
table.remove(lines, i)
|
||||
@ -89,15 +89,13 @@ M.stream = function(opts)
|
||||
|
||||
---@param line string
|
||||
local function parse_stream_data(line)
|
||||
local event = line:match("^event: (.+)$")
|
||||
local event = line:match "^event: (.+)$"
|
||||
if event then
|
||||
current_event_state = event
|
||||
return
|
||||
end
|
||||
local data_match = line:match("^data: (.+)$")
|
||||
if data_match then
|
||||
Provider.parse_response(data_match, current_event_state, handler_opts)
|
||||
end
|
||||
local data_match = line:match "^data: (.+)$"
|
||||
if data_match then Provider.parse_response(data_match, current_event_state, handler_opts) end
|
||||
end
|
||||
|
||||
local completed = false
|
||||
@ -115,9 +113,7 @@ M.stream = function(opts)
|
||||
opts.on_complete(err)
|
||||
return
|
||||
end
|
||||
if not data then
|
||||
return
|
||||
end
|
||||
if not data then return end
|
||||
vim.schedule(function()
|
||||
if Config.options[Config.provider] == nil and Provider.parse_stream_data ~= nil then
|
||||
if Provider.parse_response ~= nil then
|
||||
@ -168,11 +164,7 @@ M.stream = function(opts)
|
||||
callback = function()
|
||||
-- Error: cannot resume dead coroutine
|
||||
if active_job then
|
||||
xpcall(function()
|
||||
active_job:shutdown()
|
||||
end, function(err)
|
||||
return err
|
||||
end)
|
||||
xpcall(function() active_job:shutdown() end, function(err) return err end)
|
||||
Utils.debug("LLM request cancelled", { title = "Avante" })
|
||||
active_job = nil
|
||||
end
|
||||
@ -182,8 +174,6 @@ M.stream = function(opts)
|
||||
return active_job
|
||||
end
|
||||
|
||||
function M.cancel_inflight_request()
|
||||
api.nvim_exec_autocmds("User", { pattern = M.CANCEL_PATTERN })
|
||||
end
|
||||
function M.cancel_inflight_request() api.nvim_exec_autocmds("User", { pattern = M.CANCEL_PATTERN }) end
|
||||
|
||||
return M
|
||||
|
@ -1,8 +1,8 @@
|
||||
local fn, api = vim.fn, vim.api
|
||||
local Utils = require("avante.utils")
|
||||
local Path = require("plenary.path")
|
||||
local Scan = require("plenary.scandir")
|
||||
local Config = require("avante.config")
|
||||
local Utils = require "avante.utils"
|
||||
local Path = require "plenary.path"
|
||||
local Scan = require "plenary.scandir"
|
||||
local Config = require "avante.config"
|
||||
|
||||
---@class avante.Path
|
||||
---@field history_path Path
|
||||
@ -25,9 +25,7 @@ end
|
||||
|
||||
-- Given a mode, return the file name for the custom prompt.
|
||||
---@param mode LlmMode
|
||||
H.get_mode_file = function(mode)
|
||||
return string.format("custom.%s.avanterules", mode)
|
||||
end
|
||||
H.get_mode_file = function(mode) return string.format("custom.%s.avanterules", mode) end
|
||||
|
||||
-- History path
|
||||
local M = {}
|
||||
@ -35,9 +33,7 @@ local M = {}
|
||||
-- Returns the Path to the chat history file for the given buffer.
|
||||
---@param bufnr integer
|
||||
---@return Path
|
||||
M.get = function(bufnr)
|
||||
return Path:new(Config.history.storage_path):joinpath(H.filename(bufnr))
|
||||
end
|
||||
M.get = function(bufnr) return Path:new(Config.history.storage_path):joinpath(H.filename(bufnr)) end
|
||||
|
||||
-- Loads the chat history for the given buffer.
|
||||
---@param bufnr integer
|
||||
@ -76,99 +72,72 @@ N.templates = { planning = nil, editing = nil, suggesting = nil }
|
||||
---@param bufnr number
|
||||
---@return string the resulted cache_directory to be loaded with avante_templates
|
||||
N.get = function(bufnr)
|
||||
if not P.available() then
|
||||
error("Make sure to build avante (missing avante_templates)", 2)
|
||||
end
|
||||
if not P.available() then error("Make sure to build avante (missing avante_templates)", 2) end
|
||||
|
||||
-- get root directory of given bufnr
|
||||
local directory = Path:new(Utils.root.get({ buf = bufnr }))
|
||||
local directory = Path:new(Utils.root.get { buf = bufnr })
|
||||
---@cast directory Path
|
||||
---@type Path
|
||||
local cache_prompt_dir = P.cache_path:joinpath(directory)
|
||||
if not cache_prompt_dir:exists() then
|
||||
cache_prompt_dir:mkdir({ parents = true })
|
||||
end
|
||||
if not cache_prompt_dir:exists() then cache_prompt_dir:mkdir { parents = true } end
|
||||
|
||||
local scanner = Scan.scan_dir(directory:absolute(), { depth = 1, add_dirs = true })
|
||||
for _, entry in ipairs(scanner) do
|
||||
local file = Path:new(entry)
|
||||
if entry:find("planning") and N.templates.planning == nil then
|
||||
if entry:find "planning" and N.templates.planning == nil then
|
||||
N.templates.planning = file:read()
|
||||
elseif entry:find("editing") and N.templates.editing == nil then
|
||||
elseif entry:find "editing" and N.templates.editing == nil then
|
||||
N.templates.editing = file:read()
|
||||
elseif entry:find("suggesting") and N.templates.suggesting == nil then
|
||||
elseif entry:find "suggesting" and N.templates.suggesting == nil then
|
||||
N.templates.suggesting = file:read()
|
||||
end
|
||||
end
|
||||
|
||||
Path:new(debug.getinfo(1).source:match("@?(.*/)"):gsub("/lua/avante/path.lua$", "") .. "templates")
|
||||
:copy({ destination = cache_prompt_dir, recursive = true })
|
||||
:copy { destination = cache_prompt_dir, recursive = true }
|
||||
|
||||
vim
|
||||
.iter(N.templates)
|
||||
:filter(function(_, v)
|
||||
return v ~= nil
|
||||
end)
|
||||
:each(function(k, v)
|
||||
local f = cache_prompt_dir:joinpath(H.get_mode_file(k))
|
||||
f:write(v, "w")
|
||||
end)
|
||||
vim.iter(N.templates):filter(function(_, v) return v ~= nil end):each(function(k, v)
|
||||
local f = cache_prompt_dir:joinpath(H.get_mode_file(k))
|
||||
f:write(v, "w")
|
||||
end)
|
||||
|
||||
return cache_prompt_dir:absolute()
|
||||
end
|
||||
|
||||
---@param mode LlmMode
|
||||
N.get_file = function(mode)
|
||||
if N.templates[mode] ~= nil then
|
||||
return H.get_mode_file(mode)
|
||||
end
|
||||
if N.templates[mode] ~= nil then return H.get_mode_file(mode) end
|
||||
return string.format("%s.avanterules", mode)
|
||||
end
|
||||
|
||||
---@param mode LlmMode
|
||||
---@param opts TemplateOptions
|
||||
N.render = function(mode, opts)
|
||||
return templates.render(N.get_file(mode), opts)
|
||||
end
|
||||
N.render = function(mode, opts) return templates.render(N.get_file(mode), opts) end
|
||||
|
||||
N.initialize = function(directory)
|
||||
templates.initialize(directory)
|
||||
end
|
||||
N.initialize = function(directory) templates.initialize(directory) end
|
||||
|
||||
P.prompts = N
|
||||
|
||||
P.setup = function()
|
||||
local history_path = Path:new(Config.history.storage_path)
|
||||
if not history_path:exists() then
|
||||
history_path:mkdir({ parents = true })
|
||||
end
|
||||
if not history_path:exists() then history_path:mkdir { parents = true } end
|
||||
P.history_path = history_path
|
||||
|
||||
local cache_path = Path:new(vim.fn.stdpath("cache") .. "/avante")
|
||||
if not cache_path:exists() then
|
||||
cache_path:mkdir({ parents = true })
|
||||
end
|
||||
local cache_path = Path:new(vim.fn.stdpath "cache" .. "/avante")
|
||||
if not cache_path:exists() then cache_path:mkdir { parents = true } end
|
||||
P.cache_path = cache_path
|
||||
|
||||
vim.defer_fn(function()
|
||||
local ok, module = pcall(require, "avante_templates")
|
||||
---@cast module AvanteTemplates
|
||||
---@cast ok boolean
|
||||
if not ok then
|
||||
return
|
||||
end
|
||||
if templates == nil then
|
||||
templates = module
|
||||
end
|
||||
if not ok then return end
|
||||
if templates == nil then templates = module end
|
||||
end, 1000)
|
||||
end
|
||||
|
||||
P.available = function()
|
||||
return templates ~= nil
|
||||
end
|
||||
P.available = function() return templates ~= nil end
|
||||
|
||||
P.clear = function()
|
||||
P.cache_path:rm({ recursive = true })
|
||||
end
|
||||
P.clear = function() P.cache_path:rm { recursive = true } end
|
||||
|
||||
return P
|
||||
|
@ -4,8 +4,8 @@
|
||||
---@field temperature number
|
||||
---@field max_tokens number
|
||||
|
||||
local Utils = require("avante.utils")
|
||||
local P = require("avante.providers")
|
||||
local Utils = require "avante.utils"
|
||||
local P = require "avante.providers"
|
||||
local O = require("avante.providers").openai
|
||||
|
||||
---@class AvanteProviderFunctor
|
||||
@ -23,9 +23,7 @@ M.parse_curl_args = function(provider, code_opts)
|
||||
local headers = {
|
||||
["Content-Type"] = "application/json",
|
||||
}
|
||||
if not P.env.is_local("azure") then
|
||||
headers["api-key"] = provider.parse_api_key()
|
||||
end
|
||||
if not P.env.is_local "azure" then headers["api-key"] = provider.parse_api_key() end
|
||||
|
||||
return {
|
||||
url = Utils.trim(base.endpoint, { suffix = "/" })
|
||||
|
@ -1,6 +1,6 @@
|
||||
local Utils = require("avante.utils")
|
||||
local Clipboard = require("avante.clipboard")
|
||||
local P = require("avante.providers")
|
||||
local Utils = require "avante.utils"
|
||||
local Clipboard = require "avante.clipboard"
|
||||
local P = require "avante.providers"
|
||||
|
||||
---@class AvanteProviderFunctor
|
||||
local M = {}
|
||||
@ -29,9 +29,7 @@ M.parse_message = function(opts)
|
||||
type = "text",
|
||||
text = opts.user_prompt,
|
||||
}
|
||||
if Utils.tokens.calculate_tokens(opts.user_prompt) then
|
||||
user_prompt_obj.cache_control = { type = "ephemeral" }
|
||||
end
|
||||
if Utils.tokens.calculate_tokens(opts.user_prompt) then user_prompt_obj.cache_control = { type = "ephemeral" } end
|
||||
|
||||
table.insert(message_content, user_prompt_obj)
|
||||
|
||||
@ -46,9 +44,7 @@ end
|
||||
M.parse_response = function(data_stream, event_state, opts)
|
||||
if event_state == "content_block_delta" then
|
||||
local ok, json = pcall(vim.json.decode, data_stream)
|
||||
if not ok then
|
||||
return
|
||||
end
|
||||
if not ok then return end
|
||||
opts.on_chunk(json.delta.text)
|
||||
elseif event_state == "message_stop" then
|
||||
opts.on_complete(nil)
|
||||
@ -69,9 +65,7 @@ M.parse_curl_args = function(provider, prompt_opts)
|
||||
["anthropic-version"] = "2023-06-01",
|
||||
["anthropic-beta"] = "prompt-caching-2024-07-31",
|
||||
}
|
||||
if not P.env.is_local("claude") then
|
||||
headers["x-api-key"] = provider.parse_api_key()
|
||||
end
|
||||
if not P.env.is_local "claude" then headers["x-api-key"] = provider.parse_api_key() end
|
||||
|
||||
local messages = M.parse_message(prompt_opts)
|
||||
|
||||
@ -110,7 +104,7 @@ M.on_error = function(result)
|
||||
|
||||
if error_type == "insufficient_quota" then
|
||||
error_msg = "You don't have any credits or have exceeded your quota. Please check your plan and billing details."
|
||||
elseif error_type == "invalid_request_error" and error_msg:match("temperature") then
|
||||
elseif error_type == "invalid_request_error" and error_msg:match "temperature" then
|
||||
error_msg = "Invalid temperature value. Please ensure it's between 0 and 1."
|
||||
end
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
local Utils = require("avante.utils")
|
||||
local P = require("avante.providers")
|
||||
local Utils = require "avante.utils"
|
||||
local P = require "avante.providers"
|
||||
|
||||
---@alias CohereFinishReason "COMPLETE" | "LENGTH" | "ERROR"
|
||||
---
|
||||
@ -52,9 +52,7 @@ M.parse_stream_data = function(data, opts)
|
||||
return
|
||||
end
|
||||
---@cast json CohereTextGenerationResponse
|
||||
if json.event_type == "text-generation" then
|
||||
opts.on_chunk(json.text)
|
||||
end
|
||||
if json.event_type == "text-generation" then opts.on_chunk(json.text) end
|
||||
end
|
||||
end
|
||||
|
||||
@ -71,9 +69,7 @@ M.parse_curl_args = function(provider, code_opts)
|
||||
.. "."
|
||||
.. vim.version().patch,
|
||||
}
|
||||
if not P.env.is_local("cohere") then
|
||||
headers["Authorization"] = "Bearer " .. provider.parse_api_key()
|
||||
end
|
||||
if not P.env.is_local "cohere" then headers["Authorization"] = "Bearer " .. provider.parse_api_key() end
|
||||
|
||||
return {
|
||||
url = Utils.trim(base.endpoint, { suffix = "/" }) .. "/chat",
|
||||
|
@ -25,12 +25,12 @@
|
||||
---@field xcode boolean
|
||||
---@field xcode_chat boolean
|
||||
|
||||
local curl = require("plenary.curl")
|
||||
local curl = require "plenary.curl"
|
||||
|
||||
local Config = require("avante.config")
|
||||
local Path = require("plenary.path")
|
||||
local Utils = require("avante.utils")
|
||||
local P = require("avante.providers")
|
||||
local Config = require "avante.config"
|
||||
local Path = require "plenary.path"
|
||||
local Utils = require "avante.utils"
|
||||
local P = require "avante.providers"
|
||||
local O = require("avante.providers").openai
|
||||
|
||||
local H = {}
|
||||
@ -41,29 +41,25 @@ local H = {}
|
||||
---
|
||||
---@return string
|
||||
H.get_oauth_token = function()
|
||||
local xdg_config = vim.fn.expand("$XDG_CONFIG_HOME")
|
||||
local xdg_config = vim.fn.expand "$XDG_CONFIG_HOME"
|
||||
local os_name = Utils.get_os_name()
|
||||
---@type string
|
||||
local config_dir
|
||||
|
||||
if vim.tbl_contains({ "linux", "darwin" }, os_name) then
|
||||
config_dir = (xdg_config and vim.fn.isdirectory(xdg_config) > 0) and xdg_config or vim.fn.expand("~/.config")
|
||||
config_dir = (xdg_config and vim.fn.isdirectory(xdg_config) > 0) and xdg_config or vim.fn.expand "~/.config"
|
||||
else
|
||||
config_dir = vim.fn.expand("~/AppData/Local")
|
||||
config_dir = vim.fn.expand "~/AppData/Local"
|
||||
end
|
||||
|
||||
--- hosts.json (copilot.lua), apps.json (copilot.vim)
|
||||
---@type Path[]
|
||||
local paths = vim.iter({ "hosts.json", "apps.json" }):fold({}, function(acc, path)
|
||||
local yason = Path:new(config_dir):joinpath("github-copilot", path)
|
||||
if yason:exists() then
|
||||
table.insert(acc, yason)
|
||||
end
|
||||
if yason:exists() then table.insert(acc, yason) end
|
||||
return acc
|
||||
end)
|
||||
if #paths == 0 then
|
||||
error("You must setup copilot with either copilot.lua or copilot.vim", 2)
|
||||
end
|
||||
if #paths == 0 then error("You must setup copilot with either copilot.lua or copilot.vim", 2) end
|
||||
|
||||
local yason = paths[1]
|
||||
return vim
|
||||
@ -71,9 +67,7 @@ H.get_oauth_token = function()
|
||||
---@type table<string, OAuthToken>
|
||||
vim.json.decode(yason:read())
|
||||
)
|
||||
:filter(function(k, _)
|
||||
return k:match("github.com")
|
||||
end)
|
||||
:filter(function(k, _) return k:match "github.com" end)
|
||||
---@param acc {oauth_token: string}
|
||||
:fold({}, function(acc, _, v)
|
||||
acc.oauth_token = v.oauth_token
|
||||
@ -83,17 +77,13 @@ H.get_oauth_token = function()
|
||||
end
|
||||
|
||||
H.chat_auth_url = "https://api.github.com/copilot_internal/v2/token"
|
||||
H.chat_completion_url = function(base_url)
|
||||
return Utils.trim(base_url, { prefix = "/" }) .. "/chat/completions"
|
||||
end
|
||||
H.chat_completion_url = function(base_url) return Utils.trim(base_url, { prefix = "/" }) .. "/chat/completions" end
|
||||
|
||||
---@class AvanteProviderFunctor
|
||||
local M = {}
|
||||
|
||||
H.refresh_token = function()
|
||||
if not M.state then
|
||||
error("internal initialization error")
|
||||
end
|
||||
if not M.state then error "internal initialization error" end
|
||||
|
||||
if
|
||||
not M.state.github_token
|
||||
@ -107,14 +97,10 @@ H.refresh_token = function()
|
||||
timeout = Config.copilot.timeout,
|
||||
proxy = Config.copilot.proxy,
|
||||
insecure = Config.copilot.allow_insecure,
|
||||
on_error = function(err)
|
||||
error("Failed to get response: " .. vim.inspect(err))
|
||||
end,
|
||||
on_error = function(err) error("Failed to get response: " .. vim.inspect(err)) end,
|
||||
callback = function(output)
|
||||
M.state.github_token = vim.json.decode(output.body)
|
||||
if not vim.g.avante_login then
|
||||
vim.g.avante_login = true
|
||||
end
|
||||
if not vim.g.avante_login then vim.g.avante_login = true end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
@ -1,6 +1,6 @@
|
||||
local Utils = require("avante.utils")
|
||||
local P = require("avante.providers")
|
||||
local Clipboard = require("avante.clipboard")
|
||||
local Utils = require "avante.utils"
|
||||
local P = require "avante.providers"
|
||||
local Clipboard = require "avante.clipboard"
|
||||
|
||||
---@class AvanteProviderFunctor
|
||||
local M = {}
|
||||
@ -47,9 +47,7 @@ end
|
||||
|
||||
M.parse_response = function(data_stream, _, opts)
|
||||
local ok, json = pcall(vim.json.decode, data_stream)
|
||||
if not ok then
|
||||
opts.on_complete(json)
|
||||
end
|
||||
if not ok then opts.on_complete(json) end
|
||||
if json.candidates then
|
||||
if #json.candidates > 0 then
|
||||
opts.on_chunk(json.candidates[1].content.parts[1].text)
|
||||
|
@ -1,8 +1,8 @@
|
||||
local api = vim.api
|
||||
|
||||
local Config = require("avante.config")
|
||||
local Utils = require("avante.utils")
|
||||
local Dressing = require("avante.ui.dressing")
|
||||
local Config = require "avante.config"
|
||||
local Utils = require "avante.utils"
|
||||
local Dressing = require "avante.ui.dressing"
|
||||
|
||||
---@class AvanteHandlerOptions: table<[string], string>
|
||||
---@field on_chunk AvanteChunkParser
|
||||
@ -98,15 +98,11 @@ E.cache = {}
|
||||
---@return string | nil
|
||||
E.parse_envvar = function(Opts)
|
||||
local api_key_name = Opts.api_key_name
|
||||
if api_key_name == nil then
|
||||
error("Requires api_key_name")
|
||||
end
|
||||
if api_key_name == nil then error "Requires api_key_name" end
|
||||
|
||||
if E.cache[api_key_name] ~= nil then
|
||||
return E.cache[api_key_name]
|
||||
end
|
||||
if E.cache[api_key_name] ~= nil then return E.cache[api_key_name] end
|
||||
|
||||
local cmd = api_key_name:match("^cmd:(.*)")
|
||||
local cmd = api_key_name:match "^cmd:(.*)"
|
||||
|
||||
local key = nil
|
||||
|
||||
@ -177,9 +173,7 @@ E.setup = function(opts)
|
||||
opts.provider.setup()
|
||||
|
||||
-- check if var is a all caps string
|
||||
if var == M.AVANTE_INTERNAL_KEY or var:match("^cmd:(.*)") then
|
||||
return
|
||||
end
|
||||
if var == M.AVANTE_INTERNAL_KEY or var:match "^cmd:(.*)" then return end
|
||||
|
||||
local refresh = opts.refresh or false
|
||||
|
||||
@ -214,10 +208,10 @@ E.setup = function(opts)
|
||||
"noice",
|
||||
}
|
||||
if not vim.tbl_contains(exclude_filetypes, vim.bo.filetype) and not opts.provider.has() then
|
||||
Dressing.initialize_input_buffer({
|
||||
Dressing.initialize_input_buffer {
|
||||
opts = { prompt = "Enter " .. var .. ": " },
|
||||
on_confirm = on_confirm,
|
||||
})
|
||||
}
|
||||
end
|
||||
end, 200)
|
||||
end
|
||||
@ -260,37 +254,23 @@ M = setmetatable(M, {
|
||||
t[k] = Opts
|
||||
else
|
||||
local ok, module = pcall(require, "avante.providers." .. k)
|
||||
if not ok then
|
||||
error("Failed to load provider: " .. k)
|
||||
end
|
||||
if not ok then error("Failed to load provider: " .. k) end
|
||||
Opts._shellenv = module.api_key_name ~= M.AVANTE_INTERNAL_KEY and module.api_key_name or nil
|
||||
t[k] = vim.tbl_deep_extend("keep", Opts, module)
|
||||
end
|
||||
|
||||
t[k].parse_api_key = function()
|
||||
return E.parse_envvar(t[k])
|
||||
end
|
||||
t[k].parse_api_key = function() return E.parse_envvar(t[k]) end
|
||||
|
||||
-- default to gpt-4o as tokenizer
|
||||
if t[k].tokenizer_id == nil then
|
||||
t[k].tokenizer_id = "gpt-4o"
|
||||
end
|
||||
if t[k].tokenizer_id == nil then t[k].tokenizer_id = "gpt-4o" end
|
||||
|
||||
if t[k].use_xml_format == nil then
|
||||
t[k].use_xml_format = false
|
||||
end
|
||||
if t[k].use_xml_format == nil then t[k].use_xml_format = false end
|
||||
|
||||
if t[k].has == nil then
|
||||
t[k].has = function()
|
||||
return E.parse_envvar(t[k]) ~= nil
|
||||
end
|
||||
end
|
||||
if t[k].has == nil then t[k].has = function() return E.parse_envvar(t[k]) ~= nil end end
|
||||
|
||||
if t[k].setup == nil then
|
||||
t[k].setup = function()
|
||||
if not E.is_local(k) then
|
||||
t[k].parse_api_key()
|
||||
end
|
||||
if not E.is_local(k) then t[k].parse_api_key() end
|
||||
require("avante.tokenizers").setup(t[k].tokenizer_id)
|
||||
end
|
||||
end
|
||||
@ -304,16 +284,16 @@ M.setup = function()
|
||||
|
||||
---@type AvanteProviderFunctor
|
||||
local provider = M[Config.provider]
|
||||
E.setup({ provider = provider })
|
||||
E.setup { provider = provider }
|
||||
end
|
||||
|
||||
---@param provider Provider
|
||||
function M.refresh(provider)
|
||||
require("avante.config").override({ provider = provider })
|
||||
require("avante.config").override { provider = provider }
|
||||
|
||||
---@type AvanteProviderFunctor
|
||||
local p = M[Config.provider]
|
||||
E.setup({ provider = p, refresh = true })
|
||||
E.setup { provider = p, refresh = true }
|
||||
Utils.info("Switch to provider: " .. provider, { once = true, title = "Avante" })
|
||||
end
|
||||
|
||||
@ -334,15 +314,10 @@ M.parse_config = function(opts)
|
||||
end
|
||||
|
||||
return s1,
|
||||
vim
|
||||
.iter(s2)
|
||||
:filter(function(_, v)
|
||||
return type(v) ~= "function"
|
||||
end)
|
||||
:fold({}, function(acc, k, v)
|
||||
acc[k] = v
|
||||
return acc
|
||||
end)
|
||||
vim.iter(s2):filter(function(_, v) return type(v) ~= "function" end):fold({}, function(acc, k, v)
|
||||
acc[k] = v
|
||||
return acc
|
||||
end)
|
||||
end
|
||||
|
||||
---@private
|
||||
|
@ -1,7 +1,7 @@
|
||||
local Utils = require("avante.utils")
|
||||
local Config = require("avante.config")
|
||||
local Clipboard = require("avante.clipboard")
|
||||
local P = require("avante.providers")
|
||||
local Utils = require "avante.utils"
|
||||
local Config = require "avante.config"
|
||||
local Clipboard = require "avante.clipboard"
|
||||
local P = require "avante.providers"
|
||||
|
||||
---@class OpenAIChatResponse
|
||||
---@field id string
|
||||
@ -29,9 +29,7 @@ M.api_key_name = "OPENAI_API_KEY"
|
||||
M.tokenizer_id = "gpt-4o"
|
||||
|
||||
---@param opts AvantePromptOptions
|
||||
M.get_user_message = function(opts)
|
||||
return opts.user_prompt
|
||||
end
|
||||
M.get_user_message = function(opts) return opts.user_prompt end
|
||||
|
||||
M.parse_message = function(opts)
|
||||
---@type string | OpenAIMessage[]
|
||||
@ -58,11 +56,11 @@ M.parse_message = function(opts)
|
||||
end
|
||||
|
||||
M.parse_response = function(data_stream, _, opts)
|
||||
if data_stream:match('"%[DONE%]":') then
|
||||
if data_stream:match '"%[DONE%]":' then
|
||||
opts.on_complete(nil)
|
||||
return
|
||||
end
|
||||
if data_stream:match('"delta":') then
|
||||
if data_stream:match '"delta":' then
|
||||
---@type OpenAIChatResponse
|
||||
local json = vim.json.decode(data_stream)
|
||||
if json.choices and json.choices[1] then
|
||||
@ -70,9 +68,7 @@ M.parse_response = function(data_stream, _, opts)
|
||||
if choice.finish_reason == "stop" then
|
||||
opts.on_complete(nil)
|
||||
elseif choice.delta.content then
|
||||
if choice.delta.content ~= vim.NIL then
|
||||
opts.on_chunk(choice.delta.content)
|
||||
end
|
||||
if choice.delta.content ~= vim.NIL then opts.on_chunk(choice.delta.content) end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -84,9 +80,7 @@ M.parse_curl_args = function(provider, code_opts)
|
||||
local headers = {
|
||||
["Content-Type"] = "application/json",
|
||||
}
|
||||
if not P.env.is_local("openai") then
|
||||
headers["Authorization"] = "Bearer " .. provider.parse_api_key()
|
||||
end
|
||||
if not P.env.is_local "openai" then headers["Authorization"] = "Bearer " .. provider.parse_api_key() end
|
||||
|
||||
return {
|
||||
url = Utils.trim(base.endpoint, { suffix = "/" }) .. "/chat/completions",
|
||||
|
@ -1,13 +1,13 @@
|
||||
local Utils = require("avante.utils")
|
||||
local Config = require("avante.config")
|
||||
local Llm = require("avante.llm")
|
||||
local Highlights = require("avante.highlights")
|
||||
local Utils = require "avante.utils"
|
||||
local Config = require "avante.config"
|
||||
local Llm = require "avante.llm"
|
||||
local Highlights = require "avante.highlights"
|
||||
|
||||
local api = vim.api
|
||||
local fn = vim.fn
|
||||
|
||||
local NAMESPACE = api.nvim_create_namespace("avante_selection")
|
||||
local SELECTED_CODE_NAMESPACE = api.nvim_create_namespace("avante_selected_code")
|
||||
local NAMESPACE = api.nvim_create_namespace "avante_selection"
|
||||
local SELECTED_CODE_NAMESPACE = api.nvim_create_namespace "avante_selected_code"
|
||||
local PRIORITY = vim.highlight.priorities.user
|
||||
|
||||
local EDITING_INPUT_START_SPINNER_PATTERN = "AvanteEditingInputStartSpinner"
|
||||
@ -43,19 +43,15 @@ function Selection:new(id)
|
||||
end
|
||||
|
||||
function Selection:get_virt_text_line()
|
||||
local current_pos = fn.getpos(".")
|
||||
local current_pos = fn.getpos "."
|
||||
|
||||
-- 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)
|
||||
if current_line < 0 then
|
||||
current_line = 0
|
||||
end
|
||||
if current_line >= total_lines then
|
||||
current_line = total_lines - 1
|
||||
end
|
||||
if current_line < 0 then current_line = 0 end
|
||||
if current_line >= total_lines then current_line = total_lines - 1 end
|
||||
|
||||
-- Take the first line of the selection to ensure virt_text is always in the top right corner
|
||||
return current_line
|
||||
@ -85,9 +81,7 @@ end
|
||||
function Selection:close_editing_input()
|
||||
self:close_editing_input_shortcuts_hints()
|
||||
Llm.cancel_inflight_request()
|
||||
if api.nvim_get_mode().mode == "i" then
|
||||
vim.cmd([[stopinsert]])
|
||||
end
|
||||
if api.nvim_get_mode().mode == "i" then vim.cmd [[stopinsert]] end
|
||||
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
|
||||
@ -126,9 +120,7 @@ end
|
||||
function Selection:show_editing_input_shortcuts_hints()
|
||||
self:close_editing_input_shortcuts_hints()
|
||||
|
||||
if not self.editing_input_winid or not api.nvim_win_is_valid(self.editing_input_winid) then
|
||||
return
|
||||
end
|
||||
if not self.editing_input_winid or not api.nvim_win_is_valid(self.editing_input_winid) then return end
|
||||
|
||||
local win_width = api.nvim_win_get_width(self.editing_input_winid)
|
||||
local buf_height = api.nvim_buf_line_count(self.editing_input_bufnr)
|
||||
@ -236,23 +228,13 @@ function Selection:show_editing_input_shortcuts_hints()
|
||||
pattern = EDITING_INPUT_START_SPINNER_PATTERN,
|
||||
callback = function()
|
||||
timer = vim.uv.new_timer()
|
||||
if timer then
|
||||
timer:start(
|
||||
0,
|
||||
100,
|
||||
vim.schedule_wrap(function()
|
||||
update_spinner()
|
||||
end)
|
||||
)
|
||||
end
|
||||
if timer then timer:start(0, 100, vim.schedule_wrap(function() update_spinner() end)) end
|
||||
end,
|
||||
})
|
||||
|
||||
api.nvim_create_autocmd("User", {
|
||||
pattern = EDITING_INPUT_STOP_SPINNER_PATTERN,
|
||||
callback = function()
|
||||
stop_spinner()
|
||||
end,
|
||||
callback = function() stop_spinner() end,
|
||||
})
|
||||
|
||||
local width = fn.strdisplaywidth(hint_text)
|
||||
@ -340,9 +322,7 @@ function Selection:create_editing_input()
|
||||
api.nvim_create_autocmd({ "TextChanged", "TextChangedI" }, {
|
||||
group = self.augroup,
|
||||
buffer = bufnr,
|
||||
callback = function()
|
||||
self:show_editing_input_shortcuts_hints()
|
||||
end,
|
||||
callback = function() self:show_editing_input_shortcuts_hints() end,
|
||||
})
|
||||
|
||||
api.nvim_create_autocmd("ModeChanged", {
|
||||
@ -350,9 +330,7 @@ function Selection:create_editing_input()
|
||||
pattern = "i:*",
|
||||
callback = function()
|
||||
local cur_buf = api.nvim_get_current_buf()
|
||||
if cur_buf == bufnr then
|
||||
self:show_editing_input_shortcuts_hints()
|
||||
end
|
||||
if cur_buf == bufnr then self:show_editing_input_shortcuts_hints() end
|
||||
end,
|
||||
})
|
||||
|
||||
@ -361,9 +339,7 @@ function Selection:create_editing_input()
|
||||
pattern = "*:i",
|
||||
callback = function()
|
||||
local cur_buf = api.nvim_get_current_buf()
|
||||
if cur_buf == bufnr then
|
||||
self:show_editing_input_shortcuts_hints()
|
||||
end
|
||||
if cur_buf == bufnr then self:show_editing_input_shortcuts_hints() end
|
||||
end,
|
||||
})
|
||||
|
||||
@ -406,14 +382,12 @@ function Selection:create_editing_input()
|
||||
return
|
||||
end
|
||||
api.nvim_exec_autocmds("User", { pattern = EDITING_INPUT_STOP_SPINNER_PATTERN })
|
||||
vim.defer_fn(function()
|
||||
self:close_editing_input()
|
||||
end, 0)
|
||||
vim.defer_fn(function() self:close_editing_input() end, 0)
|
||||
end
|
||||
|
||||
local filetype = api.nvim_get_option_value("filetype", { buf = code_bufnr })
|
||||
|
||||
Llm.stream({
|
||||
Llm.stream {
|
||||
bufnr = code_bufnr,
|
||||
file_content = code_content,
|
||||
code_lang = filetype,
|
||||
@ -422,7 +396,7 @@ function Selection:create_editing_input()
|
||||
mode = "editing",
|
||||
on_chunk = on_chunk,
|
||||
on_complete = on_complete,
|
||||
})
|
||||
}
|
||||
end
|
||||
|
||||
---@return string
|
||||
@ -431,18 +405,20 @@ function Selection:create_editing_input()
|
||||
return lines[1] or ""
|
||||
end
|
||||
|
||||
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 })
|
||||
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 })
|
||||
|
||||
local quit_id, close_unfocus
|
||||
quit_id = api.nvim_create_autocmd("QuitPre", {
|
||||
@ -474,9 +450,7 @@ function Selection:create_editing_input()
|
||||
api.nvim_create_autocmd("User", {
|
||||
pattern = "AvanteEditSubmitted",
|
||||
callback = function(ev)
|
||||
if ev.data and ev.data.request then
|
||||
submit_input(ev.data.request)
|
||||
end
|
||||
if ev.data and ev.data.request then submit_input(ev.data.request) end
|
||||
end,
|
||||
})
|
||||
end
|
||||
@ -487,9 +461,7 @@ function Selection:setup_autocmds()
|
||||
group = self.augroup,
|
||||
pattern = { "n:v", "n:V", "n:" }, -- Entering Visual mode from Normal mode
|
||||
callback = function(ev)
|
||||
if not Utils.is_sidebar_buffer(ev.buf) then
|
||||
self:show_shortcuts_hints_popup()
|
||||
end
|
||||
if not Utils.is_sidebar_buffer(ev.buf) then self:show_shortcuts_hints_popup() end
|
||||
end,
|
||||
})
|
||||
|
||||
@ -510,18 +482,14 @@ function Selection:setup_autocmds()
|
||||
group = self.augroup,
|
||||
pattern = { "v:n", "v:i", "v:c" }, -- Switching from visual mode back to normal, insert, or other modes
|
||||
callback = function(ev)
|
||||
if not Utils.is_sidebar_buffer(ev.buf) then
|
||||
self:close_shortcuts_hints_popup()
|
||||
end
|
||||
if not Utils.is_sidebar_buffer(ev.buf) then self:close_shortcuts_hints_popup() end
|
||||
end,
|
||||
})
|
||||
|
||||
api.nvim_create_autocmd({ "BufLeave" }, {
|
||||
group = self.augroup,
|
||||
callback = function(ev)
|
||||
if not Utils.is_sidebar_buffer(ev.buf) then
|
||||
self:close_shortcuts_hints_popup()
|
||||
end
|
||||
if not Utils.is_sidebar_buffer(ev.buf) then self:close_shortcuts_hints_popup() end
|
||||
end,
|
||||
})
|
||||
|
||||
@ -529,9 +497,7 @@ function Selection:setup_autocmds()
|
||||
end
|
||||
|
||||
function Selection:delete_autocmds()
|
||||
if self.augroup then
|
||||
api.nvim_del_augroup_by_id(self.augroup)
|
||||
end
|
||||
if self.augroup then api.nvim_del_augroup_by_id(self.augroup) end
|
||||
self.augroup = nil
|
||||
Selection.did_setup = false
|
||||
end
|
||||
|
@ -1,19 +1,19 @@
|
||||
local api = vim.api
|
||||
local fn = vim.fn
|
||||
|
||||
local Split = require("nui.split")
|
||||
local Split = require "nui.split"
|
||||
local event = require("nui.utils.autocmd").event
|
||||
|
||||
local Path = require("avante.path")
|
||||
local Config = require("avante.config")
|
||||
local Diff = require("avante.diff")
|
||||
local Llm = require("avante.llm")
|
||||
local Utils = require("avante.utils")
|
||||
local Highlights = require("avante.highlights")
|
||||
local Path = require "avante.path"
|
||||
local Config = require "avante.config"
|
||||
local Diff = require "avante.diff"
|
||||
local Llm = require "avante.llm"
|
||||
local Utils = require "avante.utils"
|
||||
local Highlights = require "avante.highlights"
|
||||
|
||||
local RESULT_BUF_NAME = "AVANTE_RESULT"
|
||||
local VIEW_BUFFER_UPDATED_PATTERN = "AvanteViewBufferUpdated"
|
||||
local CODEBLOCK_KEYBINDING_NAMESPACE = api.nvim_create_namespace("AVANTE_CODEBLOCK_KEYBINDING")
|
||||
local CODEBLOCK_KEYBINDING_NAMESPACE = api.nvim_create_namespace "AVANTE_CODEBLOCK_KEYBINDING"
|
||||
local PRIORITY = vim.highlight.priorities.user
|
||||
|
||||
---@class avante.Sidebar
|
||||
@ -52,9 +52,7 @@ function Sidebar:new(id)
|
||||
end
|
||||
|
||||
function Sidebar:delete_autocmds()
|
||||
if self.augroup then
|
||||
api.nvim_del_augroup_by_id(self.augroup)
|
||||
end
|
||||
if self.augroup then api.nvim_del_augroup_by_id(self.augroup) end
|
||||
self.augroup = nil
|
||||
end
|
||||
|
||||
@ -84,22 +82,18 @@ function Sidebar:open()
|
||||
self:focus()
|
||||
end
|
||||
|
||||
vim.cmd("wincmd =")
|
||||
vim.cmd "wincmd ="
|
||||
return self
|
||||
end
|
||||
|
||||
function Sidebar:close()
|
||||
self:delete_autocmds()
|
||||
for _, comp in pairs(self) do
|
||||
if comp and type(comp) == "table" and comp.unmount then
|
||||
comp:unmount()
|
||||
end
|
||||
end
|
||||
if self.code and self.code.winid and api.nvim_win_is_valid(self.code.winid) then
|
||||
fn.win_gotoid(self.code.winid)
|
||||
if comp and type(comp) == "table" and comp.unmount then comp:unmount() end
|
||||
end
|
||||
if self.code and self.code.winid and api.nvim_win_is_valid(self.code.winid) then fn.win_gotoid(self.code.winid) end
|
||||
|
||||
vim.cmd("wincmd =")
|
||||
vim.cmd "wincmd ="
|
||||
end
|
||||
|
||||
---@return boolean
|
||||
@ -119,9 +113,7 @@ function Sidebar:is_open()
|
||||
and api.nvim_win_is_valid(self.result.winid)
|
||||
end
|
||||
|
||||
function Sidebar:in_code_win()
|
||||
return self.code.winid == api.nvim_get_current_win()
|
||||
end
|
||||
function Sidebar:in_code_win() return self.code.winid == api.nvim_get_current_win() end
|
||||
|
||||
function Sidebar:toggle()
|
||||
local in_visual_mode = Utils.in_visual_mode() and self:in_code_win()
|
||||
@ -172,13 +164,9 @@ local function realign_line_numbers(code_lines, snippet)
|
||||
end
|
||||
end
|
||||
|
||||
if correct_start then
|
||||
snippet.range[1] = correct_start
|
||||
end
|
||||
if correct_start then snippet.range[1] = correct_start end
|
||||
|
||||
if correct_end then
|
||||
snippet.range[2] = correct_end
|
||||
end
|
||||
if correct_end then snippet.range[2] = correct_end end
|
||||
|
||||
return snippet
|
||||
end
|
||||
@ -310,9 +298,7 @@ local function generate_display_content(replacement)
|
||||
"\n"
|
||||
) .. searching_hint
|
||||
end
|
||||
if replacement.is_replacing then
|
||||
return replacement.content .. "\n```"
|
||||
end
|
||||
if replacement.is_replacing then return replacement.content .. "\n```" end
|
||||
return replacement.content
|
||||
end
|
||||
|
||||
@ -336,12 +322,12 @@ local function extract_code_snippets(code_content, response_content)
|
||||
local explanation = ""
|
||||
|
||||
for idx, line in ipairs(vim.split(response_content, "\n")) do
|
||||
local start_line_str, end_line_str = line:match("^Replace lines: (%d+)-(%d+)")
|
||||
local start_line_str, end_line_str = line:match "^Replace lines: (%d+)-(%d+)"
|
||||
if start_line_str ~= nil and end_line_str ~= nil then
|
||||
start_line = tonumber(start_line_str)
|
||||
end_line = tonumber(end_line_str)
|
||||
end
|
||||
if line:match("^```") then
|
||||
if line:match "^```" then
|
||||
if in_code_block then
|
||||
if start_line ~= nil and end_line ~= nil then
|
||||
local snippet = {
|
||||
@ -360,10 +346,8 @@ local function extract_code_snippets(code_content, response_content)
|
||||
explanation = ""
|
||||
in_code_block = false
|
||||
else
|
||||
lang = line:match("^```(%w+)")
|
||||
if not lang or lang == "" then
|
||||
lang = "text"
|
||||
end
|
||||
lang = line:match "^```(%w+)"
|
||||
if not lang or lang == "" then lang = "text" end
|
||||
in_code_block = true
|
||||
start_line_in_response_buf = idx
|
||||
end
|
||||
@ -380,9 +364,7 @@ end
|
||||
---@param snippets AvanteCodeSnippet[]
|
||||
---@return AvanteCodeSnippet[]
|
||||
local function ensure_snippets_no_overlap(original_content, snippets)
|
||||
table.sort(snippets, function(a, b)
|
||||
return a.range[1] < b.range[1]
|
||||
end)
|
||||
table.sort(snippets, function(a, b) return a.range[1] < b.range[1] end)
|
||||
|
||||
local original_lines = vim.split(original_content, "\n")
|
||||
|
||||
@ -422,9 +404,7 @@ end
|
||||
|
||||
local function insert_conflict_contents(bufnr, snippets)
|
||||
-- sort snippets by start_line
|
||||
table.sort(snippets, function(a, b)
|
||||
return a.range[1] < b.range[1]
|
||||
end)
|
||||
table.sort(snippets, function(a, b) return a.range[1] < b.range[1] end)
|
||||
|
||||
local content = table.concat(Utils.get_buf_lines(0, -1, bufnr), "\n")
|
||||
|
||||
@ -453,9 +433,7 @@ local function insert_conflict_contents(bufnr, snippets)
|
||||
local indentation = Utils.get_indentation(line)
|
||||
need_prepend_indentation = indentation ~= original_start_line_indentation
|
||||
end
|
||||
if need_prepend_indentation then
|
||||
line = original_start_line_indentation .. line
|
||||
end
|
||||
if need_prepend_indentation then line = original_start_line_indentation .. line end
|
||||
table.insert(result, line)
|
||||
end
|
||||
|
||||
@ -472,9 +450,7 @@ local function is_cursor_in_codeblock(codeblocks)
|
||||
cursor_line = cursor_line - 1 -- 转换为 0-indexed 行号
|
||||
|
||||
for _, block in ipairs(codeblocks) do
|
||||
if cursor_line >= block.start_line and cursor_line <= block.end_line then
|
||||
return block
|
||||
end
|
||||
if cursor_line >= block.start_line and cursor_line <= block.end_line then return block end
|
||||
end
|
||||
|
||||
return nil
|
||||
@ -495,9 +471,9 @@ local function parse_codeblocks(buf)
|
||||
|
||||
local lines = Utils.get_buf_lines(0, -1, buf)
|
||||
for i, line in ipairs(lines) do
|
||||
if line:match("^```") then
|
||||
if line:match "^```" then
|
||||
-- parse language
|
||||
local lang_ = line:match("^```(%w+)")
|
||||
local lang_ = line:match "^```(%w+)"
|
||||
if in_codeblock and not lang_ then
|
||||
table.insert(codeblocks, { start_line = start_line, end_line = i - 1, lang = lang })
|
||||
in_codeblock = false
|
||||
@ -545,8 +521,8 @@ function Sidebar:apply(current_cursor)
|
||||
Diff.process(self.code.bufnr)
|
||||
api.nvim_win_set_cursor(self.code.winid, { 1, 0 })
|
||||
vim.defer_fn(function()
|
||||
Diff.find_next("ours")
|
||||
vim.cmd("normal! zz")
|
||||
Diff.find_next "ours"
|
||||
vim.cmd "normal! zz"
|
||||
end, 1000)
|
||||
end, 10)
|
||||
end
|
||||
@ -578,13 +554,9 @@ local base_win_options = {
|
||||
}
|
||||
|
||||
function Sidebar:render_header(winid, bufnr, header_text, hl, reverse_hl)
|
||||
if not bufnr or not api.nvim_buf_is_valid(bufnr) then
|
||||
return
|
||||
end
|
||||
if not bufnr or not api.nvim_buf_is_valid(bufnr) then return end
|
||||
|
||||
if not Config.windows.sidebar_header.rounded then
|
||||
header_text = " " .. header_text .. " "
|
||||
end
|
||||
if not Config.windows.sidebar_header.rounded then header_text = " " .. header_text .. " " end
|
||||
|
||||
local winbar_text = "%#Normal#"
|
||||
|
||||
@ -600,28 +572,20 @@ function Sidebar:render_header(winid, bufnr, header_text, hl, reverse_hl)
|
||||
winbar_text = winbar_text .. "%#" .. hl .. "#"
|
||||
end
|
||||
winbar_text = winbar_text .. header_text
|
||||
if Config.windows.sidebar_header.rounded then
|
||||
winbar_text = winbar_text .. "%#" .. reverse_hl .. "#"
|
||||
end
|
||||
if Config.windows.sidebar_header.rounded then winbar_text = winbar_text .. "%#" .. reverse_hl .. "#" end
|
||||
winbar_text = winbar_text .. "%#Normal#"
|
||||
if Config.windows.sidebar_header.align == "center" then
|
||||
winbar_text = winbar_text .. "%="
|
||||
end
|
||||
if Config.windows.sidebar_header.align == "center" then winbar_text = winbar_text .. "%=" end
|
||||
api.nvim_set_option_value("winbar", winbar_text, { win = winid })
|
||||
end
|
||||
|
||||
function Sidebar:render_result()
|
||||
if not self.result or not self.result.bufnr or not api.nvim_buf_is_valid(self.result.bufnr) then
|
||||
return
|
||||
end
|
||||
if not self.result or not self.result.bufnr or not api.nvim_buf_is_valid(self.result.bufnr) then return end
|
||||
local header_text = " Avante"
|
||||
self:render_header(self.result.winid, self.result.bufnr, header_text, Highlights.TITLE, Highlights.REVERSED_TITLE)
|
||||
end
|
||||
|
||||
function Sidebar:render_input()
|
||||
if not self.input or not self.input.bufnr or not api.nvim_buf_is_valid(self.input.bufnr) then
|
||||
return
|
||||
end
|
||||
if not self.input or not self.input.bufnr or not api.nvim_buf_is_valid(self.input.bufnr) then return end
|
||||
|
||||
local filetype = api.nvim_get_option_value("filetype", { buf = self.code.bufnr })
|
||||
|
||||
@ -714,17 +678,21 @@ function Sidebar:on_mount()
|
||||
end
|
||||
|
||||
local function bind_apply_key()
|
||||
vim.keymap.set("n", "a", function()
|
||||
self:apply(true)
|
||||
end, { buffer = self.result.bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "A", function()
|
||||
self:apply(false)
|
||||
end, { buffer = self.result.bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set(
|
||||
"n",
|
||||
"a",
|
||||
function() self:apply(true) end,
|
||||
{ buffer = self.result.bufnr, noremap = true, silent = true }
|
||||
)
|
||||
vim.keymap.set(
|
||||
"n",
|
||||
"A",
|
||||
function() self:apply(false) end,
|
||||
{ buffer = self.result.bufnr, noremap = true, silent = true }
|
||||
)
|
||||
end
|
||||
|
||||
local function unbind_apply_key()
|
||||
pcall(vim.keymap.del, "n", "A", { buffer = self.result.bufnr })
|
||||
end
|
||||
local function unbind_apply_key() pcall(vim.keymap.del, "n", "A", { buffer = self.result.bufnr }) end
|
||||
|
||||
---@type AvanteCodeblock[]
|
||||
local codeblocks = {}
|
||||
@ -742,9 +710,7 @@ function Sidebar:on_mount()
|
||||
break
|
||||
end
|
||||
end
|
||||
if not target_block and #codeblocks > 0 then
|
||||
target_block = codeblocks[1]
|
||||
end
|
||||
if not target_block and #codeblocks > 0 then target_block = codeblocks[1] end
|
||||
elseif direction == "prev" then
|
||||
for i = #codeblocks, 1, -1 do
|
||||
if codeblocks[i].end_line < cursor_line then
|
||||
@ -752,24 +718,28 @@ function Sidebar:on_mount()
|
||||
break
|
||||
end
|
||||
end
|
||||
if not target_block and #codeblocks > 0 then
|
||||
target_block = codeblocks[#codeblocks]
|
||||
end
|
||||
if not target_block and #codeblocks > 0 then target_block = codeblocks[#codeblocks] end
|
||||
end
|
||||
|
||||
if target_block then
|
||||
api.nvim_win_set_cursor(self.result.winid, { target_block.start_line + 1, 0 })
|
||||
vim.cmd("normal! zz")
|
||||
vim.cmd "normal! zz"
|
||||
end
|
||||
end
|
||||
|
||||
local function bind_jump_keys()
|
||||
vim.keymap.set("n", Config.mappings.jump.next, function()
|
||||
jump_to_codeblock("next")
|
||||
end, { buffer = self.result.bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", Config.mappings.jump.prev, function()
|
||||
jump_to_codeblock("prev")
|
||||
end, { buffer = self.result.bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set(
|
||||
"n",
|
||||
Config.mappings.jump.next,
|
||||
function() jump_to_codeblock "next" end,
|
||||
{ buffer = self.result.bufnr, noremap = true, silent = true }
|
||||
)
|
||||
vim.keymap.set(
|
||||
"n",
|
||||
Config.mappings.jump.prev,
|
||||
function() jump_to_codeblock "prev" end,
|
||||
{ buffer = self.result.bufnr, noremap = true, silent = true }
|
||||
)
|
||||
end
|
||||
|
||||
local function unbind_jump_keys()
|
||||
@ -805,9 +775,7 @@ function Sidebar:on_mount()
|
||||
api.nvim_create_autocmd("User", {
|
||||
pattern = VIEW_BUFFER_UPDATED_PATTERN,
|
||||
callback = function()
|
||||
if not self.result or not self.result.bufnr or not api.nvim_buf_is_valid(self.result.bufnr) then
|
||||
return
|
||||
end
|
||||
if not self.result or not self.result.bufnr or not api.nvim_buf_is_valid(self.result.bufnr) then return end
|
||||
codeblocks = parse_codeblocks(self.result.bufnr)
|
||||
bind_jump_keys()
|
||||
end,
|
||||
@ -815,9 +783,7 @@ function Sidebar:on_mount()
|
||||
|
||||
api.nvim_create_autocmd("BufLeave", {
|
||||
buffer = self.result.bufnr,
|
||||
callback = function()
|
||||
unbind_jump_keys()
|
||||
end,
|
||||
callback = function() unbind_jump_keys() end,
|
||||
})
|
||||
|
||||
self:render_result()
|
||||
@ -857,9 +823,7 @@ function Sidebar:on_mount()
|
||||
group = self.augroup,
|
||||
callback = function(args)
|
||||
local closed_winid = tonumber(args.match)
|
||||
if not self:is_focused_on(closed_winid) then
|
||||
return
|
||||
end
|
||||
if not self:is_focused_on(closed_winid) then return end
|
||||
self:close()
|
||||
end,
|
||||
})
|
||||
@ -880,15 +844,9 @@ function Sidebar:refresh_winids()
|
||||
end
|
||||
|
||||
local winids = {}
|
||||
if self.winids.result then
|
||||
table.insert(winids, self.winids.result)
|
||||
end
|
||||
if self.winids.selected_code then
|
||||
table.insert(winids, self.winids.selected_code)
|
||||
end
|
||||
if self.winids.input then
|
||||
table.insert(winids, self.winids.input)
|
||||
end
|
||||
if self.winids.result then table.insert(winids, self.winids.result) end
|
||||
if self.winids.selected_code then table.insert(winids, self.winids.selected_code) end
|
||||
if self.winids.input then table.insert(winids, self.winids.input) end
|
||||
|
||||
local function switch_windows()
|
||||
local current_winid = api.nvim_get_current_win()
|
||||
@ -899,9 +857,7 @@ function Sidebar:refresh_winids()
|
||||
current_idx = current_idx + 1
|
||||
end
|
||||
local winid = winids[current_idx]
|
||||
if winid and api.nvim_win_is_valid(winid) then
|
||||
pcall(api.nvim_set_current_win, winid)
|
||||
end
|
||||
if winid and api.nvim_win_is_valid(winid) then pcall(api.nvim_set_current_win, winid) end
|
||||
end
|
||||
|
||||
local function reverse_switch_windows()
|
||||
@ -913,19 +869,23 @@ function Sidebar:refresh_winids()
|
||||
current_idx = current_idx - 1
|
||||
end
|
||||
local winid = winids[current_idx]
|
||||
if winid and api.nvim_win_is_valid(winid) then
|
||||
api.nvim_set_current_win(winid)
|
||||
end
|
||||
if winid and api.nvim_win_is_valid(winid) then api.nvim_set_current_win(winid) end
|
||||
end
|
||||
|
||||
for _, winid in ipairs(winids) do
|
||||
local buf = api.nvim_win_get_buf(winid)
|
||||
vim.keymap.set({ "n", "i" }, "<Tab>", function()
|
||||
switch_windows()
|
||||
end, { buffer = buf, noremap = true, silent = true })
|
||||
vim.keymap.set({ "n", "i" }, "<S-Tab>", function()
|
||||
reverse_switch_windows()
|
||||
end, { buffer = buf, noremap = true, silent = true })
|
||||
vim.keymap.set(
|
||||
{ "n", "i" },
|
||||
"<Tab>",
|
||||
function() switch_windows() end,
|
||||
{ buffer = buf, noremap = true, silent = true }
|
||||
)
|
||||
vim.keymap.set(
|
||||
{ "n", "i" },
|
||||
"<S-Tab>",
|
||||
function() reverse_switch_windows() end,
|
||||
{ buffer = buf, noremap = true, silent = true }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@ -938,9 +898,7 @@ function Sidebar:resize()
|
||||
self:render_result()
|
||||
self:render_input()
|
||||
self:render_selected_code()
|
||||
vim.defer_fn(function()
|
||||
vim.cmd("AvanteRefresh")
|
||||
end, 200)
|
||||
vim.defer_fn(function() vim.cmd "AvanteRefresh" end, 200)
|
||||
end
|
||||
|
||||
--- Initialize the sidebar instance.
|
||||
@ -959,9 +917,7 @@ end
|
||||
|
||||
function Sidebar:is_focused_on(winid)
|
||||
for _, stored_winid in pairs(self.winids) do
|
||||
if stored_winid == winid then
|
||||
return true
|
||||
end
|
||||
if stored_winid == winid then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
@ -969,9 +925,7 @@ end
|
||||
---@param content string concatenated content of the buffer
|
||||
---@param opts? {focus?: boolean, stream?: boolean, scroll?: boolean, callback?: fun(): nil} whether to focus the result view
|
||||
function Sidebar:update_content(content, opts)
|
||||
if not self.result or not self.result.bufnr then
|
||||
return
|
||||
end
|
||||
if not self.result or not self.result.bufnr then return end
|
||||
opts = vim.tbl_deep_extend("force", { focus = true, scroll = true, stream = false, callback = nil }, opts or {})
|
||||
if opts.stream then
|
||||
local scroll_to_bottom = function()
|
||||
@ -982,38 +936,27 @@ function Sidebar:update_content(content, opts)
|
||||
if #current_lines > 0 then
|
||||
local last_line_content = current_lines[1]
|
||||
local last_col = #last_line_content
|
||||
xpcall(function()
|
||||
api.nvim_win_set_cursor(self.result.winid, { last_line, last_col })
|
||||
end, function(err)
|
||||
return err
|
||||
end)
|
||||
xpcall(
|
||||
function() api.nvim_win_set_cursor(self.result.winid, { last_line, last_col }) end,
|
||||
function(err) return err end
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
vim.schedule(function()
|
||||
if not self.result or not self.result.bufnr or not api.nvim_buf_is_valid(self.result.bufnr) then
|
||||
return
|
||||
end
|
||||
if not self.result or not self.result.bufnr or not api.nvim_buf_is_valid(self.result.bufnr) then return end
|
||||
scroll_to_bottom()
|
||||
local lines = vim.split(content, "\n")
|
||||
Utils.unlock_buf(self.result.bufnr)
|
||||
api.nvim_buf_call(self.result.bufnr, function()
|
||||
api.nvim_put(lines, "c", true, true)
|
||||
end)
|
||||
api.nvim_buf_call(self.result.bufnr, function() api.nvim_put(lines, "c", true, true) end)
|
||||
Utils.lock_buf(self.result.bufnr)
|
||||
api.nvim_set_option_value("filetype", "Avante", { buf = self.result.bufnr })
|
||||
if opts.scroll then
|
||||
scroll_to_bottom()
|
||||
end
|
||||
if opts.callback ~= nil then
|
||||
opts.callback()
|
||||
end
|
||||
if opts.scroll then scroll_to_bottom() end
|
||||
if opts.callback ~= nil then opts.callback() end
|
||||
end)
|
||||
else
|
||||
vim.defer_fn(function()
|
||||
if not self.result or not self.result.bufnr or not api.nvim_buf_is_valid(self.result.bufnr) then
|
||||
return
|
||||
end
|
||||
if not self.result or not self.result.bufnr or not api.nvim_buf_is_valid(self.result.bufnr) then return end
|
||||
local lines = vim.split(content, "\n")
|
||||
Utils.unlock_buf(self.result.bufnr)
|
||||
api.nvim_buf_set_lines(self.result.bufnr, 0, -1, false, lines)
|
||||
@ -1023,27 +966,19 @@ function Sidebar:update_content(content, opts)
|
||||
xpcall(function()
|
||||
--- set cursor to bottom of result view
|
||||
api.nvim_set_current_win(self.result.winid)
|
||||
end, function(err)
|
||||
return err
|
||||
end)
|
||||
end, function(err) return err end)
|
||||
end
|
||||
|
||||
if opts.scroll then
|
||||
Utils.buf_scroll_to_end(self.result.bufnr)
|
||||
end
|
||||
if opts.scroll then Utils.buf_scroll_to_end(self.result.bufnr) end
|
||||
|
||||
if opts.callback ~= nil then
|
||||
opts.callback()
|
||||
end
|
||||
if opts.callback ~= nil then opts.callback() end
|
||||
end, 0)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
-- Function to get current timestamp
|
||||
local function get_timestamp()
|
||||
return os.date("%Y-%m-%d %H:%M:%S")
|
||||
end
|
||||
local function get_timestamp() return os.date "%Y-%m-%d %H:%M:%S" end
|
||||
|
||||
local function get_chat_record_prefix(timestamp, provider, model, request)
|
||||
provider = provider or "unknown"
|
||||
@ -1061,9 +996,7 @@ local function get_chat_record_prefix(timestamp, provider, model, request)
|
||||
end
|
||||
|
||||
function Sidebar:get_layout()
|
||||
if Config.windows.position == "left" or Config.windows.position == "right" then
|
||||
return "vertical"
|
||||
end
|
||||
if Config.windows.position == "left" or Config.windows.position == "right" then return "vertical" end
|
||||
return "horizontal"
|
||||
end
|
||||
|
||||
@ -1074,9 +1007,7 @@ function Sidebar:update_content_with_history(history)
|
||||
get_chat_record_prefix(entry.timestamp, entry.provider, entry.model, entry.request or entry.requirement or "")
|
||||
content = content .. prefix
|
||||
content = content .. entry.response .. "\n\n"
|
||||
if idx < #history then
|
||||
content = content .. "---\n\n"
|
||||
end
|
||||
if idx < #history then content = content .. "---\n\n" end
|
||||
end
|
||||
self:update_content(content)
|
||||
end
|
||||
@ -1147,9 +1078,7 @@ function Sidebar:get_commands()
|
||||
help = function(args, cb)
|
||||
local help_text = get_help_text(items)
|
||||
self:update_content(help_text, { focus = false, scroll = false })
|
||||
if cb then
|
||||
cb(args)
|
||||
end
|
||||
if cb then cb(args) end
|
||||
end,
|
||||
clear = function(args, cb)
|
||||
local chat_history = {}
|
||||
@ -1157,15 +1086,11 @@ function Sidebar:get_commands()
|
||||
self:update_content("Chat history cleared", { focus = false, scroll = false })
|
||||
vim.defer_fn(function()
|
||||
self:close()
|
||||
if cb then
|
||||
cb(args)
|
||||
end
|
||||
if cb then cb(args) end
|
||||
end, 1000)
|
||||
end,
|
||||
lines = function(args, cb)
|
||||
if cb then
|
||||
cb(args)
|
||||
end
|
||||
if cb then cb(args) end
|
||||
end,
|
||||
}
|
||||
|
||||
@ -1194,7 +1119,7 @@ function Sidebar:create_selected_code()
|
||||
local selected_code_size = self:get_selected_code_size()
|
||||
|
||||
if self.code.selection ~= nil then
|
||||
self.selected_code = Split({
|
||||
self.selected_code = Split {
|
||||
enter = false,
|
||||
relative = {
|
||||
type = "win",
|
||||
@ -1206,7 +1131,7 @@ function Sidebar:create_selected_code()
|
||||
size = {
|
||||
height = selected_code_size + 3,
|
||||
},
|
||||
})
|
||||
}
|
||||
self.selected_code:mount()
|
||||
if self:get_layout() == "horizontal" then
|
||||
api.nvim_win_set_height(self.result.winid, api.nvim_win_get_height(self.result.winid) - selected_code_size - 3)
|
||||
@ -1217,13 +1142,9 @@ end
|
||||
local hint_window = nil
|
||||
|
||||
function Sidebar:create_input()
|
||||
if self.input then
|
||||
self.input:unmount()
|
||||
end
|
||||
if self.input then self.input:unmount() end
|
||||
|
||||
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
|
||||
|
||||
local chat_history = Path.history.load(self.code.bufnr)
|
||||
|
||||
@ -1253,23 +1174,18 @@ function Sidebar:create_input()
|
||||
end
|
||||
|
||||
if request:sub(1, 1) == "/" then
|
||||
local command, args = request:match("^/(%S+)%s*(.*)")
|
||||
local command, args = request:match "^/(%S+)%s*(.*)"
|
||||
if command == nil then
|
||||
self:update_content("Invalid command", { focus = false, scroll = false })
|
||||
return
|
||||
end
|
||||
local cmds = self:get_commands()
|
||||
---@type AvanteSlash
|
||||
local cmd = vim
|
||||
.iter(cmds)
|
||||
:filter(function(_)
|
||||
return _.command == command
|
||||
end)
|
||||
:totable()[1]
|
||||
local cmd = vim.iter(cmds):filter(function(_) return _.command == command end):totable()[1]
|
||||
if cmd then
|
||||
if command == "lines" then
|
||||
cmd.callback(args, function(args_)
|
||||
local start_line, end_line, question = args_:match("(%d+)-(%d+)%s+(.*)")
|
||||
local start_line, end_line, question = args_:match "(%d+)-(%d+)%s+(.*)"
|
||||
---@cast start_line integer
|
||||
start_line = tonumber(start_line)
|
||||
---@cast end_line integer
|
||||
@ -1307,9 +1223,7 @@ function Sidebar:create_input()
|
||||
return
|
||||
end
|
||||
self:update_content(chunk, { stream = true, scroll = true })
|
||||
vim.schedule(function()
|
||||
vim.cmd("redraw")
|
||||
end)
|
||||
vim.schedule(function() vim.cmd "redraw" end)
|
||||
end
|
||||
|
||||
---@type AvanteCompleteParser
|
||||
@ -1323,9 +1237,7 @@ function Sidebar:create_input()
|
||||
self:update_content("\n\n**Generation complete!** Please review the code suggestions above.", {
|
||||
stream = true,
|
||||
scroll = true,
|
||||
callback = function()
|
||||
api.nvim_exec_autocmds("User", { pattern = VIEW_BUFFER_UPDATED_PATTERN })
|
||||
end,
|
||||
callback = function() api.nvim_exec_autocmds("User", { pattern = VIEW_BUFFER_UPDATED_PATTERN }) end,
|
||||
})
|
||||
|
||||
vim.defer_fn(function()
|
||||
@ -1345,7 +1257,7 @@ function Sidebar:create_input()
|
||||
Path.history.save(self.code.bufnr, chat_history)
|
||||
end
|
||||
|
||||
Llm.stream({
|
||||
Llm.stream {
|
||||
bufnr = self.code.bufnr,
|
||||
file_content = content_with_line_numbers,
|
||||
code_lang = filetype,
|
||||
@ -1354,26 +1266,20 @@ function Sidebar:create_input()
|
||||
mode = "planning",
|
||||
on_chunk = on_chunk,
|
||||
on_complete = on_complete,
|
||||
})
|
||||
}
|
||||
|
||||
if Config.behaviour.auto_apply_diff_after_generation then
|
||||
self:apply(false)
|
||||
end
|
||||
if Config.behaviour.auto_apply_diff_after_generation then self:apply(false) end
|
||||
end
|
||||
|
||||
local get_position = function()
|
||||
if self:get_layout() == "vertical" then
|
||||
return "bottom"
|
||||
end
|
||||
if self:get_layout() == "vertical" then return "bottom" end
|
||||
return "right"
|
||||
end
|
||||
|
||||
local get_size = function()
|
||||
if self:get_layout() == "vertical" then
|
||||
return {
|
||||
height = 8,
|
||||
}
|
||||
end
|
||||
if self:get_layout() == "vertical" then return {
|
||||
height = 8,
|
||||
} end
|
||||
|
||||
local selected_code_size = self:get_selected_code_size()
|
||||
|
||||
@ -1383,7 +1289,7 @@ function Sidebar:create_input()
|
||||
}
|
||||
end
|
||||
|
||||
self.input = Split({
|
||||
self.input = Split {
|
||||
enter = false,
|
||||
relative = {
|
||||
type = "win",
|
||||
@ -1392,21 +1298,17 @@ function Sidebar:create_input()
|
||||
win_options = vim.tbl_deep_extend("force", base_win_options, { signcolumn = "yes" }),
|
||||
position = get_position(),
|
||||
size = get_size(),
|
||||
})
|
||||
}
|
||||
|
||||
local function on_submit()
|
||||
if not vim.g.avante_login then
|
||||
Utils.warn("Sending message to fast!, API key is not yet set", { title = "Avante" })
|
||||
return
|
||||
end
|
||||
if not self.input or not self.input.bufnr or not api.nvim_buf_is_valid(self.input.bufnr) then
|
||||
return
|
||||
end
|
||||
if not self.input or not self.input.bufnr or not api.nvim_buf_is_valid(self.input.bufnr) then return end
|
||||
local lines = api.nvim_buf_get_lines(self.input.bufnr, 0, -1, false)
|
||||
local request = table.concat(lines, "\n")
|
||||
if request == "" then
|
||||
return
|
||||
end
|
||||
if request == "" then return end
|
||||
api.nvim_buf_set_lines(self.input.bufnr, 0, -1, false, {})
|
||||
handle_submit(request)
|
||||
end
|
||||
@ -1447,12 +1349,12 @@ function Sidebar:create_input()
|
||||
self.registered_cmp = true
|
||||
cmp.register_source("avante_commands", require("cmp_avante.commands").new(self))
|
||||
end
|
||||
cmp.setup.buffer({
|
||||
cmp.setup.buffer {
|
||||
enabled = true,
|
||||
sources = {
|
||||
{ name = "avante_commands" },
|
||||
},
|
||||
})
|
||||
}
|
||||
end
|
||||
end,
|
||||
})
|
||||
@ -1512,9 +1414,7 @@ function Sidebar:create_input()
|
||||
api.nvim_create_autocmd("QuitPre", {
|
||||
group = self.augroup,
|
||||
buffer = self.input.bufnr,
|
||||
callback = function()
|
||||
close_hint()
|
||||
end,
|
||||
callback = function() close_hint() end,
|
||||
})
|
||||
|
||||
-- Show hint in insert mode
|
||||
@ -1523,9 +1423,7 @@ function Sidebar:create_input()
|
||||
pattern = "*:i",
|
||||
callback = function()
|
||||
local cur_buf = api.nvim_get_current_buf()
|
||||
if self.input and cur_buf == self.input.bufnr then
|
||||
show_hint()
|
||||
end
|
||||
if self.input and cur_buf == self.input.bufnr then show_hint() end
|
||||
end,
|
||||
})
|
||||
|
||||
@ -1535,9 +1433,7 @@ function Sidebar:create_input()
|
||||
pattern = "i:*",
|
||||
callback = function()
|
||||
local cur_buf = api.nvim_get_current_buf()
|
||||
if self.input and cur_buf == self.input.bufnr then
|
||||
show_hint()
|
||||
end
|
||||
if self.input and cur_buf == self.input.bufnr then show_hint() end
|
||||
end,
|
||||
})
|
||||
|
||||
@ -1557,9 +1453,7 @@ function Sidebar:create_input()
|
||||
api.nvim_create_autocmd("User", {
|
||||
pattern = "AvanteInputSubmitted",
|
||||
callback = function(ev)
|
||||
if ev.data and ev.data.request then
|
||||
handle_submit(ev.data.request)
|
||||
end
|
||||
if ev.data and ev.data.request then handle_submit(ev.data.request) end
|
||||
end,
|
||||
})
|
||||
end
|
||||
@ -1581,9 +1475,7 @@ end
|
||||
function Sidebar:render()
|
||||
local chat_history = Path.history.load(self.code.bufnr)
|
||||
|
||||
local get_position = function()
|
||||
return Config.windows.position
|
||||
end
|
||||
local get_position = function() return Config.windows.position end
|
||||
|
||||
local get_height = function()
|
||||
local selected_code_size = self:get_selected_code_size()
|
||||
@ -1603,7 +1495,7 @@ function Sidebar:render()
|
||||
return math.max(1, api.nvim_win_get_width(self.code.winid))
|
||||
end
|
||||
|
||||
self.result = Split({
|
||||
self.result = Split {
|
||||
enter = false,
|
||||
relative = "editor",
|
||||
position = get_position(),
|
||||
@ -1619,14 +1511,12 @@ function Sidebar:render()
|
||||
width = get_width(),
|
||||
height = get_height(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
self.result:mount()
|
||||
|
||||
self.result:on(event.BufWinEnter, function()
|
||||
xpcall(function()
|
||||
api.nvim_buf_set_name(self.result.bufnr, RESULT_BUF_NAME)
|
||||
end, function(_) end)
|
||||
xpcall(function() api.nvim_buf_set_name(self.result.bufnr, RESULT_BUF_NAME) end, function(_) end)
|
||||
end)
|
||||
|
||||
self.result:map("n", "q", function()
|
||||
@ -1645,9 +1535,7 @@ function Sidebar:render()
|
||||
|
||||
-- reset states when buffer is closed
|
||||
api.nvim_buf_attach(self.code.bufnr, false, {
|
||||
on_detach = function(_, _)
|
||||
self:reset()
|
||||
end,
|
||||
on_detach = function(_, _) self:reset() end,
|
||||
})
|
||||
|
||||
self:create_selected_code()
|
||||
|
@ -1,11 +1,11 @@
|
||||
local Utils = require("avante.utils")
|
||||
local Llm = require("avante.llm")
|
||||
local Highlights = require("avante.highlights")
|
||||
local Config = require("avante.config")
|
||||
local Utils = require "avante.utils"
|
||||
local Llm = require "avante.llm"
|
||||
local Highlights = require "avante.highlights"
|
||||
local Config = require "avante.config"
|
||||
local api = vim.api
|
||||
local fn = vim.fn
|
||||
|
||||
local SUGGESTION_NS = api.nvim_create_namespace("avante_suggestion")
|
||||
local SUGGESTION_NS = api.nvim_create_namespace "avante_suggestion"
|
||||
|
||||
---@class avante.SuggestionItem
|
||||
---@field content string
|
||||
@ -50,13 +50,9 @@ function Suggestion:destroy()
|
||||
end
|
||||
|
||||
function Suggestion:setup_mappings()
|
||||
if not Config.behaviour.auto_set_keymaps then
|
||||
return
|
||||
end
|
||||
if not Config.behaviour.auto_set_keymaps then return end
|
||||
if Config.mappings.suggestion and Config.mappings.suggestion.accept then
|
||||
vim.keymap.set("i", Config.mappings.suggestion.accept, function()
|
||||
self:accept()
|
||||
end, {
|
||||
vim.keymap.set("i", Config.mappings.suggestion.accept, function() self:accept() end, {
|
||||
desc = "[avante] accept suggestion",
|
||||
noremap = true,
|
||||
silent = true,
|
||||
@ -65,9 +61,7 @@ function Suggestion:setup_mappings()
|
||||
|
||||
if Config.mappings.suggestion and Config.mappings.suggestion.dismiss then
|
||||
vim.keymap.set("i", Config.mappings.suggestion.dismiss, function()
|
||||
if self:is_visible() then
|
||||
self:dismiss()
|
||||
end
|
||||
if self:is_visible() then self:dismiss() end
|
||||
end, {
|
||||
desc = "[avante] dismiss suggestion",
|
||||
noremap = true,
|
||||
@ -76,9 +70,7 @@ function Suggestion:setup_mappings()
|
||||
end
|
||||
|
||||
if Config.mappings.suggestion and Config.mappings.suggestion.next then
|
||||
vim.keymap.set("i", Config.mappings.suggestion.next, function()
|
||||
self:next()
|
||||
end, {
|
||||
vim.keymap.set("i", Config.mappings.suggestion.next, function() self:next() end, {
|
||||
desc = "[avante] next suggestion",
|
||||
noremap = true,
|
||||
silent = true,
|
||||
@ -86,9 +78,7 @@ function Suggestion:setup_mappings()
|
||||
end
|
||||
|
||||
if Config.mappings.suggestion and Config.mappings.suggestion.prev then
|
||||
vim.keymap.set("i", Config.mappings.suggestion.prev, function()
|
||||
self:prev()
|
||||
end, {
|
||||
vim.keymap.set("i", Config.mappings.suggestion.prev, function() self:prev() end, {
|
||||
desc = "[avante] previous suggestion",
|
||||
noremap = true,
|
||||
silent = true,
|
||||
@ -97,7 +87,7 @@ function Suggestion:setup_mappings()
|
||||
end
|
||||
|
||||
function Suggestion:suggest()
|
||||
Utils.debug("suggesting")
|
||||
Utils.debug "suggesting"
|
||||
|
||||
local ctx = self:ctx()
|
||||
local doc = Utils.get_doc()
|
||||
@ -110,15 +100,13 @@ function Suggestion:suggest()
|
||||
|
||||
local full_response = ""
|
||||
|
||||
Llm.stream({
|
||||
Llm.stream {
|
||||
bufnr = bufnr,
|
||||
file_content = code_content,
|
||||
code_lang = filetype,
|
||||
instructions = vim.json.encode(doc),
|
||||
mode = "suggesting",
|
||||
on_chunk = function(chunk)
|
||||
full_response = full_response .. chunk
|
||||
end,
|
||||
on_chunk = function(chunk) full_response = full_response .. chunk end,
|
||||
on_complete = function(err)
|
||||
if err then
|
||||
Utils.error("Error while suggesting: " .. vim.inspect(err), { once = true, title = "Avante" })
|
||||
@ -126,9 +114,7 @@ function Suggestion:suggest()
|
||||
end
|
||||
Utils.debug("full_response: " .. vim.inspect(full_response))
|
||||
local cursor_row, cursor_col = Utils.get_cursor_pos()
|
||||
if cursor_row ~= doc.position.row or cursor_col ~= doc.position.col then
|
||||
return
|
||||
end
|
||||
if cursor_row ~= doc.position.row or cursor_col ~= doc.position.col then return end
|
||||
local ok, suggestions = pcall(vim.json.decode, full_response)
|
||||
if not ok then
|
||||
Utils.error("Error while decoding suggestions: " .. full_response, { once = true, title = "Avante" })
|
||||
@ -140,35 +126,27 @@ function Suggestion:suggest()
|
||||
end
|
||||
suggestions = vim
|
||||
.iter(suggestions)
|
||||
:map(function(s)
|
||||
return { row = s.row, col = s.col, content = Utils.trim_all_line_numbers(s.content) }
|
||||
end)
|
||||
:map(function(s) return { row = s.row, col = s.col, content = Utils.trim_all_line_numbers(s.content) } end)
|
||||
:totable()
|
||||
ctx.suggestions = suggestions
|
||||
ctx.current_suggestion_idx = 1
|
||||
self:show()
|
||||
end,
|
||||
})
|
||||
}
|
||||
end
|
||||
|
||||
function Suggestion:show()
|
||||
self:hide()
|
||||
|
||||
if not fn.mode():match("^[iR]") then
|
||||
return
|
||||
end
|
||||
if not fn.mode():match "^[iR]" then return end
|
||||
|
||||
local ctx = self:ctx()
|
||||
local suggestion = ctx.suggestions[ctx.current_suggestion_idx]
|
||||
if not suggestion then
|
||||
return
|
||||
end
|
||||
if not suggestion then return end
|
||||
|
||||
local cursor_row, cursor_col = Utils.get_cursor_pos()
|
||||
|
||||
if suggestion.row < cursor_row then
|
||||
return
|
||||
end
|
||||
if suggestion.row < cursor_row then return end
|
||||
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
local row = suggestion.row
|
||||
@ -179,9 +157,7 @@ function Suggestion:show()
|
||||
|
||||
local extmark_col = cursor_col
|
||||
|
||||
if cursor_row < row then
|
||||
extmark_col = 0
|
||||
end
|
||||
if cursor_row < row then extmark_col = 0 end
|
||||
|
||||
local current_lines = api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||
|
||||
@ -223,9 +199,7 @@ function Suggestion:is_visible()
|
||||
return not not api.nvim_buf_get_extmark_by_id(0, SUGGESTION_NS, self.extmark_id, { details = false })[1]
|
||||
end
|
||||
|
||||
function Suggestion:hide()
|
||||
api.nvim_buf_del_extmark(0, SUGGESTION_NS, self.extmark_id)
|
||||
end
|
||||
function Suggestion:hide() api.nvim_buf_del_extmark(0, SUGGESTION_NS, self.extmark_id) end
|
||||
|
||||
function Suggestion:ctx()
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
@ -249,27 +223,21 @@ end
|
||||
|
||||
function Suggestion:stop_timer()
|
||||
if self._timer then
|
||||
pcall(function()
|
||||
fn.timer_stop(self._timer)
|
||||
end)
|
||||
pcall(function() fn.timer_stop(self._timer) end)
|
||||
self._timer = nil
|
||||
end
|
||||
end
|
||||
|
||||
function Suggestion:next()
|
||||
local ctx = self:ctx()
|
||||
if #ctx.suggestions == 0 then
|
||||
return
|
||||
end
|
||||
if #ctx.suggestions == 0 then return end
|
||||
ctx.current_suggestion_idx = (ctx.current_suggestion_idx % #ctx.suggestions) + 1
|
||||
self:show()
|
||||
end
|
||||
|
||||
function Suggestion:prev()
|
||||
local ctx = self:ctx()
|
||||
if #ctx.suggestions == 0 then
|
||||
return
|
||||
end
|
||||
if #ctx.suggestions == 0 then return end
|
||||
ctx.current_suggestion_idx = ((ctx.current_suggestion_idx - 2 + #ctx.suggestions) % #ctx.suggestions) + 1
|
||||
self:show()
|
||||
end
|
||||
@ -298,9 +266,7 @@ function Suggestion:accept()
|
||||
local content = suggestion.content
|
||||
local lines = vim.split(content, "\n")
|
||||
local cursor_row, cursor_col = Utils.get_cursor_pos()
|
||||
if row > cursor_row then
|
||||
api.nvim_buf_set_lines(bufnr, row - 1, row - 1, false, { "" })
|
||||
end
|
||||
if row > cursor_row then api.nvim_buf_set_lines(bufnr, row - 1, row - 1, false, { "" }) end
|
||||
local line_count = #lines
|
||||
if line_count > 0 then
|
||||
if cursor_row == row then
|
||||
@ -325,9 +291,7 @@ function Suggestion:accept()
|
||||
end
|
||||
|
||||
local down_count = line_count - 1
|
||||
if row > cursor_row then
|
||||
down_count = down_count + 1
|
||||
end
|
||||
if row > cursor_row then down_count = down_count + 1 end
|
||||
|
||||
local cursor_keys = string.rep("<Down>", down_count) .. "<End>"
|
||||
api.nvim_feedkeys(api.nvim_replace_termcodes(cursor_keys, true, false, true), "n", false)
|
||||
@ -347,19 +311,13 @@ function Suggestion:setup_autocmds()
|
||||
end, 77)
|
||||
|
||||
local function suggest_callback()
|
||||
if not vim.bo.buflisted then
|
||||
return
|
||||
end
|
||||
if not vim.bo.buflisted then return end
|
||||
|
||||
if vim.bo.buftype ~= "" then
|
||||
return
|
||||
end
|
||||
if vim.bo.buftype ~= "" then return end
|
||||
|
||||
local ctx = self:ctx()
|
||||
|
||||
if ctx.prev_doc and vim.deep_equal(ctx.prev_doc, Utils.get_doc()) then
|
||||
return
|
||||
end
|
||||
if ctx.prev_doc and vim.deep_equal(ctx.prev_doc, Utils.get_doc()) then return end
|
||||
|
||||
self:hide()
|
||||
last_cursor_pos = api.nvim_win_get_cursor(0)
|
||||
@ -374,9 +332,7 @@ function Suggestion:setup_autocmds()
|
||||
api.nvim_create_autocmd("BufEnter", {
|
||||
group = self.augroup,
|
||||
callback = function()
|
||||
if fn.mode():match("^[iR]") then
|
||||
suggest_callback()
|
||||
end
|
||||
if fn.mode():match "^[iR]" then suggest_callback() end
|
||||
end,
|
||||
})
|
||||
|
||||
@ -396,9 +352,7 @@ function Suggestion:setup_autocmds()
|
||||
end
|
||||
|
||||
function Suggestion:delete_autocmds()
|
||||
if self.augroup then
|
||||
api.nvim_del_augroup_by_id(self.augroup)
|
||||
end
|
||||
if self.augroup then api.nvim_del_augroup_by_id(self.augroup) end
|
||||
self.augroup = nil
|
||||
end
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
local Utils = require("avante.utils")
|
||||
local Utils = require "avante.utils"
|
||||
|
||||
---@class AvanteTokenizer
|
||||
---@field from_pretrained fun(model: string): nil
|
||||
@ -11,19 +11,15 @@ local M = {}
|
||||
M.setup = function(model)
|
||||
vim.defer_fn(function()
|
||||
local ok, core = pcall(require, "avante_tokenizers")
|
||||
if not ok then
|
||||
return
|
||||
end
|
||||
if not ok then return end
|
||||
|
||||
---@cast core AvanteTokenizer
|
||||
if tokenizers == nil then
|
||||
tokenizers = core
|
||||
end
|
||||
if tokenizers == nil then tokenizers = core end
|
||||
|
||||
core.from_pretrained(model)
|
||||
end, 1000)
|
||||
|
||||
local HF_TOKEN = os.getenv("HF_TOKEN")
|
||||
local HF_TOKEN = os.getenv "HF_TOKEN"
|
||||
if HF_TOKEN == nil and model ~= "gpt-4o" then
|
||||
Utils.warn(
|
||||
"Please set HF_TOKEN environment variable to use HuggingFace tokenizer if " .. model .. " is gated",
|
||||
@ -33,35 +29,23 @@ M.setup = function(model)
|
||||
vim.env.HF_HUB_DISABLE_PROGRESS_BARS = 1
|
||||
end
|
||||
|
||||
M.available = function()
|
||||
return tokenizers ~= nil
|
||||
end
|
||||
M.available = function() return tokenizers ~= nil end
|
||||
|
||||
---@param prompt string
|
||||
M.encode = function(prompt)
|
||||
if not tokenizers then
|
||||
return nil
|
||||
end
|
||||
if not prompt or prompt == "" then
|
||||
return nil
|
||||
end
|
||||
if type(prompt) ~= "string" then
|
||||
error("Prompt is not type string", 2)
|
||||
end
|
||||
if not tokenizers then return nil end
|
||||
if not prompt or prompt == "" then return nil end
|
||||
if type(prompt) ~= "string" then error("Prompt is not type string", 2) end
|
||||
|
||||
return tokenizers.encode(prompt)
|
||||
end
|
||||
|
||||
---@param prompt string
|
||||
M.count = function(prompt)
|
||||
if not tokenizers then
|
||||
return math.ceil(#prompt * 0.5)
|
||||
end
|
||||
if not tokenizers then return math.ceil(#prompt * 0.5) end
|
||||
|
||||
local tokens = M.encode(prompt)
|
||||
if not tokens then
|
||||
return 0
|
||||
end
|
||||
if not tokens then return 0 end
|
||||
return #tokens
|
||||
end
|
||||
|
||||
|
@ -6,9 +6,7 @@ local H = {}
|
||||
local C = {
|
||||
filetype = "DressingInput",
|
||||
conceal_char = "*",
|
||||
close_window = function()
|
||||
require("dressing.input").close()
|
||||
end,
|
||||
close_window = function() require("dressing.input").close() end,
|
||||
}
|
||||
|
||||
---@class avante.DressingState
|
||||
@ -34,16 +32,19 @@ H.initialize_input_buffer = function(options)
|
||||
end
|
||||
|
||||
local prompt_length = api.nvim_strwidth(fn.prompt_getprompt(state.input_bufnr))
|
||||
api.nvim_buf_call(state.input_bufnr, function()
|
||||
vim.cmd(string.format(
|
||||
[[
|
||||
api.nvim_buf_call(
|
||||
state.input_bufnr,
|
||||
function()
|
||||
vim.cmd(string.format(
|
||||
[[
|
||||
syn region SecretValue start=/^/ms=s+%s end=/$/ contains=SecretChar
|
||||
syn match SecretChar /./ contained conceal %s
|
||||
]],
|
||||
prompt_length,
|
||||
"cchar=*"
|
||||
))
|
||||
end)
|
||||
prompt_length,
|
||||
"cchar=*"
|
||||
))
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
---@param switch_buffer? boolean To switch back original buffer, default to tru
|
||||
@ -53,9 +54,7 @@ H.teardown = function(switch_buffer)
|
||||
if state.input_winid and api.nvim_win_is_valid(state.input_winid) then
|
||||
C.close_window()
|
||||
state.input_winid = nil
|
||||
if switch_buffer then
|
||||
pcall(api.nvim_set_current_win, state.winid)
|
||||
end
|
||||
if switch_buffer then pcall(api.nvim_set_current_win, state.winid) end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -10,9 +10,7 @@ local M = {}
|
||||
setmetatable(M, {
|
||||
__index = function(t, k)
|
||||
local ok, lazyutil = pcall(require, "lazy.core.util")
|
||||
if ok and lazyutil[k] then
|
||||
return lazyutil[k]
|
||||
end
|
||||
if ok and lazyutil[k] then return lazyutil[k] end
|
||||
|
||||
---@diagnostic disable-next-line: no-unknown
|
||||
t[k] = require("avante.utils." .. k)
|
||||
@ -25,15 +23,11 @@ setmetatable(M, {
|
||||
---@return boolean
|
||||
M.has = function(plugin)
|
||||
local ok, LazyConfig = pcall(require, "lazy.core.config")
|
||||
if ok then
|
||||
return LazyConfig.plugins[plugin] ~= nil
|
||||
end
|
||||
if ok then return LazyConfig.plugins[plugin] ~= nil end
|
||||
return package.loaded[plugin] ~= nil
|
||||
end
|
||||
|
||||
M.is_win = function()
|
||||
return jit.os:find("Windows") ~= nil
|
||||
end
|
||||
M.is_win = function() return jit.os:find "Windows" ~= nil end
|
||||
|
||||
---@return "linux" | "darwin" | "windows"
|
||||
M.get_os_name = function()
|
||||
@ -58,12 +52,12 @@ M.shell_run = function(input_cmd)
|
||||
local cmd
|
||||
|
||||
-- powershell then we can just run the cmd
|
||||
if shell:match("powershell") or shell:match("pwsh") then
|
||||
if shell:match "powershell" or shell:match "pwsh" then
|
||||
cmd = input_cmd
|
||||
elseif vim.fn.has("wsl") > 0 then
|
||||
elseif vim.fn.has "wsl" > 0 then
|
||||
-- wsl: powershell.exe -Command 'command "/path"'
|
||||
cmd = "powershell.exe -NoProfile -Command '" .. input_cmd:gsub("'", '"') .. "'"
|
||||
elseif vim.fn.has("win32") > 0 then
|
||||
elseif vim.fn.has "win32" > 0 then
|
||||
cmd = 'powershell.exe -NoProfile -Command "' .. input_cmd:gsub('"', "'") .. '"'
|
||||
else
|
||||
-- linux and macos we wil just do sh -c
|
||||
@ -138,9 +132,7 @@ M.safe_keymap_set = function(mode, lhs, rhs, opts)
|
||||
---@cast modes -string
|
||||
|
||||
---@param m string
|
||||
modes = vim.tbl_filter(function(m)
|
||||
return not (Keys.have and Keys:have(lhs, m))
|
||||
end, modes)
|
||||
modes = vim.tbl_filter(function(m) return not (Keys.have and Keys:have(lhs, m)) end, modes)
|
||||
|
||||
-- don't create keymap if a lazy keys handler exists
|
||||
if #modes > 0 then
|
||||
@ -157,16 +149,12 @@ end
|
||||
---@param str string
|
||||
---@param opts? {suffix?: string, prefix?: string}
|
||||
function M.trim(str, opts)
|
||||
if not opts then
|
||||
return str
|
||||
end
|
||||
if not opts then return str end
|
||||
local res = str
|
||||
if opts.suffix then
|
||||
res = str:sub(#str - #opts.suffix + 1) == opts.suffix and str:sub(1, #str - #opts.suffix) or str
|
||||
end
|
||||
if opts.prefix then
|
||||
res = str:sub(1, #opts.prefix) == opts.prefix and str:sub(#opts.prefix + 1) or str
|
||||
end
|
||||
if opts.prefix then res = str:sub(1, #opts.prefix) == opts.prefix and str:sub(#opts.prefix + 1) or str end
|
||||
return res
|
||||
end
|
||||
|
||||
@ -178,15 +166,13 @@ end
|
||||
---Get the selected content and range in Visual mode
|
||||
---@return avante.SelectionResult | nil Selected content and range
|
||||
function M.get_visual_selection_and_range()
|
||||
local Range = require("avante.range")
|
||||
local SelectionResult = require("avante.selection_result")
|
||||
local Range = require "avante.range"
|
||||
local SelectionResult = require "avante.selection_result"
|
||||
|
||||
if not M.in_visual_mode() then
|
||||
return nil
|
||||
end
|
||||
if not M.in_visual_mode() then return nil end
|
||||
-- Get the start and end positions of Visual mode
|
||||
local start_pos = vim.fn.getpos("v")
|
||||
local end_pos = vim.fn.getpos(".")
|
||||
local start_pos = vim.fn.getpos "v"
|
||||
local end_pos = vim.fn.getpos "."
|
||||
-- Get the start and end line and column numbers
|
||||
local start_line = start_pos[2]
|
||||
local start_col = start_pos[3]
|
||||
@ -219,9 +205,7 @@ function M.get_visual_selection_and_range()
|
||||
content = lines
|
||||
end
|
||||
end
|
||||
if not content then
|
||||
return nil
|
||||
end
|
||||
if not content then return nil end
|
||||
-- Return the selected content and range
|
||||
return SelectionResult.new(content, range)
|
||||
end
|
||||
@ -231,16 +215,12 @@ end
|
||||
---@param end_ integer
|
||||
---@param buf integer?
|
||||
---@return string[]
|
||||
function M.get_buf_lines(start, end_, buf)
|
||||
return api.nvim_buf_get_lines(buf or 0, start, end_, false)
|
||||
end
|
||||
function M.get_buf_lines(start, end_, buf) return api.nvim_buf_get_lines(buf or 0, start, end_, false) end
|
||||
|
||||
---Get cursor row and column as (1, 0) based
|
||||
---@param win_id integer?
|
||||
---@return integer, integer
|
||||
function M.get_cursor_pos(win_id)
|
||||
return unpack(api.nvim_win_get_cursor(win_id or 0))
|
||||
end
|
||||
function M.get_cursor_pos(win_id) return unpack(api.nvim_win_get_cursor(win_id or 0)) end
|
||||
|
||||
---Check if the buffer is likely to have actionable conflict markers
|
||||
---@param bufnr integer?
|
||||
@ -253,9 +233,7 @@ end
|
||||
---@param name string?
|
||||
---@return table<string, string>
|
||||
function M.get_hl(name)
|
||||
if not name then
|
||||
return {}
|
||||
end
|
||||
if not name then return {} end
|
||||
return api.nvim_get_hl(0, { name = name })
|
||||
end
|
||||
|
||||
@ -278,9 +256,7 @@ end
|
||||
function M.norm(path)
|
||||
if path:sub(1, 1) == "~" then
|
||||
local home = vim.uv.os_homedir()
|
||||
if home:sub(-1) == "\\" or home:sub(-1) == "/" then
|
||||
home = home:sub(1, -2)
|
||||
end
|
||||
if home:sub(-1) == "\\" or home:sub(-1) == "/" then home = home:sub(1, -2) end
|
||||
path = home .. path:sub(2)
|
||||
end
|
||||
path = path:gsub("\\", "/"):gsub("/+", "/")
|
||||
@ -290,38 +266,25 @@ end
|
||||
---@param msg string|string[]
|
||||
---@param opts? LazyNotifyOpts
|
||||
function M.notify(msg, opts)
|
||||
if vim.in_fast_event() then
|
||||
return vim.schedule(function()
|
||||
M.notify(msg, opts)
|
||||
end)
|
||||
end
|
||||
if vim.in_fast_event() then return vim.schedule(function() M.notify(msg, opts) end) end
|
||||
|
||||
opts = opts or {}
|
||||
if type(msg) == "table" then
|
||||
---@diagnostic disable-next-line: no-unknown
|
||||
msg = table.concat(
|
||||
vim.tbl_filter(function(line)
|
||||
return line or false
|
||||
end, msg),
|
||||
"\n"
|
||||
)
|
||||
msg = table.concat(vim.tbl_filter(function(line) return line or false end, msg), "\n")
|
||||
end
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
if opts.stacktrace then
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
msg = msg .. M.pretty_trace({ level = opts.stacklevel or 2 })
|
||||
msg = msg .. M.pretty_trace { level = opts.stacklevel or 2 }
|
||||
end
|
||||
local lang = opts.lang or "markdown"
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local n = opts.once and vim.notify_once or vim.notify
|
||||
n(msg, opts.level or vim.log.levels.INFO, {
|
||||
on_open = function(win)
|
||||
local ok = pcall(function()
|
||||
vim.treesitter.language.add("markdown")
|
||||
end)
|
||||
if not ok then
|
||||
pcall(require, "nvim-treesitter")
|
||||
end
|
||||
local ok = pcall(function() vim.treesitter.language.add "markdown" end)
|
||||
if not ok then pcall(require, "nvim-treesitter") end
|
||||
vim.wo[win].conceallevel = 3
|
||||
vim.wo[win].concealcursor = ""
|
||||
vim.wo[win].spell = false
|
||||
@ -354,9 +317,7 @@ end
|
||||
---@param msg string|string[]
|
||||
---@param opts? LazyNotifyOpts
|
||||
function M.warn(msg, opts)
|
||||
if require("avante.config").options.silent_warning then
|
||||
return
|
||||
end
|
||||
if require("avante.config").options.silent_warning then return end
|
||||
|
||||
opts = opts or {}
|
||||
opts.level = vim.log.levels.WARN
|
||||
@ -366,13 +327,9 @@ end
|
||||
---@param msg string|table
|
||||
---@param opts? LazyNotifyOpts
|
||||
function M.debug(msg, opts)
|
||||
if not require("avante.config").options.debug then
|
||||
return
|
||||
end
|
||||
if not require("avante.config").options.debug then return end
|
||||
opts = opts or {}
|
||||
if opts.title then
|
||||
opts.title = "avante.nvim: " .. opts.title
|
||||
end
|
||||
if opts.title then opts.title = "avante.nvim: " .. opts.title end
|
||||
if type(msg) == "string" then
|
||||
M.notify(msg, opts)
|
||||
else
|
||||
@ -383,9 +340,7 @@ end
|
||||
|
||||
function M.tbl_indexof(tbl, value)
|
||||
for i, v in ipairs(tbl) do
|
||||
if v == value then
|
||||
return i
|
||||
end
|
||||
if v == value then return i end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
@ -396,9 +351,7 @@ function M.update_win_options(winid, opt_name, key, value)
|
||||
if cur_opt_value:find(key .. ":") then
|
||||
cur_opt_value = cur_opt_value:gsub(key .. ":[^,]*", key .. ":" .. value)
|
||||
else
|
||||
if #cur_opt_value > 0 then
|
||||
cur_opt_value = cur_opt_value .. ","
|
||||
end
|
||||
if #cur_opt_value > 0 then cur_opt_value = cur_opt_value .. "," end
|
||||
cur_opt_value = cur_opt_value .. key .. ":" .. value
|
||||
end
|
||||
|
||||
@ -407,15 +360,11 @@ end
|
||||
|
||||
function M.get_win_options(winid, opt_name, key)
|
||||
local cur_opt_value = api.nvim_get_option_value(opt_name, { win = winid })
|
||||
if not cur_opt_value then
|
||||
return
|
||||
end
|
||||
if not cur_opt_value then return end
|
||||
local pieces = vim.split(cur_opt_value, ",")
|
||||
for _, piece in ipairs(pieces) do
|
||||
local kv_pair = vim.split(piece, ":")
|
||||
if kv_pair[1] == key then
|
||||
return kv_pair[2]
|
||||
end
|
||||
if kv_pair[1] == key then return kv_pair[2] end
|
||||
end
|
||||
end
|
||||
|
||||
@ -425,7 +374,7 @@ function M.unlock_buf(bufnr)
|
||||
end
|
||||
|
||||
function M.lock_buf(bufnr)
|
||||
vim.cmd("stopinsert")
|
||||
vim.cmd "stopinsert"
|
||||
vim.bo[bufnr].modified = false
|
||||
vim.bo[bufnr].modifiable = false
|
||||
end
|
||||
@ -453,14 +402,10 @@ end
|
||||
M.buf_list_wins = function(bufnr)
|
||||
local wins = {}
|
||||
|
||||
if not bufnr or bufnr == 0 then
|
||||
bufnr = api.nvim_get_current_buf()
|
||||
end
|
||||
if not bufnr or bufnr == 0 then bufnr = api.nvim_get_current_buf() end
|
||||
|
||||
for _, winnr in ipairs(api.nvim_list_wins()) do
|
||||
if api.nvim_win_is_valid(winnr) and api.nvim_win_get_buf(winnr) == bufnr then
|
||||
table.insert(wins, winnr)
|
||||
end
|
||||
if api.nvim_win_is_valid(winnr) and api.nvim_win_get_buf(winnr) == bufnr then table.insert(wins, winnr) end
|
||||
end
|
||||
|
||||
return wins
|
||||
@ -468,25 +413,17 @@ end
|
||||
|
||||
local sidebar_buffer_var_name = "is_avante_sidebar_buffer"
|
||||
|
||||
function M.mark_as_sidebar_buffer(bufnr)
|
||||
api.nvim_buf_set_var(bufnr, sidebar_buffer_var_name, true)
|
||||
end
|
||||
function M.mark_as_sidebar_buffer(bufnr) api.nvim_buf_set_var(bufnr, sidebar_buffer_var_name, true) end
|
||||
|
||||
function M.is_sidebar_buffer(bufnr)
|
||||
local ok, v = pcall(api.nvim_buf_get_var, bufnr, sidebar_buffer_var_name)
|
||||
if not ok then
|
||||
return false
|
||||
end
|
||||
if not ok then return false end
|
||||
return v == true
|
||||
end
|
||||
|
||||
function M.trim_spaces(s)
|
||||
return s:match("^%s*(.-)%s*$")
|
||||
end
|
||||
function M.trim_spaces(s) return s:match "^%s*(.-)%s*$" end
|
||||
|
||||
function M.fallback(v, default_value)
|
||||
return type(v) == "nil" and default_value or v
|
||||
end
|
||||
function M.fallback(v, default_value) return type(v) == "nil" and default_value or v end
|
||||
|
||||
-- luacheck: push no max comment line length
|
||||
---@param type_name "'nil'" | "'number'" | "'string'" | "'boolean'" | "'table'" | "'function'" | "'thread'" | "'userdata'" | "'list'" | '"map"'
|
||||
@ -494,13 +431,9 @@ end
|
||||
function M.is_type(type_name, v)
|
||||
---@diagnostic disable-next-line: deprecated
|
||||
local islist = vim.islist or vim.tbl_islist
|
||||
if type_name == "list" then
|
||||
return islist(v)
|
||||
end
|
||||
if type_name == "list" then return islist(v) end
|
||||
|
||||
if type_name == "map" then
|
||||
return type(v) == "table" and not islist(v)
|
||||
end
|
||||
if type_name == "map" then return type(v) == "table" and not islist(v) end
|
||||
|
||||
return type(v) == type_name
|
||||
end
|
||||
@ -508,20 +441,14 @@ end
|
||||
|
||||
---@param code string
|
||||
---@return string
|
||||
function M.get_indentation(code)
|
||||
return code:match("^%s*") or ""
|
||||
end
|
||||
function M.get_indentation(code) return code:match "^%s*" or "" end
|
||||
|
||||
--- remove indentation from code: spaces or tabs
|
||||
function M.remove_indentation(code)
|
||||
return code:gsub("^%s*", "")
|
||||
end
|
||||
function M.remove_indentation(code) return code:gsub("^%s*", "") end
|
||||
|
||||
local function relative_path(absolute)
|
||||
local relative = fn.fnamemodify(absolute, ":.")
|
||||
if string.sub(relative, 0, 1) == "/" then
|
||||
return fn.fnamemodify(absolute, ":t")
|
||||
end
|
||||
if string.sub(relative, 0, 1) == "/" then return fn.fnamemodify(absolute, ":t") end
|
||||
return relative
|
||||
end
|
||||
|
||||
@ -558,9 +485,7 @@ function M.prepend_line_number(content, start_line)
|
||||
return table.concat(result, "\n")
|
||||
end
|
||||
|
||||
function M.trim_line_number(line)
|
||||
return line:gsub("^L%d+: ", "")
|
||||
end
|
||||
function M.trim_line_number(line) return line:gsub("^L%d+: ", "") end
|
||||
|
||||
function M.trim_all_line_numbers(content)
|
||||
return vim
|
||||
@ -569,7 +494,7 @@ function M.trim_all_line_numbers(content)
|
||||
local new_line = M.trim_line_number(line)
|
||||
return new_line
|
||||
end)
|
||||
:join("\n")
|
||||
:join "\n"
|
||||
end
|
||||
|
||||
function M.debounce(func, delay)
|
||||
@ -578,9 +503,7 @@ function M.debounce(func, delay)
|
||||
return function(...)
|
||||
local args = { ... }
|
||||
|
||||
if timer_id then
|
||||
fn.timer_stop(timer_id)
|
||||
end
|
||||
if timer_id then fn.timer_stop(timer_id) end
|
||||
|
||||
timer_id = fn.timer_start(delay, function()
|
||||
func(unpack(args))
|
||||
|
@ -1,12 +1,10 @@
|
||||
-- COPIED and MODIFIED from https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/util/root.lua
|
||||
local Utils = require("avante.utils")
|
||||
local Utils = require "avante.utils"
|
||||
|
||||
---@class avante.utils.root
|
||||
---@overload fun(): string
|
||||
local M = setmetatable({}, {
|
||||
__call = function(m)
|
||||
return m.get()
|
||||
end,
|
||||
__call = function(m) return m.get() end,
|
||||
})
|
||||
|
||||
---@class AvanteRoot
|
||||
@ -22,25 +20,19 @@ M.spec = { "lsp", { ".git", "lua" }, "cwd" }
|
||||
|
||||
M.detectors = {}
|
||||
|
||||
function M.detectors.cwd()
|
||||
return { vim.uv.cwd() }
|
||||
end
|
||||
function M.detectors.cwd() return { vim.uv.cwd() } end
|
||||
|
||||
---@param buf number
|
||||
function M.detectors.lsp(buf)
|
||||
local bufpath = M.bufpath(buf)
|
||||
if not bufpath then
|
||||
return {}
|
||||
end
|
||||
if not bufpath then return {} end
|
||||
local roots = {} ---@type string[]
|
||||
for _, client in pairs(Utils.lsp.get_clients({ bufnr = buf })) do
|
||||
for _, client in pairs(Utils.lsp.get_clients { bufnr = buf }) do
|
||||
local workspace = client.config.workspace_folders
|
||||
for _, ws in pairs(workspace or {}) do
|
||||
roots[#roots + 1] = vim.uri_to_fname(ws.uri)
|
||||
end
|
||||
if client.root_dir then
|
||||
roots[#roots + 1] = client.root_dir
|
||||
end
|
||||
if client.root_dir then roots[#roots + 1] = client.root_dir end
|
||||
end
|
||||
return vim.tbl_filter(function(path)
|
||||
path = Utils.norm(path)
|
||||
@ -54,30 +46,20 @@ function M.detectors.pattern(buf, patterns)
|
||||
local path = M.bufpath(buf) or vim.uv.cwd()
|
||||
local pattern = vim.fs.find(function(name)
|
||||
for _, p in ipairs(patterns) do
|
||||
if name == p then
|
||||
return true
|
||||
end
|
||||
if p:sub(1, 1) == "*" and name:find(vim.pesc(p:sub(2)) .. "$") then
|
||||
return true
|
||||
end
|
||||
if name == p then return true end
|
||||
if p:sub(1, 1) == "*" and name:find(vim.pesc(p:sub(2)) .. "$") then return true end
|
||||
end
|
||||
return false
|
||||
end, { path = path, upward = true })[1]
|
||||
return pattern and { vim.fs.dirname(pattern) } or {}
|
||||
end
|
||||
|
||||
function M.bufpath(buf)
|
||||
return M.realpath(vim.api.nvim_buf_get_name(assert(buf)))
|
||||
end
|
||||
function M.bufpath(buf) return M.realpath(vim.api.nvim_buf_get_name(assert(buf))) end
|
||||
|
||||
function M.cwd()
|
||||
return M.realpath(vim.uv.cwd()) or ""
|
||||
end
|
||||
function M.cwd() return M.realpath(vim.uv.cwd()) or "" end
|
||||
|
||||
function M.realpath(path)
|
||||
if path == "" or path == nil then
|
||||
return nil
|
||||
end
|
||||
if path == "" or path == nil then return nil end
|
||||
path = vim.uv.fs_realpath(path) or path
|
||||
return Utils.norm(path)
|
||||
end
|
||||
@ -90,9 +72,7 @@ function M.resolve(spec)
|
||||
elseif type(spec) == "function" then
|
||||
return spec
|
||||
end
|
||||
return function(buf)
|
||||
return M.detectors.pattern(buf, spec)
|
||||
end
|
||||
return function(buf) return M.detectors.pattern(buf, spec) end
|
||||
end
|
||||
|
||||
---@param opts? { buf?: number, spec?: AvanteRootSpec[], all?: boolean }
|
||||
@ -109,18 +89,12 @@ function M.detect(opts)
|
||||
local roots = {} ---@type string[]
|
||||
for _, p in ipairs(paths) do
|
||||
local pp = M.realpath(p)
|
||||
if pp and not vim.tbl_contains(roots, pp) then
|
||||
roots[#roots + 1] = pp
|
||||
end
|
||||
if pp and not vim.tbl_contains(roots, pp) then roots[#roots + 1] = pp end
|
||||
end
|
||||
table.sort(roots, function(a, b)
|
||||
return #a > #b
|
||||
end)
|
||||
table.sort(roots, function(a, b) return #a > #b end)
|
||||
if #roots > 0 then
|
||||
ret[#ret + 1] = { spec = spec, paths = roots }
|
||||
if opts.all == false then
|
||||
break
|
||||
end
|
||||
if opts.all == false then break end
|
||||
end
|
||||
end
|
||||
return ret
|
||||
@ -141,13 +115,11 @@ function M.get(opts)
|
||||
local buf = opts.buf or vim.api.nvim_get_current_buf()
|
||||
local ret = M.cache[buf]
|
||||
if not ret then
|
||||
local roots = M.detect({ all = false, buf = buf })
|
||||
local roots = M.detect { all = false, buf = buf }
|
||||
ret = roots[1] and roots[1].paths[1] or vim.uv.cwd()
|
||||
M.cache[buf] = ret
|
||||
end
|
||||
if opts and opts.normalize then
|
||||
return ret
|
||||
end
|
||||
if opts and opts.normalize then return ret end
|
||||
return Utils.is_win() and ret:gsub("/", "\\") or ret
|
||||
end
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
--Taken from https://github.com/jackMort/ChatGPT.nvim/blob/main/lua/chatgpt/flows/chat/tokens.lua
|
||||
local Tokenizer = require("avante.tokenizers")
|
||||
local Tokenizer = require "avante.tokenizers"
|
||||
|
||||
---@class avante.utils.tokens
|
||||
local Tokens = {}
|
||||
@ -13,13 +13,11 @@ local cost_per_token = {
|
||||
---@param text string The text to calculate the number of tokens for.
|
||||
---@return integer The number of tokens in the given text.
|
||||
function Tokens.calculate_tokens(text)
|
||||
if Tokenizer.available() then
|
||||
return Tokenizer.count(text)
|
||||
end
|
||||
if Tokenizer.available() then return Tokenizer.count(text) end
|
||||
|
||||
local tokens = 0
|
||||
local current_token = ""
|
||||
for char in text:gmatch(".") do
|
||||
for char in text:gmatch "." do
|
||||
if char == " " or char == "\n" then
|
||||
if current_token ~= "" then
|
||||
tokens = tokens + 1
|
||||
@ -29,9 +27,7 @@ function Tokens.calculate_tokens(text)
|
||||
current_token = current_token .. char
|
||||
end
|
||||
end
|
||||
if current_token ~= "" then
|
||||
tokens = tokens + 1
|
||||
end
|
||||
if current_token ~= "" then tokens = tokens + 1 end
|
||||
return tokens
|
||||
end
|
||||
|
||||
@ -48,8 +44,6 @@ end
|
||||
-- @param tokens The number of tokens to calculate the cost of.
|
||||
-- @param model The model to use to calculate the cost.
|
||||
-- @return The cost of the given number of tokens in dollars.
|
||||
function Tokens.usage_in_dollars(tokens, model)
|
||||
return tokens * cost_per_token[model or "davinci"]
|
||||
end
|
||||
function Tokens.usage_in_dollars(tokens, model) return tokens * cost_per_token[model or "davinci"] end
|
||||
|
||||
return Tokens
|
||||
|
@ -8,9 +8,7 @@ local function get_library_path()
|
||||
end
|
||||
|
||||
---@type fun(s: string): string
|
||||
local trim_semicolon = function(s)
|
||||
return s:sub(-1) == ";" and s:sub(1, -2) or s
|
||||
end
|
||||
local trim_semicolon = function(s) return s:sub(-1) == ";" and s:sub(1, -2) or s end
|
||||
|
||||
M.load = function()
|
||||
local library_path = get_library_path()
|
||||
|
@ -10,21 +10,13 @@ function source.new(sidebar)
|
||||
}, { __index = source })
|
||||
end
|
||||
|
||||
function source:is_available()
|
||||
return vim.bo.filetype == "AvanteInput"
|
||||
end
|
||||
function source:is_available() return vim.bo.filetype == "AvanteInput" end
|
||||
|
||||
source.get_position_encoding_kind = function()
|
||||
return "utf-8"
|
||||
end
|
||||
source.get_position_encoding_kind = function() return "utf-8" end
|
||||
|
||||
function source:get_trigger_characters()
|
||||
return { "/" }
|
||||
end
|
||||
function source:get_trigger_characters() return { "/" } end
|
||||
|
||||
function source:get_keyword_pattern()
|
||||
return [[\%(@\|#\|/\)\k*]]
|
||||
end
|
||||
function source:get_keyword_pattern() return [[\%(@\|#\|/\)\k*]] end
|
||||
|
||||
function source:complete(_, callback)
|
||||
local kind = require("cmp").lsp.CompletionItemKind.Variable
|
||||
@ -41,10 +33,10 @@ function source:complete(_, callback)
|
||||
})
|
||||
end
|
||||
|
||||
callback({
|
||||
callback {
|
||||
items = items,
|
||||
isIncomplete = false,
|
||||
})
|
||||
}
|
||||
end
|
||||
|
||||
return source
|
||||
|
@ -1,17 +1,17 @@
|
||||
if vim.fn.has("nvim-0.10") == 0 then
|
||||
if vim.fn.has "nvim-0.10" == 0 then
|
||||
vim.api.nvim_echo({
|
||||
{ "Avante requires at least nvim-0.10", "ErrorMsg" },
|
||||
{ "Please upgrade your neovim version", "WarningMsg" },
|
||||
{ "Press any key to exit", "ErrorMsg" },
|
||||
}, true, {})
|
||||
vim.fn.getchar()
|
||||
vim.cmd([[quit]])
|
||||
vim.cmd [[quit]]
|
||||
end
|
||||
|
||||
--- NOTE: We will override vim.paste if img-clip.nvim is available to work with avante.nvim internal logic paste
|
||||
|
||||
local Clipboard = require("avante.clipboard")
|
||||
local Config = require("avante.config")
|
||||
local Clipboard = require "avante.clipboard"
|
||||
local Config = require "avante.config"
|
||||
|
||||
if Config.support_paste_image(true) then
|
||||
vim.paste = (function(overriden)
|
||||
@ -22,17 +22,13 @@ if Config.support_paste_image(true) then
|
||||
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local filetype = vim.api.nvim_get_option_value("filetype", { buf = bufnr })
|
||||
if filetype ~= "AvanteInput" then
|
||||
return overriden(lines, phase)
|
||||
end
|
||||
if filetype ~= "AvanteInput" then return overriden(lines, phase) end
|
||||
|
||||
---@type string
|
||||
local line = lines[1]
|
||||
|
||||
local ok = Clipboard.paste_image(line)
|
||||
if not ok then
|
||||
return overriden(lines, phase)
|
||||
end
|
||||
if not ok then return overriden(lines, phase) end
|
||||
|
||||
-- After pasting, insert a new line and set cursor to this line
|
||||
vim.api.nvim_buf_set_lines(bufnr, -1, -1, false, { "" })
|
||||
|
7
stylua.toml
Normal file
7
stylua.toml
Normal file
@ -0,0 +1,7 @@
|
||||
indent_type = "Spaces"
|
||||
indent_width = 2
|
||||
no_call_parentheses = true
|
||||
column_width = 119
|
||||
line_endings = "Unix"
|
||||
quote_style = "AutoPreferDouble"
|
||||
collapse_simple_statement = "Always"
|
Loading…
x
Reference in New Issue
Block a user