From 30604304ba57878edc350c8e8e9c8139315f5315 Mon Sep 17 00:00:00 2001 From: guanghechen <42513619+guanghechen@users.noreply.github.com> Date: Wed, 2 Jul 2025 12:17:13 +0800 Subject: [PATCH] improve: support to customize the avanterules directories for project/global (#2392) --- README.md | 17 +++++++++++++++++ README_zh.md | 17 +++++++++++++++++ lua/avante/config.lua | 4 ++++ lua/avante/path.lua | 37 +++++++++++++++++++++++++------------ 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 75fb8e4..334c6a0 100644 --- a/README.md +++ b/README.md @@ -1137,6 +1137,23 @@ The rules for root hierarchy: - root pattern of filename of the current buffer - root pattern of cwd +You can also configure custom directories for your `avanterules` files using the `rules` option: + +```lua +require('avante').setup({ + rules = { + project_dir = '.avante/rules', -- relative to project root, can also be an absolute path + global_dir = '~/.config/avante/rules', -- absolute path + }, +}) +``` + +The loading priority is as follows: + +1. `rules.project_dir` +2. `rules.global_dir` +3. Project root +
Example folder structure for custom prompt diff --git a/README_zh.md b/README_zh.md index d40f6a9..e63a451 100644 --- a/README_zh.md +++ b/README_zh.md @@ -960,6 +960,23 @@ vim.keymap.set("n", "am", function() vim.api.nvim_exec_autocmds("User", - 当前缓冲区的文件名的根模式 - cwd 的根模式 +您还可以使用 `rules` 选项为您的 `avanterules` 文件配置自定义目录: + +```lua +require('avante').setup({ + rules = { + project_dir = '.avante/rules', -- 相对于项目根目录,也可以是绝对路径 + global_dir = '~/.config/avante/rules', -- 绝对路径 + }, +}) +``` + +加载优先级如下: + +1. `rules.project_dir` +2. `rules.global_dir` +3. 项目根目录 +
自定义提示的示例文件夹结构 diff --git a/lua/avante/config.lua b/lua/avante/config.lua index 8116626..5f937f9 100644 --- a/lua/avante/config.lua +++ b/lua/avante/config.lua @@ -40,6 +40,10 @@ M._defaults = { tokenizer = "tiktoken", ---@type string | (fun(): string) | nil system_prompt = nil, + rules = { + project_dir = nil, ---@type string | nil (could be relative dirpath) + global_dir = nil, ---@type string | nil (absolute dirpath) + }, rag_service = { -- RAG service configuration enabled = false, -- Enables the RAG service host_mount = os.getenv("HOME"), -- Host mount path for the RAG service (Docker will mount this path) diff --git a/lua/avante/path.lua b/lua/avante/path.lua index c23aa02..dff650e 100644 --- a/lua/avante/path.lua +++ b/lua/avante/path.lua @@ -222,22 +222,35 @@ function Prompt.get_templates_dir(project_root) local cache_prompt_dir = P.cache_path:joinpath(directory) 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 file:is_file() then - local pieces = vim.split(entry, "/") - local piece = pieces[#pieces] - local mode = piece:match("([^.]+)%.avanterules$") - if not mode or not Prompt.custom_modes[mode] then goto continue end - if Prompt.custom_prompts_contents[mode] == nil then - Utils.info(string.format("Using %s as %s system prompt", entry, mode)) - Prompt.custom_prompts_contents[mode] = file:read() + local function find_rules(dir) + if not dir then return end + if vim.fn.isdirectory(dir) ~= 1 then return end + + local scanner = Scan.scan_dir(dir, { depth = 1, add_dirs = true }) + for _, entry in ipairs(scanner) do + local file = Path:new(entry) + if file:is_file() then + local pieces = vim.split(entry, "/") + local piece = pieces[#pieces] + local mode = piece:match("([^.]+)%.avanterules$") + if not mode or not Prompt.custom_modes[mode] then goto continue end + if Prompt.custom_prompts_contents[mode] == nil then + Utils.info(string.format("Using %s as %s system prompt", entry, mode)) + Prompt.custom_prompts_contents[mode] = file:read() + end end + ::continue:: end - ::continue:: end + if Config.rules.project_dir then + local project_rules_path = Path:new(Config.rules.project_dir) + if not project_rules_path:is_absolute() then project_rules_path = directory:joinpath(project_rules_path) end + find_rules(tostring(project_rules_path)) + end + find_rules(Config.rules.global_dir) + find_rules(directory:absolute()) + Path:new(debug.getinfo(1).source:match("@?(.*/)"):gsub("/lua/avante/path.lua$", "") .. "templates") :copy({ destination = cache_prompt_dir, recursive = true })