chore: prefer not to use function assignment (#1381)

This commit is contained in:
Peter Cardenas
2025-02-24 20:08:03 -08:00
committed by GitHub
parent a1d1697400
commit afa674c6fd
29 changed files with 571 additions and 147 deletions

View File

@@ -12,7 +12,7 @@ local PromptInput = require("avante.prompt_input")
local M = {} local M = {}
---@param target_provider FileSelectorProvider ---@param target_provider FileSelectorProvider
M.switch_file_selector_provider = function(target_provider) function M.switch_file_selector_provider(target_provider)
require("avante.config").override({ require("avante.config").override({
file_selector = { file_selector = {
provider = target_provider, provider = target_provider,
@@ -21,7 +21,7 @@ M.switch_file_selector_provider = function(target_provider)
end end
---@param target Provider ---@param target Provider
M.switch_provider = function(target) require("avante.providers").refresh(target) end function M.switch_provider(target) require("avante.providers").refresh(target) end
---@param path string ---@param path string
local function to_windows_path(path) local function to_windows_path(path)
@@ -35,7 +35,7 @@ local function to_windows_path(path)
end end
---@param opts? {source: boolean} ---@param opts? {source: boolean}
M.build = function(opts) function M.build(opts)
opts = opts or { source = true } opts = opts or { source = true }
local dirname = Utils.trim(string.sub(debug.getinfo(1).source, 2, #"/init.lua" * -1), { suffix = "/" }) local dirname = Utils.trim(string.sub(debug.getinfo(1).source, 2, #"/init.lua" * -1), { suffix = "/" })
local git_root = vim.fs.find(".git", { path = dirname, upward = true })[1] local git_root = vim.fs.find(".git", { path = dirname, upward = true })[1]
@@ -101,7 +101,7 @@ end
---@field floating? boolean whether to open a floating input to enter the question ---@field floating? boolean whether to open a floating input to enter the question
---@param opts? AskOptions ---@param opts? AskOptions
M.ask = function(opts) function M.ask(opts)
opts = opts or {} opts = opts or {}
if type(opts) == "string" then if type(opts) == "string" then
Utils.warn("passing 'ask' as string is deprecated, do {question = '...'} instead", { once = true }) Utils.warn("passing 'ask' as string is deprecated, do {question = '...'} instead", { once = true })
@@ -147,7 +147,7 @@ M.ask = function(opts)
end end
---@param question? string ---@param question? string
M.edit = function(question) function M.edit(question)
local _, selection = require("avante").get() local _, selection = require("avante").get()
if not selection then return end if not selection then return end
selection:create_editing_input() selection:create_editing_input()
@@ -157,13 +157,13 @@ M.edit = function(question)
end end
---@return avante.Suggestion | nil ---@return avante.Suggestion | nil
M.get_suggestion = function() function M.get_suggestion()
local _, _, suggestion = require("avante").get() local _, _, suggestion = require("avante").get()
return suggestion return suggestion
end end
---@param opts? AskOptions ---@param opts? AskOptions
M.refresh = function(opts) function M.refresh(opts)
opts = opts or {} opts = opts or {}
local sidebar = require("avante").get() local sidebar = require("avante").get()
if not sidebar then return end if not sidebar then return end
@@ -185,7 +185,7 @@ M.refresh = function(opts)
end end
---@param opts? AskOptions ---@param opts? AskOptions
M.focus = function(opts) function M.focus(opts)
opts = opts or {} opts = opts or {}
local sidebar = require("avante").get() local sidebar = require("avante").get()
if not sidebar then return end if not sidebar then return end
@@ -211,7 +211,7 @@ M.focus = function(opts)
end end
end end
M.select_model = function() require("avante.model_selector").open() end function M.select_model() require("avante.model_selector").open() end
return setmetatable(M, { return setmetatable(M, {
__index = function(t, k) __index = function(t, k)

View File

@@ -25,7 +25,7 @@ end
M.support_paste_image = Config.support_paste_image M.support_paste_image = Config.support_paste_image
M.setup = function() function M.setup()
get_paste_directory() 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
@@ -34,7 +34,7 @@ M.setup = function()
end end
---@param line? string ---@param line? string
M.paste_image = function(line) function M.paste_image(line)
line = line or nil line = line or nil
if not Config.support_paste_image() then return false end if not Config.support_paste_image() then return false end
@@ -53,7 +53,7 @@ M.paste_image = function(line)
end end
---@param filepath string ---@param filepath string
M.get_base64_content = function(filepath) function M.get_base64_content(filepath)
local os_mapping = Utils.get_os_name() local os_mapping = Utils.get_os_name()
---@type vim.SystemCompleted ---@type vim.SystemCompleted
local output local output

View File

@@ -479,18 +479,18 @@ M = setmetatable(M, {
end, end,
}) })
M.support_paste_image = function() return Utils.has("img-clip.nvim") or Utils.has("img-clip") end function M.support_paste_image() 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 function M.get_window_width() return math.ceil(vim.o.columns * (M.windows.width / 100)) end
---@param provider Provider ---@param provider Provider
---@return boolean ---@return boolean
M.has_provider = function(provider) return M._options[provider] ~= nil or M.vendors[provider] ~= nil end function M.has_provider(provider) return M._options[provider] ~= nil or M.vendors[provider] ~= nil end
---get supported providers ---get supported providers
---@param provider Provider ---@param provider Provider
---@return AvanteProviderFunctor ---@return AvanteProviderFunctor
M.get_provider = function(provider) function M.get_provider(provider)
if M._options[provider] ~= nil then if M._options[provider] ~= nil then
return vim.deepcopy(M._options[provider], true) return vim.deepcopy(M._options[provider], true)
elseif M.vendors and M.vendors[provider] ~= nil then elseif M.vendors and M.vendors[provider] ~= nil then

View File

@@ -351,7 +351,7 @@ end
-----------------------------------------------------------------------------// -----------------------------------------------------------------------------//
---@param bufnr integer given buffer id ---@param bufnr integer given buffer id
H.setup_buffer_mappings = function(bufnr) function H.setup_buffer_mappings(bufnr)
---@param desc string ---@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
@@ -372,7 +372,7 @@ H.setup_buffer_mappings = function(bufnr)
end end
---@param bufnr integer ---@param bufnr integer
H.clear_buffer_mappings = function(bufnr) function H.clear_buffer_mappings(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.mappings.diff) do for _, mapping in pairs(Config.mappings.diff) 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
@@ -382,7 +382,7 @@ H.clear_buffer_mappings = function(bufnr)
end end
---@param bufnr integer ---@param bufnr integer
M.override_timeoutlen = function(bufnr) function M.override_timeoutlen(bufnr)
if vim.b[bufnr].avante_original_timeoutlen then return end if vim.b[bufnr].avante_original_timeoutlen then return end
if Config.diff.override_timeoutlen > 0 then if Config.diff.override_timeoutlen > 0 then
vim.b[bufnr].avante_original_timeoutlen = vim.o.timeoutlen vim.b[bufnr].avante_original_timeoutlen = vim.o.timeoutlen
@@ -391,7 +391,7 @@ M.override_timeoutlen = function(bufnr)
end end
---@param bufnr integer ---@param bufnr integer
M.restore_timeoutlen = function(bufnr) function M.restore_timeoutlen(bufnr)
if vim.b[bufnr].avante_original_timeoutlen then if vim.b[bufnr].avante_original_timeoutlen then
vim.o.timeoutlen = vim.b[bufnr].avante_original_timeoutlen vim.o.timeoutlen = vim.b[bufnr].avante_original_timeoutlen
vim.b[bufnr].avante_original_timeoutlen = nil vim.b[bufnr].avante_original_timeoutlen = nil

View File

@@ -211,7 +211,7 @@ function FileSelector:fzf_ui(handler)
local filepaths = self:get_filepaths() local filepaths = self:get_filepaths()
local close_action = function() handler(nil) end local function close_action() handler(nil) end
fzf_lua.fzf_exec( fzf_lua.fzf_exec(
filepaths, filepaths,
vim.tbl_deep_extend("force", { vim.tbl_deep_extend("force", {
@@ -244,8 +244,8 @@ function FileSelector:mini_pick_ui(handler)
Utils.error("mini.pick is not set up. Please install and set up mini.pick to use it as a file selector.") Utils.error("mini.pick is not set up. Please install and set up mini.pick to use it as a file selector.")
return return
end end
local choose = function(item) handler(type(item) == "string" and { item } or item) end local function choose(item) handler(type(item) == "string" and { item } or item) end
local choose_marked = function(items_marked) handler(items_marked) end local function choose_marked(items_marked) handler(items_marked) end
local source = { choose = choose, choose_marked = choose_marked } local source = { choose = choose, choose_marked = choose_marked }
---@diagnostic disable-next-line: undefined-global ---@diagnostic disable-next-line: undefined-global
local result = MiniPick.builtin.files(nil, { source = source }) local result = MiniPick.builtin.files(nil, { source = source })

View File

@@ -3,7 +3,7 @@ local H = require("vim.health")
local Utils = require("avante.utils") local Utils = require("avante.utils")
local Config = require("avante.config") local Config = require("avante.config")
M.check = function() function M.check()
H.start("avante.nvim") H.start("avante.nvim")
-- Required dependencies -- Required dependencies

View File

@@ -37,7 +37,7 @@ local function has_set_colors(hl_group)
return next(hl) ~= nil return next(hl) ~= nil
end end
M.setup = function() function M.setup()
if Config.behaviour.auto_set_highlight_group then if Config.behaviour.auto_set_highlight_group then
vim vim
.iter(Highlights) .iter(Highlights)
@@ -59,16 +59,16 @@ M.setup = function()
M.setup_conflict_highlights() M.setup_conflict_highlights()
end end
M.setup_conflict_highlights = function() function M.setup_conflict_highlights()
local custom_hls = Config.highlights.diff local custom_hls = Config.highlights.diff
---@return number | nil ---@return number | nil
local get_bg = function(hl_name) local function get_bg(hl_name)
local hl = api.nvim_get_hl(0, { name = hl_name }) local hl = api.nvim_get_hl(0, { name = hl_name })
return hl.bg return hl.bg
end end
local get_bold = function(hl_name) local function get_bold(hl_name)
local hl = api.nvim_get_hl(0, { name = hl_name }) local hl = api.nvim_get_hl(0, { name = hl_name })
return hl.bold return hl.bold
end end
@@ -133,7 +133,7 @@ setmetatable(M, {
--- ---
---@param rgb_24bit number 24-bit RGB value ---@param rgb_24bit number 24-bit RGB value
---@return {r: integer, g: integer, b: integer} with keys 'r', 'g', 'b' in [0,255] ---@return {r: integer, g: integer, b: integer} with keys 'r', 'g', 'b' in [0,255]
H.decode_24bit_rgb = function(rgb_24bit) function H.decode_24bit_rgb(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 r = band(rshift(rgb_24bit, 16), 255)
local g = band(rshift(rgb_24bit, 8), 255) local g = band(rshift(rgb_24bit, 8), 255)
@@ -143,7 +143,7 @@ end
---@param attr integer ---@param attr integer
---@param percent integer ---@param percent integer
H.alter = function(attr, percent) return math.floor(attr * (100 + percent) / 100) end function H.alter(attr, percent) return math.floor(attr * (100 + percent) / 100) end
---@source https://stackoverflow.com/q/5560248 ---@source https://stackoverflow.com/q/5560248
---@see https://stackoverflow.com/a/37797380 ---@see https://stackoverflow.com/a/37797380
@@ -151,7 +151,7 @@ H.alter = function(attr, percent) return math.floor(attr * (100 + percent) / 100
---@param color number ---@param color number
---@param percent number ---@param percent number
---@return string ---@return string
H.shade_color = function(color, percent) function H.shade_color(color, percent)
percent = vim.opt.background:get() == "light" and percent / 5 or percent percent = vim.opt.background:get() == "light" and percent / 5 or percent
local rgb = H.decode_24bit_rgb(color) 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

View File

@@ -24,12 +24,12 @@ M.did_setup = false
local H = {} local H = {}
H.load_path = function() function H.load_path()
local ok, LazyConfig = pcall(require, "lazy.core.config") local ok, LazyConfig = pcall(require, "lazy.core.config")
if ok then if ok then
local name = "avante.nvim" local name = "avante.nvim"
local load_path = function() require("avante_lib").load() end local function load_path() require("avante_lib").load() end
if LazyConfig.plugins[name] and LazyConfig.plugins[name]._.loaded then if LazyConfig.plugins[name] and LazyConfig.plugins[name]._.loaded then
vim.schedule(load_path) vim.schedule(load_path)
@@ -54,7 +54,7 @@ H.load_path = function()
end end
end end
H.keymaps = function() function H.keymaps()
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteAsk)", function() require("avante.api").ask() end, { noremap = true }) vim.keymap.set({ "n", "v" }, "<Plug>(AvanteAsk)", function() require("avante.api").ask() end, { noremap = true })
vim.keymap.set( vim.keymap.set(
{ "n", "v" }, { "n", "v" },
@@ -180,17 +180,17 @@ end
---@class ApiCaller ---@class ApiCaller
---@operator call(...): any ---@operator call(...): any
H.api = function(fun) function H.api(fun)
return setmetatable({ api = true }, { return setmetatable({ api = true }, {
__call = function(...) return fun(...) end, __call = function(...) return fun(...) end,
}) --[[@as ApiCaller]] }) --[[@as ApiCaller]]
end end
H.signs = function() vim.fn.sign_define("AvanteInputPromptSign", { text = Config.windows.input.prefix }) end function H.signs() vim.fn.sign_define("AvanteInputPromptSign", { text = Config.windows.input.prefix }) end
H.augroup = api.nvim_create_augroup("avante_autocmds", { clear = true }) H.augroup = api.nvim_create_augroup("avante_autocmds", { clear = true })
H.autocmds = function() function H.autocmds()
api.nvim_create_autocmd("TabEnter", { api.nvim_create_autocmd("TabEnter", {
group = H.augroup, group = H.augroup,
pattern = "*", pattern = "*",
@@ -293,7 +293,7 @@ end
M.toggle = { api = true } M.toggle = { api = true }
---@param opts? AskOptions ---@param opts? AskOptions
M.toggle_sidebar = function(opts) function M.toggle_sidebar(opts)
opts = opts or {} opts = opts or {}
if opts.ask == nil then opts.ask = true end if opts.ask == nil then opts.ask = true end
@@ -308,14 +308,14 @@ M.toggle_sidebar = function(opts)
return sidebar:toggle(opts) return sidebar:toggle(opts)
end end
M.is_sidebar_open = function() function M.is_sidebar_open()
local sidebar = M.get() local sidebar = M.get()
if not sidebar then return false end if not sidebar then return false end
return sidebar:is_open() return sidebar:is_open()
end end
---@param opts? AskOptions ---@param opts? AskOptions
M.open_sidebar = function(opts) function M.open_sidebar(opts)
opts = opts or {} opts = opts or {}
if opts.ask == nil then opts.ask = true end if opts.ask == nil then opts.ask = true end
local sidebar = M.get() local sidebar = M.get()
@@ -324,7 +324,7 @@ M.open_sidebar = function(opts)
M.current.sidebar:open(opts) M.current.sidebar:open(opts)
end end
M.close_sidebar = function() function M.close_sidebar()
local sidebar = M.get() local sidebar = M.get()
if not sidebar then return end if not sidebar then return end
sidebar:close() sidebar:close()

424
lua/avante/init.lua-E Normal file
View File

@@ -0,0 +1,424 @@
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 RagService = require("avante.rag_service")
---@class Avante
local M = {
---@type avante.Sidebar[] we use this to track chat command across tabs
sidebars = {},
---@type avante.Selection[]
selections = {},
---@type avante.Suggestion[]
suggestions = {},
---@type {sidebar?: avante.Sidebar, selection?: avante.Selection, suggestion?: avante.Suggestion}
current = { sidebar = nil, selection = nil, suggestion = nil },
}
M.did_setup = false
local H = {}
H.load_path = function()
local ok, LazyConfig = pcall(require, "lazy.core.config")
if ok then
local name = "avante.nvim"
local load_path = function() require("avante_lib").load() end
if LazyConfig.plugins[name] and LazyConfig.plugins[name]._.loaded then
vim.schedule(load_path)
else
api.nvim_create_autocmd("User", {
pattern = "LazyLoad",
callback = function(event)
if event.data == name then
load_path()
return true
end
end,
})
end
api.nvim_create_autocmd("User", {
pattern = "VeryLazy",
callback = load_path,
})
else
require("avante_lib").load()
end
end
H.keymaps = function()
vim.keymap.set({ "n", "v" }, "<Plug>(AvanteAsk)", function() require("avante.api").ask() end, { noremap = true })
vim.keymap.set(
{ "n", "v" },
"<Plug>(AvanteChat)",
function() require("avante.api").ask({ ask = false }) 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>(AvanteFocus)", function() require("avante.api").focus() end, { noremap = true })
vim.keymap.set("n", "<Plug>(AvanteBuild)", function() require("avante.api").build() 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", "<Plug>(AvanteToggleSuggestion)", function() M.toggle.suggestion() 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", "<Plug>(AvanteSelectModel)", function() require("avante.api").select_model() 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.focus,
function() require("avante.api").focus() end,
{ desc = "avante: focus" }
)
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",
Config.mappings.toggle.suggestion,
function() M.toggle.suggestion() end,
{ desc = "avante: toggle suggestion" }
)
Utils.safe_keymap_set("n", Config.mappings.toggle.repomap, function() require("avante.repo_map").show() end, {
desc = "avante: display repo map",
noremap = true,
silent = true,
})
Utils.safe_keymap_set(
"n",
Config.mappings.select_model,
function() require("avante.api").select_model() end,
{ desc = "avante: select model" }
)
end
if Config.behaviour.auto_suggestions then
Utils.safe_keymap_set("i", Config.mappings.suggestion.accept, function()
local _, _, sg = M.get()
sg:accept()
end, {
desc = "avante: accept suggestion",
noremap = true,
silent = true,
})
Utils.safe_keymap_set("i", Config.mappings.suggestion.dismiss, function()
local _, _, sg = M.get()
if sg:is_visible() then sg:dismiss() end
end, {
desc = "avante: dismiss suggestion",
noremap = true,
silent = true,
})
Utils.safe_keymap_set("i", Config.mappings.suggestion.next, function()
local _, _, sg = M.get()
sg:next()
end, {
desc = "avante: next suggestion",
noremap = true,
silent = true,
})
Utils.safe_keymap_set("i", Config.mappings.suggestion.prev, function()
local _, _, sg = M.get()
sg:prev()
end, {
desc = "avante: previous suggestion",
noremap = true,
silent = true,
})
end
end
---@class ApiCaller
---@operator call(...): any
H.api = function(fun)
return setmetatable({ api = true }, {
__call = function(...) return fun(...) end,
}) --[[@as ApiCaller]]
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 })
H.autocmds = function()
api.nvim_create_autocmd("TabEnter", {
group = H.augroup,
pattern = "*",
once = true,
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
end,
})
api.nvim_create_autocmd("VimResized", {
group = H.augroup,
callback = function()
local sidebar = M.get()
if not sidebar then return end
if not sidebar:is_open() then return end
sidebar:resize()
end,
})
api.nvim_create_autocmd("TabClosed", {
group = H.augroup,
pattern = "*",
callback = function(ev)
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
end,
})
vim.schedule(function()
M._init(api.nvim_get_current_tabpage())
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,
})
api.nvim_create_autocmd("ColorScheme", {
group = H.augroup,
callback = function() require("avante.highlights").setup() end,
})
-- automatically setup Avante filetype to markdown
vim.treesitter.language.register("markdown", "Avante")
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.
---@return avante.Sidebar, avante.Selection, avante.Suggestion
function M.get(current)
local tab = api.nvim_get_current_tabpage()
local sidebar = M.sidebars[tab]
local selection = M.selections[tab]
local suggestion = M.suggestions[tab]
if current ~= false then
M.current.sidebar = sidebar
M.current.selection = selection
M.current.suggestion = suggestion
end
return sidebar, selection, suggestion
end
---@param id integer
function M._init(id)
local sidebar = M.sidebars[id]
local selection = M.selections[id]
local suggestion = M.suggestions[id]
if not sidebar then
sidebar = Sidebar:new(id)
M.sidebars[id] = sidebar
end
if not selection then
selection = Selection:new(id)
M.selections[id] = selection
end
if not suggestion then
suggestion = Suggestion:new(id)
M.suggestions[id] = suggestion
end
M.current = { sidebar = sidebar, selection = selection, suggestion = suggestion }
return M
end
M.toggle = { api = true }
---@param opts? AskOptions
M.toggle_sidebar = function(opts)
opts = opts or {}
if opts.ask == nil then opts.ask = true end
local sidebar = M.get()
if not sidebar then
M._init(api.nvim_get_current_tabpage())
---@cast opts SidebarOpenOptions
M.current.sidebar:open(opts)
return true
end
return sidebar:toggle(opts)
end
M.is_sidebar_open = function()
local sidebar = M.get()
if not sidebar then return false end
return sidebar:is_open()
end
---@param opts? AskOptions
M.open_sidebar = function(opts)
opts = opts or {}
if opts.ask == nil then opts.ask = true end
local sidebar = M.get()
if not sidebar then M._init(api.nvim_get_current_tabpage()) end
---@cast opts SidebarOpenOptions
M.current.sidebar:open(opts)
end
M.close_sidebar = function()
local sidebar = M.get()
if not sidebar then return end
sidebar:close()
end
M.toggle.debug = H.api(Utils.toggle_wrap({
name = "debug",
get = function() return Config.debug end,
set = function(state) Config.override({ debug = state }) end,
}))
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,
}))
M.toggle.suggestion = H.api(Utils.toggle_wrap({
name = "suggestion",
get = function() return Config.behaviour.auto_suggestions end,
set = function(state)
Config.override({ behaviour = { auto_suggestions = state } })
local _, _, sg = M.get()
if state ~= false then
if sg then sg:setup_autocmds() end
H.keymaps()
else
if sg then sg:delete_autocmds() end
end
end,
}))
setmetatable(M.toggle, {
__index = M.toggle,
__call = function() M.toggle_sidebar() end,
})
---@param opts? avante.Config
function M.setup(opts)
---PERF: we can still allow running require("avante").setup() multiple times to override config if users wish to
---but most of the other functionality will only be called once from lazy.nvim
Config.setup(opts)
if M.did_setup then return end
H.load_path()
require("avante.html2md").setup()
require("avante.repo_map").setup()
require("avante.path").setup()
require("avante.highlights").setup()
require("avante.diff").setup()
require("avante.providers").setup()
require("avante.clipboard").setup()
-- setup helpers
H.autocmds()
H.keymaps()
H.signs()
M.did_setup = true
local function run_rag_service()
local started_at = os.time()
local add_resource_with_delay
local function add_resource()
local is_ready = RagService.is_ready()
if not is_ready then
local elapsed = os.time() - started_at
if elapsed > 1000 * 60 * 15 then
Utils.warn("Rag Service is not ready, giving up")
return
end
add_resource_with_delay()
return
end
vim.defer_fn(function()
Utils.info("Adding project root to Rag Service ...")
local uri = "file://" .. Utils.get_project_root()
if uri:sub(-1) ~= "/" then uri = uri .. "/" end
RagService.add_resource(uri)
Utils.info("Added project root to Rag Service")
end, 5000)
end
add_resource_with_delay = function()
vim.defer_fn(function() add_resource() end, 5000)
end
vim.schedule(function()
Utils.info("Starting Rag Service ...")
RagService.launch_rag_service(add_resource_with_delay)
end)
end
if Config.rag_service.enabled then run_rag_service() end
end
return M

View File

@@ -21,7 +21,7 @@ local group = api.nvim_create_augroup("avante_llm", { clear = true })
---@param opts AvanteGeneratePromptsOptions ---@param opts AvanteGeneratePromptsOptions
---@return AvantePromptOptions ---@return AvantePromptOptions
M.generate_prompts = function(opts) function M.generate_prompts(opts)
local provider = opts.provider or Providers[Config.provider] local provider = opts.provider or Providers[Config.provider]
local mode = opts.mode or "planning" local mode = opts.mode or "planning"
---@type AvanteProviderFunctor | AvanteBedrockProviderFunctor ---@type AvanteProviderFunctor | AvanteBedrockProviderFunctor
@@ -141,7 +141,7 @@ end
---@param opts AvanteGeneratePromptsOptions ---@param opts AvanteGeneratePromptsOptions
---@return integer ---@return integer
M.calculate_tokens = function(opts) function M.calculate_tokens(opts)
local prompt_opts = M.generate_prompts(opts) local prompt_opts = M.generate_prompts(opts)
local tokens = Utils.tokens.calculate_tokens(prompt_opts.system_prompt) local tokens = Utils.tokens.calculate_tokens(prompt_opts.system_prompt)
for _, message in ipairs(prompt_opts.messages) do for _, message in ipairs(prompt_opts.messages) do
@@ -151,7 +151,7 @@ M.calculate_tokens = function(opts)
end end
---@param opts AvanteLLMStreamOptions ---@param opts AvanteLLMStreamOptions
M._stream = function(opts) function M._stream(opts)
local provider = opts.provider or Providers[Config.provider] local provider = opts.provider or Providers[Config.provider]
local prompt_opts = M.generate_prompts(opts) local prompt_opts = M.generate_prompts(opts)
@@ -353,7 +353,7 @@ local function _collector_add_response(collector, index, response, opts)
end end
end end
M._dual_boost_stream = function(opts, Provider1, Provider2) function M._dual_boost_stream(opts, Provider1, Provider2)
Utils.debug("Starting Dual Boost Stream") Utils.debug("Starting Dual Boost Stream")
local collector = { local collector = {
@@ -408,7 +408,7 @@ M._dual_boost_stream = function(opts, Provider1, Provider2)
end end
---@param opts AvanteLLMStreamOptions ---@param opts AvanteLLMStreamOptions
M.stream = function(opts) function M.stream(opts)
local is_completed = false local is_completed = false
if opts.on_tool_log ~= nil then if opts.on_tool_log ~= nil then
local original_on_tool_log = opts.on_tool_log local original_on_tool_log = opts.on_tool_log

View File

@@ -30,7 +30,7 @@ local History = {}
-- Get a chat history file name given a buffer -- Get a chat history file name given a buffer
---@param bufnr integer ---@param bufnr integer
---@return string ---@return string
History.filename = function(bufnr) function History.filename(bufnr)
local project_root = Utils.root.get({ local project_root = Utils.root.get({
buf = bufnr, buf = bufnr,
}) })
@@ -43,12 +43,12 @@ end
-- Returns the Path to the chat history file for the given buffer. -- Returns the Path to the chat history file for the given buffer.
---@param bufnr integer ---@param bufnr integer
---@return Path ---@return Path
History.get = function(bufnr) return Path:new(Config.history.storage_path):joinpath(History.filename(bufnr)) end function History.get(bufnr) return Path:new(Config.history.storage_path):joinpath(History.filename(bufnr)) end
-- Loads the chat history for the given buffer. -- Loads the chat history for the given buffer.
---@param bufnr integer ---@param bufnr integer
---@return avante.ChatHistoryEntry[] ---@return avante.ChatHistoryEntry[]
History.load = function(bufnr) function History.load(bufnr)
local history_file = History.get(bufnr) local history_file = History.get(bufnr)
local cached_key = tostring(history_file:absolute()) local cached_key = tostring(history_file:absolute())
local cached_value = history_file_cache:get(cached_key) local cached_value = history_file_cache:get(cached_key)
@@ -79,7 +79,7 @@ local Prompt = {}
-- Given a mode, return the file name for the custom prompt. -- Given a mode, return the file name for the custom prompt.
---@param mode AvanteLlmMode ---@param mode AvanteLlmMode
Prompt.get_mode_file = function(mode) return string.format("custom.%s.avanterules", mode) end function Prompt.get_mode_file(mode) return string.format("custom.%s.avanterules", mode) end
---@class AvanteTemplates ---@class AvanteTemplates
---@field initialize fun(directory: string): nil ---@field initialize fun(directory: string): nil
@@ -92,7 +92,7 @@ Prompt.templates = { planning = nil, editing = nil, suggesting = nil }
-- PERF: Hmm instead of copy to cache, we can also load in globals context, but it requires some work on bindings. (eh maybe?) -- PERF: Hmm instead of copy to cache, we can also load in globals context, but it requires some work on bindings. (eh maybe?)
---@param project_root string ---@param project_root string
---@return string the resulted cache_directory to be loaded with avante_templates ---@return string the resulted cache_directory to be loaded with avante_templates
Prompt.get = function(project_root) function Prompt.get(project_root)
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 -- get root directory of given bufnr
@@ -134,20 +134,20 @@ Prompt.get = function(project_root)
end end
---@param mode AvanteLlmMode ---@param mode AvanteLlmMode
Prompt.get_file = function(mode) function Prompt.get_file(mode)
if Prompt.templates[mode] ~= nil then return Prompt.get_mode_file(mode) end if Prompt.templates[mode] ~= nil then return Prompt.get_mode_file(mode) end
return string.format("%s.avanterules", mode) return string.format("%s.avanterules", mode)
end end
---@param path string ---@param path string
---@param opts AvanteTemplateOptions ---@param opts AvanteTemplateOptions
Prompt.render_file = function(path, opts) return templates.render(path, opts) end function Prompt.render_file(path, opts) return templates.render(path, opts) end
---@param mode AvanteLlmMode ---@param mode AvanteLlmMode
---@param opts AvanteTemplateOptions ---@param opts AvanteTemplateOptions
Prompt.render_mode = function(mode, opts) return templates.render(Prompt.get_file(mode), opts) end function Prompt.render_mode(mode, opts) return templates.render(Prompt.get_file(mode), opts) end
Prompt.initialize = function(directory) templates.initialize(directory) end function Prompt.initialize(directory) templates.initialize(directory) end
P.prompts = Prompt P.prompts = Prompt
@@ -157,21 +157,21 @@ local RepoMap = {}
---@param project_root string ---@param project_root string
---@param ext string ---@param ext string
---@return string ---@return string
RepoMap.filename = function(project_root, ext) function RepoMap.filename(project_root, ext)
-- Replace path separators with double underscores -- Replace path separators with double underscores
local path_with_separators = fn.substitute(project_root, "/", "__", "g") local path_with_separators = fn.substitute(project_root, "/", "__", "g")
-- Replace other non-alphanumeric characters with single underscores -- Replace other non-alphanumeric characters with single underscores
return fn.substitute(path_with_separators, "[^A-Za-z0-9._]", "_", "g") .. "." .. ext .. ".repo_map.json" return fn.substitute(path_with_separators, "[^A-Za-z0-9._]", "_", "g") .. "." .. ext .. ".repo_map.json"
end end
RepoMap.get = function(project_root, ext) return Path:new(P.data_path):joinpath(RepoMap.filename(project_root, ext)) end function RepoMap.get(project_root, ext) return Path:new(P.data_path):joinpath(RepoMap.filename(project_root, ext)) end
RepoMap.save = function(project_root, ext, data) function RepoMap.save(project_root, ext, data)
local file = RepoMap.get(project_root, ext) local file = RepoMap.get(project_root, ext)
file:write(vim.json.encode(data), "w") file:write(vim.json.encode(data), "w")
end end
RepoMap.load = function(project_root, ext) function RepoMap.load(project_root, ext)
local file = RepoMap.get(project_root, ext) local file = RepoMap.get(project_root, ext)
if file:exists() then if file:exists() then
local content = file:read() local content = file:read()
@@ -183,7 +183,7 @@ end
P.repo_map = RepoMap P.repo_map = RepoMap
---@return AvanteTemplates|nil ---@return AvanteTemplates|nil
P._init_templates_lib = function() function P._init_templates_lib()
if templates ~= nil then return templates end if templates ~= nil then return templates end
local ok, module = pcall(require, "avante_templates") local ok, module = pcall(require, "avante_templates")
---@cast module AvanteTemplates ---@cast module AvanteTemplates
@@ -194,7 +194,7 @@ P._init_templates_lib = function()
return templates return templates
end end
P.setup = function() function P.setup()
local history_path = Path:new(Config.history.storage_path) 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 P.history_path = history_path
@@ -210,9 +210,9 @@ P.setup = function()
vim.defer_fn(P._init_templates_lib, 1000) vim.defer_fn(P._init_templates_lib, 1000)
end end
P.available = function() return P._init_templates_lib() ~= nil end function P.available() return P._init_templates_lib() ~= nil end
P.clear = function() function P.clear()
P.cache_path:rm({ recursive = true }) P.cache_path:rm({ recursive = true })
P.history_path:rm({ recursive = true }) P.history_path:rm({ recursive = true })

View File

@@ -17,7 +17,7 @@ M.parse_messages = O.parse_messages
M.parse_response = O.parse_response M.parse_response = O.parse_response
M.parse_response_without_stream = O.parse_response_without_stream M.parse_response_without_stream = O.parse_response_without_stream
M.parse_curl_args = function(provider, prompt_opts) function M.parse_curl_args(provider, prompt_opts)
local provider_conf, request_body = P.parse_config(provider) local provider_conf, request_body = P.parse_config(provider)
local headers = { local headers = {

View File

@@ -7,7 +7,7 @@ local M = {}
M.api_key_name = "BEDROCK_KEYS" M.api_key_name = "BEDROCK_KEYS"
M.use_xml_format = true M.use_xml_format = true
M.load_model_handler = function() function M.load_model_handler()
local provider_conf, _ = P.parse_config(P["bedrock"]) local provider_conf, _ = P.parse_config(P["bedrock"])
local bedrock_model = provider_conf.model local bedrock_model = provider_conf.model
if provider_conf.model:match("anthropic") then bedrock_model = "claude" end if provider_conf.model:match("anthropic") then bedrock_model = "claude" end
@@ -18,17 +18,17 @@ M.load_model_handler = function()
error(error_msg) error(error_msg)
end end
M.parse_response = function(ctx, data_stream, event_state, opts) function M.parse_response(ctx, data_stream, event_state, opts)
local model_handler = M.load_model_handler() local model_handler = M.load_model_handler()
return model_handler.parse_response(ctx, data_stream, event_state, opts) return model_handler.parse_response(ctx, data_stream, event_state, opts)
end end
M.build_bedrock_payload = function(prompt_opts, body_opts) function M.build_bedrock_payload(prompt_opts, body_opts)
local model_handler = M.load_model_handler() local model_handler = M.load_model_handler()
return model_handler.build_bedrock_payload(prompt_opts, body_opts) return model_handler.build_bedrock_payload(prompt_opts, body_opts)
end end
M.parse_stream_data = function(data, opts) function M.parse_stream_data(data, opts)
-- @NOTE: Decode and process Bedrock response -- @NOTE: Decode and process Bedrock response
-- Each response contains a Base64-encoded `bytes` field, which is decoded into JSON. -- Each response contains a Base64-encoded `bytes` field, which is decoded into JSON.
-- The `type` field in the decoded JSON determines how the response is handled. -- The `type` field in the decoded JSON determines how the response is handled.
@@ -44,7 +44,7 @@ end
---@param provider AvanteBedrockProviderFunctor ---@param provider AvanteBedrockProviderFunctor
---@param prompt_opts AvantePromptOptions ---@param prompt_opts AvantePromptOptions
---@return table ---@return table
M.parse_curl_args = function(provider, prompt_opts) function M.parse_curl_args(provider, prompt_opts)
local base, body_opts = P.parse_config(provider) local base, body_opts = P.parse_config(provider)
local api_key = provider.parse_api_key() local api_key = provider.parse_api_key()
@@ -86,7 +86,7 @@ M.parse_curl_args = function(provider, prompt_opts)
} }
end end
M.on_error = function(result) function M.on_error(result)
if not result.body then if not result.body then
return Utils.error("API request failed with status " .. result.status, { once = true, title = "Avante" }) return Utils.error("API request failed with status " .. result.status, { once = true, title = "Avante" })
end end

View File

@@ -16,7 +16,7 @@ M.role_map = {
assistant = "assistant", assistant = "assistant",
} }
M.parse_messages = function(opts) function M.parse_messages(opts)
---@type AvanteBedrockClaudeMessage[] ---@type AvanteBedrockClaudeMessage[]
local messages = {} local messages = {}
@@ -78,7 +78,7 @@ M.parse_response = Claude.parse_response
---@param prompt_opts AvantePromptOptions ---@param prompt_opts AvantePromptOptions
---@param body_opts table ---@param body_opts table
---@return table ---@return table
M.build_bedrock_payload = function(prompt_opts, body_opts) function M.build_bedrock_payload(prompt_opts, body_opts)
local system_prompt = prompt_opts.system_prompt or "" local system_prompt = prompt_opts.system_prompt or ""
local messages = M.parse_messages(prompt_opts) local messages = M.parse_messages(prompt_opts)
local max_tokens = body_opts.max_tokens or 2000 local max_tokens = body_opts.max_tokens or 2000

View File

@@ -36,7 +36,7 @@ M.role_map = {
assistant = "assistant", assistant = "assistant",
} }
M.parse_messages = function(opts) function M.parse_messages(opts)
---@type AvanteClaudeMessage[] ---@type AvanteClaudeMessage[]
local messages = {} local messages = {}
@@ -123,7 +123,7 @@ M.parse_messages = function(opts)
return messages return messages
end end
M.parse_response = function(ctx, data_stream, event_state, opts) function M.parse_response(ctx, data_stream, event_state, opts)
if event_state == nil then if event_state == nil then
if data_stream:match('"message_start"') then if data_stream:match('"message_start"') then
event_state = "message_start" event_state = "message_start"
@@ -214,7 +214,7 @@ end
---@param provider AvanteProviderFunctor ---@param provider AvanteProviderFunctor
---@param prompt_opts AvantePromptOptions ---@param prompt_opts AvantePromptOptions
---@return table ---@return table
M.parse_curl_args = function(provider, prompt_opts) function M.parse_curl_args(provider, prompt_opts)
local provider_conf, request_body = P.parse_config(provider) local provider_conf, request_body = P.parse_config(provider)
local disable_tools = provider_conf.disable_tools or false local disable_tools = provider_conf.disable_tools or false
@@ -256,7 +256,7 @@ M.parse_curl_args = function(provider, prompt_opts)
} }
end end
M.on_error = function(result) function M.on_error(result)
if not result.body then if not result.body then
return Utils.error("API request failed with status " .. result.status, { once = true, title = "Avante" }) return Utils.error("API request failed with status " .. result.status, { once = true, title = "Avante" })
end end

View File

@@ -47,7 +47,7 @@ M.role_map = {
assistant = "assistant", assistant = "assistant",
} }
M.parse_messages = function(opts) function M.parse_messages(opts)
local messages = { local messages = {
{ role = "system", content = opts.system_prompt }, { role = "system", content = opts.system_prompt },
} }
@@ -57,7 +57,7 @@ M.parse_messages = function(opts)
return { messages = messages } return { messages = messages }
end end
M.parse_stream_data = function(data, opts) function M.parse_stream_data(data, opts)
---@type CohereChatResponse ---@type CohereChatResponse
local json = vim.json.decode(data) local json = vim.json.decode(data)
if json.type ~= nil then if json.type ~= nil then
@@ -69,7 +69,7 @@ M.parse_stream_data = function(data, opts)
end end
end end
M.parse_curl_args = function(provider, prompt_opts) function M.parse_curl_args(provider, prompt_opts)
local provider_conf, request_body = P.parse_config(provider) local provider_conf, request_body = P.parse_config(provider)
local headers = { local headers = {
@@ -96,7 +96,7 @@ M.parse_curl_args = function(provider, prompt_opts)
} }
end end
M.setup = function() function M.setup()
P.env.parse_envvar(M) P.env.parse_envvar(M)
require("avante.tokenizers").setup(M.tokenizer_id, false) require("avante.tokenizers").setup(M.tokenizer_id, false)
vim.g.avante_login = true vim.g.avante_login = true

View File

@@ -98,7 +98,7 @@ end
---@field oauth_token string ---@field oauth_token string
--- ---
---@return string ---@return string
H.get_oauth_token = function() function H.get_oauth_token()
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() local os_name = Utils.get_os_name()
---@type string ---@type string
@@ -138,9 +138,9 @@ H.get_oauth_token = function()
end end
H.chat_auth_url = "https://api.github.com/copilot_internal/v2/token" H.chat_auth_url = "https://api.github.com/copilot_internal/v2/token"
H.chat_completion_url = function(base_url) return Utils.url_join(base_url, "/chat/completions") end function H.chat_completion_url(base_url) return Utils.url_join(base_url, "/chat/completions") end
H.refresh_token = function(async, force) function H.refresh_token(async, force)
if not M.state then error("internal initialization error") end if not M.state then error("internal initialization error") end
async = async == nil and true or async async = async == nil and true or async
@@ -166,7 +166,7 @@ H.refresh_token = function(async, force)
insecure = Config.copilot.allow_insecure, insecure = Config.copilot.allow_insecure,
} }
local handle_response = function(response) local function handle_response(response)
if response.status == 200 then if response.status == 200 then
M.state.github_token = vim.json.decode(response.body) M.state.github_token = vim.json.decode(response.body)
local file = Path:new(copilot_path) local file = Path:new(copilot_path)
@@ -209,7 +209,7 @@ M.role_map = {
assistant = "assistant", assistant = "assistant",
} }
M.parse_messages = function(opts) function M.parse_messages(opts)
local messages = { local messages = {
{ role = "system", content = opts.system_prompt }, { role = "system", content = opts.system_prompt },
} }
@@ -245,7 +245,7 @@ end
M.parse_response = OpenAI.parse_response M.parse_response = OpenAI.parse_response
M.parse_curl_args = function(provider, prompt_opts) function M.parse_curl_args(provider, prompt_opts)
-- refresh token synchronously, only if it has expired -- refresh token synchronously, only if it has expired
-- (this should rarely happen, as we refresh the token in the background) -- (this should rarely happen, as we refresh the token in the background)
H.refresh_token(false, false) H.refresh_token(false, false)
@@ -282,7 +282,7 @@ end
M._refresh_timer = nil M._refresh_timer = nil
M.setup_timer = function() function M.setup_timer()
if M._refresh_timer then if M._refresh_timer then
M._refresh_timer:stop() M._refresh_timer:stop()
M._refresh_timer:close() M._refresh_timer:close()
@@ -305,7 +305,7 @@ M.setup_timer = function()
) )
end end
M.setup_file_watcher = function() function M.setup_file_watcher()
if M._file_watcher then return end if M._file_watcher then return end
local copilot_token_file = Path:new(copilot_path) local copilot_token_file = Path:new(copilot_path)
@@ -321,7 +321,7 @@ M.setup_file_watcher = function()
) )
end end
M.setup = function() function M.setup()
local copilot_token_file = Path:new(copilot_path) local copilot_token_file = Path:new(copilot_path)
if not M.state then M.state = { if not M.state then M.state = {
@@ -351,7 +351,7 @@ M.setup = function()
vim.g.avante_login = true vim.g.avante_login = true
end end
M.cleanup = function() function M.cleanup()
-- Cleanup refresh timer -- Cleanup refresh timer
if M._refresh_timer then if M._refresh_timer then
M._refresh_timer:stop() M._refresh_timer:stop()

View File

@@ -12,7 +12,7 @@ M.role_map = {
} }
-- M.tokenizer_id = "google/gemma-2b" -- M.tokenizer_id = "google/gemma-2b"
M.parse_messages = function(opts) function M.parse_messages(opts)
local contents = {} local contents = {}
local prev_role = nil local prev_role = nil
@@ -64,7 +64,7 @@ M.parse_messages = function(opts)
} }
end end
M.parse_response = function(ctx, data_stream, _, opts) function M.parse_response(ctx, data_stream, _, opts)
local ok, json = pcall(vim.json.decode, data_stream) local ok, json = pcall(vim.json.decode, data_stream)
if not ok then opts.on_stop({ reason = "error", error = json }) end if not ok then opts.on_stop({ reason = "error", error = json }) end
if json.candidates then if json.candidates then
@@ -81,7 +81,7 @@ M.parse_response = function(ctx, data_stream, _, opts)
end end
end end
M.parse_curl_args = function(provider, prompt_opts) function M.parse_curl_args(provider, prompt_opts)
local provider_conf, request_body = P.parse_config(provider) local provider_conf, request_body = P.parse_config(provider)
request_body = vim.tbl_deep_extend("force", request_body, { request_body = vim.tbl_deep_extend("force", request_body, {

View File

@@ -29,7 +29,7 @@ E.cache = {}
---@param Opts AvanteSupportedProvider | AvanteProviderFunctor | AvanteBedrockProviderFunctor ---@param Opts AvanteSupportedProvider | AvanteProviderFunctor | AvanteBedrockProviderFunctor
---@return string | nil ---@return string | nil
E.parse_envvar = function(Opts) function E.parse_envvar(Opts)
local api_key_name = Opts.api_key_name 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
@@ -91,7 +91,7 @@ end
--- This will only run once and spawn a UI for users to input the envvar. --- This will only run once and spawn a UI for users to input the envvar.
---@param opts {refresh: boolean, provider: AvanteProviderFunctor | AvanteBedrockProviderFunctor} ---@param opts {refresh: boolean, provider: AvanteProviderFunctor | AvanteBedrockProviderFunctor}
---@private ---@private
E.setup = function(opts) function E.setup(opts)
opts.provider.setup() opts.provider.setup()
local var = opts.provider.api_key_name local var = opts.provider.api_key_name
@@ -180,7 +180,7 @@ end
E.REQUEST_LOGIN_PATTERN = "AvanteRequestLogin" E.REQUEST_LOGIN_PATTERN = "AvanteRequestLogin"
---@param provider AvanteDefaultBaseProvider ---@param provider AvanteDefaultBaseProvider
E.require_api_key = function(provider) function E.require_api_key(provider)
if provider["local"] ~= nil then if provider["local"] ~= nil then
if provider["local"] then if provider["local"] then
vim.deprecate('"local" = true', "api_key_name = ''", "0.1.0", "avante.nvim") vim.deprecate('"local" = true', "api_key_name = ''", "0.1.0", "avante.nvim")
@@ -239,7 +239,7 @@ M = setmetatable(M, {
end, end,
}) })
M.setup = function() function M.setup()
vim.g.avante_login = false vim.g.avante_login = false
---@type AvanteProviderFunctor | AvanteBedrockProviderFunctor ---@type AvanteProviderFunctor | AvanteBedrockProviderFunctor
@@ -274,7 +274,7 @@ end
---@param opts AvanteProvider | AvanteSupportedProvider | AvanteProviderFunctor | AvanteBedrockProviderFunctor ---@param opts AvanteProvider | AvanteSupportedProvider | AvanteProviderFunctor | AvanteBedrockProviderFunctor
---@return AvanteDefaultBaseProvider provider_opts ---@return AvanteDefaultBaseProvider provider_opts
---@return table<string, any> request_body ---@return table<string, any> request_body
M.parse_config = function(opts) function M.parse_config(opts)
---@type AvanteDefaultBaseProvider ---@type AvanteDefaultBaseProvider
local provider_opts = {} local provider_opts = {}
---@type table<string, any> ---@type table<string, any>
@@ -302,7 +302,7 @@ end
---@private ---@private
---@param provider Provider ---@param provider Provider
---@return AvanteProviderFunctor | AvanteBedrockProviderFunctor ---@return AvanteProviderFunctor | AvanteBedrockProviderFunctor
M.get_config = function(provider) function M.get_config(provider)
provider = provider or Config.provider provider = provider or Config.provider
local cur = Config.get_provider(provider) local cur = Config.get_provider(provider)
return type(cur) == "function" and cur() or cur return type(cur) == "function" and cur() or cur

View File

@@ -43,10 +43,10 @@ function M.transform_tool(tool)
return res return res
end end
M.is_openrouter = function(url) return url:match("^https://openrouter%.ai/") end function M.is_openrouter(url) return url:match("^https://openrouter%.ai/") end
---@param opts AvantePromptOptions ---@param opts AvantePromptOptions
M.get_user_message = function(opts) function M.get_user_message(opts)
vim.deprecate("get_user_message", "parse_messages", "0.1.0", "avante.nvim") vim.deprecate("get_user_message", "parse_messages", "0.1.0", "avante.nvim")
return table.concat( return table.concat(
vim vim
@@ -61,9 +61,9 @@ M.get_user_message = function(opts)
) )
end end
M.is_o_series_model = function(model) return model and string.match(model, "^o%d+") ~= nil end function M.is_o_series_model(model) return model and string.match(model, "^o%d+") ~= nil end
M.parse_messages = function(opts) function M.parse_messages(opts)
local messages = {} local messages = {}
local provider = P[Config.provider] local provider = P[Config.provider]
local base, _ = P.parse_config(provider) local base, _ = P.parse_config(provider)
@@ -137,7 +137,7 @@ M.parse_messages = function(opts)
return final_messages return final_messages
end end
M.parse_response = function(ctx, data_stream, _, opts) function M.parse_response(ctx, data_stream, _, opts)
if data_stream:match('"%[DONE%]":') then if data_stream:match('"%[DONE%]":') then
opts.on_stop({ reason = "complete" }) opts.on_stop({ reason = "complete" })
return return
@@ -205,7 +205,7 @@ M.parse_response = function(ctx, data_stream, _, opts)
end end
end end
M.parse_response_without_stream = function(data, _, opts) function M.parse_response_without_stream(data, _, opts)
---@type AvanteOpenAIChatResponse ---@type AvanteOpenAIChatResponse
local json = vim.json.decode(data) local json = vim.json.decode(data)
if json.choices and json.choices[1] then if json.choices and json.choices[1] then
@@ -217,7 +217,7 @@ M.parse_response_without_stream = function(data, _, opts)
end end
end end
M.parse_curl_args = function(provider, prompt_opts) function M.parse_curl_args(provider, prompt_opts)
local provider_conf, request_body = P.parse_config(provider) local provider_conf, request_body = P.parse_config(provider)
local disable_tools = provider_conf.disable_tools or false local disable_tools = provider_conf.disable_tools or false

View File

@@ -22,7 +22,7 @@ local function execute_command(command)
return result:match("^%s*(.-)%s*$") return result:match("^%s*(.-)%s*$")
end end
M.parse_api_key = function() function M.parse_api_key()
if not M.api_key_name:match("^cmd:") then if not M.api_key_name:match("^cmd:") then
error("Invalid api_key_name: Expected 'cmd:<command>' format, got '" .. M.api_key_name .. "'") error("Invalid api_key_name: Expected 'cmd:<command>' format, got '" .. M.api_key_name .. "'")
end end
@@ -31,7 +31,7 @@ M.parse_api_key = function()
return direct_output return direct_output
end end
M.parse_curl_args = function(provider, prompt_opts) function M.parse_curl_args(provider, prompt_opts)
local provider_conf, request_body = P.parse_config(provider) local provider_conf, request_body = P.parse_config(provider)
local location = vim.fn.getenv("LOCATION") or "default-location" local location = vim.fn.getenv("LOCATION") or "default-location"
local project_id = vim.fn.getenv("PROJECT_ID") or "default-project-id" local project_id = vim.fn.getenv("PROJECT_ID") or "default-project-id"

View File

@@ -289,7 +289,7 @@ end
---@field total_count number ---@field total_count number
---@return AvanteRagServiceResourceListResponse | nil ---@return AvanteRagServiceResourceListResponse | nil
M.get_resources = function() function M.get_resources()
local resp = curl.get(M.get_rag_service_url() .. "/api/v1/resources", { local resp = curl.get(M.get_rag_service_url() .. "/api/v1/resources", {
headers = { headers = {
["Content-Type"] = "application/json", ["Content-Type"] = "application/json",

View File

@@ -146,7 +146,7 @@ function Selection:create_editing_input()
priority = PRIORITY, priority = PRIORITY,
}) })
local submit_input = function(input) local function submit_input(input)
local full_response = "" local full_response = ""
local start_line = self.selection.range.start.lnum local start_line = self.selection.range.start.lnum
local finish_line = self.selection.range.finish.lnum local finish_line = self.selection.range.finish.lnum
@@ -158,10 +158,10 @@ function Selection:create_editing_input()
self.prompt_input:start_spinner() self.prompt_input:start_spinner()
---@type AvanteLLMStartCallback ---@type AvanteLLMStartCallback
local on_start = function(start_opts) end local function on_start(start_opts) end
---@type AvanteLLMChunkCallback ---@type AvanteLLMChunkCallback
local on_chunk = function(chunk) local function on_chunk(chunk)
full_response = full_response .. chunk full_response = full_response .. chunk
local response_lines_ = vim.split(full_response, "\n") local response_lines_ = vim.split(full_response, "\n")
local response_lines = {} local response_lines = {}
@@ -186,7 +186,7 @@ function Selection:create_editing_input()
end end
---@type AvanteLLMStopCallback ---@type AvanteLLMStopCallback
local on_stop = function(stop_opts) local function on_stop(stop_opts)
if stop_opts.error then if stop_opts.error then
-- NOTE: in Ubuntu 22.04+ you will see this ignorable error from ~/.local/share/nvim/lazy/avante.nvim/lua/avante/llm.lua `on_error = function(err)`, check to avoid showing this error. -- NOTE: in Ubuntu 22.04+ you will see this ignorable error from ~/.local/share/nvim/lazy/avante.nvim/lua/avante/llm.lua `on_error = function(err)`, check to avoid showing this error.
if type(stop_opts.error) == "table" and stop_opts.error.exit == nil and stop_opts.error.stderr == "{}" then if type(stop_opts.error) == "table" and stop_opts.error.exit == nil and stop_opts.error.stderr == "{}" then

View File

@@ -1275,7 +1275,7 @@ function Sidebar:apply(current_cursor)
api.nvim_buf_set_lines(bufnr, 0, -1, false, new_lines) api.nvim_buf_set_lines(bufnr, 0, -1, false, new_lines)
local process = function(winid) local function process(winid)
api.nvim_set_current_win(winid) api.nvim_set_current_win(winid)
api.nvim_feedkeys(api.nvim_replace_termcodes("<Esc>", true, false, true), "n", true) api.nvim_feedkeys(api.nvim_replace_termcodes("<Esc>", true, false, true), "n", true)
Diff.add_visited_buffer(bufnr) Diff.add_visited_buffer(bufnr)
@@ -1314,7 +1314,7 @@ function Sidebar:apply(current_cursor)
local path_ = PPath:new(filepath) local path_ = PPath:new(filepath)
path_:parent():mkdir({ parents = true, exists_ok = true }) path_:parent():mkdir({ parents = true, exists_ok = true })
insert_conflict_contents(bufnr, snippets) insert_conflict_contents(bufnr, snippets)
local process = function(winid) local function process(winid)
api.nvim_set_current_win(winid) api.nvim_set_current_win(winid)
api.nvim_feedkeys(api.nvim_replace_termcodes("<Esc>", true, false, true), "n", true) api.nvim_feedkeys(api.nvim_replace_termcodes("<Esc>", true, false, true), "n", true)
Diff.add_visited_buffer(bufnr) Diff.add_visited_buffer(bufnr)
@@ -1947,7 +1947,7 @@ function Sidebar:update_content(content, opts)
content = self:render_history_content(chat_history) .. "-------\n\n" .. content content = self:render_history_content(chat_history) .. "-------\n\n" .. content
end end
if opts.stream then if opts.stream then
local scroll_to_bottom = function() local function scroll_to_bottom()
local last_line = api.nvim_buf_line_count(self.result_container.bufnr) local last_line = api.nvim_buf_line_count(self.result_container.bufnr)
local current_lines = Utils.get_buf_lines(last_line - 1, last_line, self.result_container.bufnr) local current_lines = Utils.get_buf_lines(last_line - 1, last_line, self.result_container.bufnr)
@@ -2480,10 +2480,10 @@ function Sidebar:create_input_container(opts)
vim.keymap.set("n", "G", on_G, { buffer = self.result_container.bufnr }) vim.keymap.set("n", "G", on_G, { buffer = self.result_container.bufnr })
---@type AvanteLLMStartCallback ---@type AvanteLLMStartCallback
local on_start = function(_) end local function on_start(_) end
---@type AvanteLLMChunkCallback ---@type AvanteLLMChunkCallback
local on_chunk = function(chunk) local function on_chunk(chunk)
self.is_generating = true self.is_generating = true
original_response = original_response .. chunk original_response = original_response .. chunk
@@ -2507,7 +2507,7 @@ function Sidebar:create_input_container(opts)
displayed_response = cur_displayed_response displayed_response = cur_displayed_response
end end
local on_tool_log = function(tool_name, log) local function on_tool_log(tool_name, log)
if transformed_response:sub(-1) ~= "\n" then transformed_response = transformed_response .. "\n" end if transformed_response:sub(-1) ~= "\n" then transformed_response = transformed_response .. "\n" end
transformed_response = transformed_response .. "[" .. tool_name .. "]: " .. log .. "\n" transformed_response = transformed_response .. "[" .. tool_name .. "]: " .. log .. "\n"
local breakline = "" local breakline = ""
@@ -2519,7 +2519,7 @@ function Sidebar:create_input_container(opts)
end end
---@type AvanteLLMStopCallback ---@type AvanteLLMStopCallback
local on_stop = function(stop_opts) local function on_stop(stop_opts)
self.is_generating = false self.is_generating = false
pcall(function() pcall(function()
@@ -2586,12 +2586,12 @@ function Sidebar:create_input_container(opts)
Llm.stream(stream_options) Llm.stream(stream_options)
end end
local get_position = function() local function get_position()
if self:get_layout() == "vertical" then return "bottom" end if self:get_layout() == "vertical" then return "bottom" end
return "right" return "right"
end end
local get_size = function() local function get_size()
if self:get_layout() == "vertical" then return { if self:get_layout() == "vertical" then return {
height = Config.windows.input.height, height = Config.windows.input.height,
} end } end
@@ -2881,7 +2881,7 @@ end
function Sidebar:render(opts) function Sidebar:render(opts)
local chat_history = Path.history.load(self.code.bufnr) local chat_history = Path.history.load(self.code.bufnr)
local get_position = function() local function get_position()
return (opts and opts.win and opts.win.position) and opts.win.position or calculate_config_window_position() return (opts and opts.win and opts.win.position) and opts.win.position or calculate_config_window_position()
end end
@@ -2988,7 +2988,7 @@ function Sidebar:create_selected_files_container()
self.selected_files_container:mount() self.selected_files_container:mount()
local render = function() local function render()
local selected_filepaths_ = self.file_selector:get_selected_filepaths() local selected_filepaths_ = self.file_selector:get_selected_filepaths()
if #selected_filepaths_ == 0 then if #selected_filepaths_ == 0 then
@@ -3020,7 +3020,7 @@ function Sidebar:create_selected_files_container()
self.file_selector:on("update", render) self.file_selector:on("update", render)
local remove_file = function(line_number) self.file_selector:remove_selected_filepaths_with_index(line_number) end local function remove_file(line_number) self.file_selector:remove_selected_filepaths_with_index(line_number) end
-- Function to show hint -- Function to show hint
local function show_hint() local function show_hint()

View File

@@ -12,7 +12,7 @@ local M = {}
---@param model "gpt-4o" | string ---@param model "gpt-4o" | string
---@return AvanteTokenizer|nil ---@return AvanteTokenizer|nil
M._init_tokenizers_lib = function(model) function M._init_tokenizers_lib(model)
if tokenizers ~= nil then return tokenizers end if tokenizers ~= nil then return tokenizers end
local ok, core = pcall(require, "avante_tokenizers") local ok, core = pcall(require, "avante_tokenizers")
@@ -28,7 +28,7 @@ end
---@param model "gpt-4o" | string ---@param model "gpt-4o" | string
---@param warning? boolean ---@param warning? boolean
M.setup = function(model, warning) function M.setup(model, warning)
current_model = model current_model = model
warning = warning or true warning = warning or true
vim.defer_fn(function() M._init_tokenizers_lib(model) end, 1000) vim.defer_fn(function() M._init_tokenizers_lib(model) end, 1000)
@@ -44,10 +44,10 @@ M.setup = function(model, warning)
end end
end end
M.available = function() return M._init_tokenizers_lib(current_model) ~= nil end function M.available() return M._init_tokenizers_lib(current_model) ~= nil end
---@param prompt string ---@param prompt string
M.encode = function(prompt) function M.encode(prompt)
if not M.available() then return nil end if not M.available() then return nil end
if not prompt or prompt == "" 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 type(prompt) ~= "string" then error("Prompt is not type string", 2) end
@@ -56,7 +56,7 @@ M.encode = function(prompt)
end end
---@param prompt string ---@param prompt string
M.count = function(prompt) function M.count(prompt)
if not M.available() then return math.ceil(#prompt * 0.5) end if not M.available() then return math.ceil(#prompt * 0.5) end
local tokens = M.encode(prompt) local tokens = M.encode(prompt)

View File

@@ -24,16 +24,16 @@ setmetatable(M, {
---Check if a plugin is installed ---Check if a plugin is installed
---@param plugin string ---@param plugin string
---@return boolean ---@return boolean
M.has = function(plugin) function M.has(plugin)
local ok, LazyConfig = pcall(require, "lazy.core.config") 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 return package.loaded[plugin] ~= nil
end end
M.is_win = function() return jit.os:find("Windows") ~= nil end function M.is_win() return jit.os:find("Windows") ~= nil end
---@return "linux" | "darwin" | "windows" ---@return "linux" | "darwin" | "windows"
M.get_os_name = function() function M.get_os_name()
local os_name = vim.uv.os_uname().sysname local os_name = vim.uv.os_uname().sysname
if os_name == "Linux" then if os_name == "Linux" then
return "linux" return "linux"
@@ -46,7 +46,7 @@ M.get_os_name = function()
end end
end end
M.get_system_info = function() function M.get_system_info()
local os_name = vim.loop.os_uname().sysname local os_name = vim.loop.os_uname().sysname
local os_version = vim.loop.os_uname().release local os_version = vim.loop.os_uname().release
local os_machine = vim.loop.os_uname().machine local os_machine = vim.loop.os_uname().machine
@@ -75,7 +75,7 @@ end
---@param input_cmd string ---@param input_cmd string
---@param shell_cmd string? ---@param shell_cmd string?
---@return vim.SystemCompleted ---@return vim.SystemCompleted
M.shell_run = function(input_cmd, shell_cmd) function M.shell_run(input_cmd, shell_cmd)
local shell = vim.o.shell:lower() local shell = vim.o.shell:lower()
---@type string ---@type string
local cmd local cmd
@@ -114,7 +114,7 @@ end
---@operator call:boolean ---@operator call:boolean
---@param toggle ToggleBind ---@param toggle ToggleBind
M.toggle_wrap = function(toggle) function M.toggle_wrap(toggle)
return setmetatable(toggle, { return setmetatable(toggle, {
__call = function() __call = function()
toggle.set(not toggle.get()) toggle.set(not toggle.get())
@@ -139,7 +139,7 @@ end
---@param rhs string|function Right-hand side |{rhs}| of the mapping, can be a Lua function. ---@param rhs string|function Right-hand side |{rhs}| of the mapping, can be a Lua function.
--- ---
---@param opts? vim.keymap.set.Opts ---@param opts? vim.keymap.set.Opts
M.safe_keymap_set = function(mode, lhs, rhs, opts) function M.safe_keymap_set(mode, lhs, rhs, opts)
---@type boolean ---@type boolean
local ok local ok
---@module "lazy.core.handler" ---@module "lazy.core.handler"
@@ -273,7 +273,7 @@ M.lsp = {}
---@param opts? vim.lsp.Client.filter ---@param opts? vim.lsp.Client.filter
---@return vim.lsp.Client[] ---@return vim.lsp.Client[]
M.lsp.get_clients = function(opts) function M.lsp.get_clients(opts)
---@type vim.lsp.Client[] ---@type vim.lsp.Client[]
local ret = vim.lsp.get_clients(opts) local ret = vim.lsp.get_clients(opts)
return (opts and opts.filter) and vim.tbl_filter(opts.filter, ret) or ret return (opts and opts.filter) and vim.tbl_filter(opts.filter, ret) or ret
@@ -412,7 +412,7 @@ end
---@param winnr? number ---@param winnr? number
---@return nil ---@return nil
M.scroll_to_end = function(winnr) function M.scroll_to_end(winnr)
winnr = winnr or 0 winnr = winnr or 0
local bufnr = api.nvim_win_get_buf(winnr) local bufnr = api.nvim_win_get_buf(winnr)
local lnum = api.nvim_buf_line_count(bufnr) local lnum = api.nvim_buf_line_count(bufnr)
@@ -422,7 +422,7 @@ end
---@param bufnr nil|integer ---@param bufnr nil|integer
---@return nil ---@return nil
M.buf_scroll_to_end = function(bufnr) function M.buf_scroll_to_end(bufnr)
for _, winnr in ipairs(M.buf_list_wins(bufnr or 0)) do for _, winnr in ipairs(M.buf_list_wins(bufnr or 0)) do
M.scroll_to_end(winnr) M.scroll_to_end(winnr)
end end
@@ -430,7 +430,7 @@ end
---@param bufnr nil|integer ---@param bufnr nil|integer
---@return integer[] ---@return integer[]
M.buf_list_wins = function(bufnr) function M.buf_list_wins(bufnr)
local wins = {} 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
@@ -954,7 +954,7 @@ end
---Check if an icon plugin is installed ---Check if an icon plugin is installed
---@return boolean ---@return boolean
M.icons_enabled = function() return M.has("nvim-web-devicons") or M.has("mini.icons") or M.has("mini.nvim") end function M.icons_enabled() return M.has("nvim-web-devicons") or M.has("mini.icons") or M.has("mini.nvim") end
---Display an string with icon, if an icon plugin is available. ---Display an string with icon, if an icon plugin is available.
---Dev icons are an optional install for avante, this function prevents ugly chars ---Dev icons are an optional install for avante, this function prevents ugly chars
@@ -962,7 +962,7 @@ M.icons_enabled = function() return M.has("nvim-web-devicons") or M.has("mini.ic
---@param string_with_icon string ---@param string_with_icon string
---@param utf8_fallback string|nil ---@param utf8_fallback string|nil
---@return string ---@return string
M.icon = function(string_with_icon, utf8_fallback) function M.icon(string_with_icon, utf8_fallback)
if M.icons_enabled() then if M.icons_enabled() then
return string_with_icon return string_with_icon
else else

View File

@@ -8,9 +8,9 @@ local function get_library_path()
end end
---@type fun(s: string): string ---@type fun(s: string): string
local trim_semicolon = function(s) return s:sub(-1) == ";" and s:sub(1, -2) or s end local function trim_semicolon(s) return s:sub(-1) == ";" and s:sub(1, -2) or s end
M.load = function() function M.load()
local library_path = get_library_path() local library_path = get_library_path()
if not string.find(package.cpath, library_path, 1, true) then if not string.find(package.cpath, library_path, 1, true) then
package.cpath = trim_semicolon(package.cpath) .. ";" .. library_path package.cpath = trim_semicolon(package.cpath) .. ";" .. library_path

View File

@@ -19,7 +19,7 @@ end
function commands_source:is_available() return api.nvim_get_current_buf() == self.bufnr end function commands_source:is_available() return api.nvim_get_current_buf() == self.bufnr end
commands_source.get_position_encoding_kind = function() return "utf-8" end function commands_source.get_position_encoding_kind() return "utf-8" end
function commands_source:get_trigger_characters() return { "/" } end function commands_source:get_trigger_characters() return { "/" } end

View File

@@ -19,7 +19,7 @@ end
function mentions_source:is_available() return api.nvim_get_current_buf() == self.bufnr end function mentions_source:is_available() return api.nvim_get_current_buf() == self.bufnr end
mentions_source.get_position_encoding_kind = function() return "utf-8" end function mentions_source.get_position_encoding_kind() return "utf-8" end
function mentions_source:get_trigger_characters() return { "@" } end function mentions_source:get_trigger_characters() return { "@" } end