feat: enable override prompt templates directory (#2387)
This commit is contained in:
28
README.md
28
README.md
@@ -1116,7 +1116,9 @@ By default, `avante.nvim` provides three different modes to interact with: `plan
|
|||||||
- `suggesting`: Used with `require("avante").get_suggestion():suggest()` on Tab flow.
|
- `suggesting`: Used with `require("avante").get_suggestion():suggest()` on Tab flow.
|
||||||
- `cursor-planning`: Used with `require("avante").toggle()` on Tab flow, but only when cursor planning mode is enabled.
|
- `cursor-planning`: Used with `require("avante").toggle()` on Tab flow, but only when cursor planning mode is enabled.
|
||||||
|
|
||||||
Users can customize the system prompts via `Config.system_prompt`. We recommend calling this in a custom Autocmds depending on your need:
|
Users can customize the system prompts via `Config.system_prompt` or `Config.override_prompt_dir`.
|
||||||
|
|
||||||
|
`Config.system_prompt` allows you to set a global system prompt. We recommend calling this in a custom Autocmds depending on your need:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
vim.api.nvim_create_autocmd("User", {
|
vim.api.nvim_create_autocmd("User", {
|
||||||
@@ -1127,7 +1129,29 @@ vim.api.nvim_create_autocmd("User", {
|
|||||||
vim.keymap.set("n", "<leader>am", function() vim.api.nvim_exec_autocmds("User", { pattern = "ToggleMyPrompt" }) end, { desc = "avante: toggle my prompt" })
|
vim.keymap.set("n", "<leader>am", function() vim.api.nvim_exec_autocmds("User", { pattern = "ToggleMyPrompt" }) end, { desc = "avante: toggle my prompt" })
|
||||||
```
|
```
|
||||||
|
|
||||||
If one wish to custom prompts for each mode, `avante.nvim` will check for project root based on the given buffer whether it contains
|
`Config.override_prompt_dir` allows you to specify a directory containing your own custom prompt templates, which will override the built-in templates. This is useful if you want to maintain a set of custom prompts outside of your Neovim configuration. It can be a string representing the directory path, or a function that returns a string representing the directory path.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- Example: Override with prompts from a specific directory
|
||||||
|
require("avante").setup({
|
||||||
|
override_prompt_dir = vim.fn.expand("~/.config/nvim/avante_prompts"),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Example: Override with prompts from a function (dynamic directory)
|
||||||
|
require("avante").setup({
|
||||||
|
override_prompt_dir = function()
|
||||||
|
-- Your logic to determine the prompt directory
|
||||||
|
return vim.fn.expand("~/.config/nvim/my_dynamic_prompts")
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
>
|
||||||
|
> If you customize `base.avanterules`, please ensure that `{% block custom_prompt %}{% endblock %}` and `{% block extra_prompt %}{% endblock %}` exist, otherwise the entire plugin may become unusable.
|
||||||
|
> If you are unsure about the specific reasons or what you are doing, please do not override the built-in prompts. The built-in prompts work very well.
|
||||||
|
|
||||||
|
If you wish to custom prompts for each mode, `avante.nvim` will check for project root based on the given buffer whether it contains
|
||||||
the following patterns: `*.{mode}.avanterules`.
|
the following patterns: `*.{mode}.avanterules`.
|
||||||
|
|
||||||
The rules for root hierarchy:
|
The rules for root hierarchy:
|
||||||
|
|||||||
26
README_zh.md
26
README_zh.md
@@ -940,7 +940,9 @@ Avante 利用 [Claude 文本编辑器工具](https://docs.anthropic.com/en/docs/
|
|||||||
- `suggesting`:与 Tab 流上的 `require("avante").get_suggestion():suggest()` 一起使用。
|
- `suggesting`:与 Tab 流上的 `require("avante").get_suggestion():suggest()` 一起使用。
|
||||||
- `cursor-planning`:与 Tab 流上的 `require("avante").toggle()` 一起使用,但仅在启用 cursor 规划模式时。
|
- `cursor-planning`:与 Tab 流上的 `require("avante").toggle()` 一起使用,但仅在启用 cursor 规划模式时。
|
||||||
|
|
||||||
用户可以通过 `Config.system_prompt` 自定义系统提示。我们建议根据您的需要在自定义 Autocmds 中调用此方法:
|
用户可以通过 `Config.system_prompt` 或 `Config.override_prompt_dir` 自定义系统提示。
|
||||||
|
|
||||||
|
`Config.system_prompt` 允许您设置全局系统提示。我们建议根据您的需要在自定义 Autocmds 中调用此方法:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
vim.api.nvim_create_autocmd("User", {
|
vim.api.nvim_create_autocmd("User", {
|
||||||
@@ -951,6 +953,28 @@ vim.api.nvim_create_autocmd("User", {
|
|||||||
vim.keymap.set("n", "<leader>am", function() vim.api.nvim_exec_autocmds("User", { pattern = "ToggleMyPrompt" }) end, { desc = "avante: toggle my prompt" })
|
vim.keymap.set("n", "<leader>am", function() vim.api.nvim_exec_autocmds("User", { pattern = "ToggleMyPrompt" }) end, { desc = "avante: toggle my prompt" })
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`Config.override_prompt_dir` 允许您指定一个目录,其中包含您自己的自定义提示模板,这将覆盖内置模板。如果您想在 Neovim 配置之外维护一组自定义提示,这将非常有用。它可以是一个表示目录路径的字符串,也可以是一个返回表示目录路径的字符串的函数。
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- 示例:使用特定目录中的提示进行覆盖
|
||||||
|
require("avante").setup({
|
||||||
|
override_prompt_dir = vim.fn.expand("~/.config/nvim/avante_prompts"),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- 示例:使用函数(动态目录)中的提示进行覆盖
|
||||||
|
require("avante").setup({
|
||||||
|
override_prompt_dir = function()
|
||||||
|
-- 确定提示目录的逻辑
|
||||||
|
return vim.fn.expand("~/.config/nvim/my_dynamic_prompts")
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
>
|
||||||
|
> 如果您自定 `base.avanterules`,请一定要确保 `{% block custom_prompt %}{% endblock %}` 和 `{% block extra_prompt %}{% endblock %}` 存在,否则可能会导致整个插件无法使用。
|
||||||
|
> 如果您不清楚具体原因或者您不知道自己在干什么,请不要覆盖内置 prompt。内置 prompt 工作得非常好。
|
||||||
|
|
||||||
如果希望为每种模式自定义提示,`avante.nvim` 将根据给定缓冲区的项目根目录检查是否包含以下模式:`*.{mode}.avanterules`。
|
如果希望为每种模式自定义提示,`avante.nvim` 将根据给定缓冲区的项目根目录检查是否包含以下模式:`*.{mode}.avanterules`。
|
||||||
|
|
||||||
根目录层次结构的规则:
|
根目录层次结构的规则:
|
||||||
|
|||||||
@@ -38,8 +38,10 @@ M._defaults = {
|
|||||||
-- For most providers that we support we will determine this automatically.
|
-- For most providers that we support we will determine this automatically.
|
||||||
-- If you wish to use a given implementation, then you can override it here.
|
-- If you wish to use a given implementation, then you can override it here.
|
||||||
tokenizer = "tiktoken",
|
tokenizer = "tiktoken",
|
||||||
---@type string | (fun(): string) | nil
|
---@type string | fun(): string | nil
|
||||||
system_prompt = nil,
|
system_prompt = nil,
|
||||||
|
---@type string | fun(): string | nil
|
||||||
|
override_prompt_dir = nil,
|
||||||
rules = {
|
rules = {
|
||||||
project_dir = nil, ---@type string | nil (could be relative dirpath)
|
project_dir = nil, ---@type string | nil (could be relative dirpath)
|
||||||
global_dir = nil, ---@type string | nil (absolute dirpath)
|
global_dir = nil, ---@type string | nil (absolute dirpath)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ local Config = require("avante.config")
|
|||||||
---@class avante.Path
|
---@class avante.Path
|
||||||
---@field history_path Path
|
---@field history_path Path
|
||||||
---@field cache_path Path
|
---@field cache_path Path
|
||||||
|
---@field data_path Path
|
||||||
local P = {}
|
local P = {}
|
||||||
|
|
||||||
---@param bufnr integer | nil
|
---@param bufnr integer | nil
|
||||||
@@ -243,6 +244,45 @@ function Prompt.get_templates_dir(project_root)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Check for override prompt
|
||||||
|
local override_prompt_dir = Config.override_prompt_dir
|
||||||
|
if override_prompt_dir then
|
||||||
|
-- Handle the case where override_prompt_dir is a function
|
||||||
|
if type(override_prompt_dir) == "function" then
|
||||||
|
local ok, result = pcall(override_prompt_dir)
|
||||||
|
if ok and result then override_prompt_dir = result end
|
||||||
|
end
|
||||||
|
|
||||||
|
if override_prompt_dir then
|
||||||
|
local user_template_path = Path:new(override_prompt_dir)
|
||||||
|
if user_template_path:exists() then
|
||||||
|
local user_scanner = Scan.scan_dir(user_template_path:absolute(), { depth = 1, add_dirs = false })
|
||||||
|
for _, entry in ipairs(user_scanner) do
|
||||||
|
local file = Path:new(entry)
|
||||||
|
if file:is_file() then
|
||||||
|
local pieces = vim.split(entry, "/")
|
||||||
|
local piece = pieces[#pieces]
|
||||||
|
|
||||||
|
if piece == "base.avanterules" then
|
||||||
|
local content = file:read()
|
||||||
|
|
||||||
|
if not content:match("{%% block extra_prompt %%}[%s,\\n]*{%% endblock %%}") then
|
||||||
|
file:write("{% block extra_prompt %}\n", "a")
|
||||||
|
file:write("{% endblock %}\n", "a")
|
||||||
|
end
|
||||||
|
|
||||||
|
if not content:match("{%% block custom_prompt %%}[%s,\\n]*{%% endblock %%}") then
|
||||||
|
file:write("{% block custom_prompt %}\n", "a")
|
||||||
|
file:write("{% endblock %}", "a")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
file:copy({ destination = cache_prompt_dir:joinpath(piece) })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if Config.rules.project_dir then
|
if Config.rules.project_dir then
|
||||||
local project_rules_path = Path:new(Config.rules.project_dir)
|
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
|
if not project_rules_path:is_absolute() then project_rules_path = directory:joinpath(project_rules_path) end
|
||||||
@@ -251,8 +291,12 @@ function Prompt.get_templates_dir(project_root)
|
|||||||
find_rules(Config.rules.global_dir)
|
find_rules(Config.rules.global_dir)
|
||||||
find_rules(directory:absolute())
|
find_rules(directory:absolute())
|
||||||
|
|
||||||
Path:new(debug.getinfo(1).source:match("@?(.*/)"):gsub("/lua/avante/path.lua$", "") .. "templates")
|
-- Copy built-in templates to cache directory (only if not overridden by user templates)
|
||||||
:copy({ destination = cache_prompt_dir, recursive = true })
|
Path:new(debug.getinfo(1).source:match("@?(.*/)"):gsub("/lua/avante/path.lua$", "") .. "templates"):copy({
|
||||||
|
destination = cache_prompt_dir,
|
||||||
|
recursive = true,
|
||||||
|
override = false,
|
||||||
|
})
|
||||||
|
|
||||||
vim.iter(Prompt.custom_prompts_contents):filter(function(_, v) return v ~= nil end):each(function(k, v)
|
vim.iter(Prompt.custom_prompts_contents):filter(function(_, v) return v ~= nil end):each(function(k, v)
|
||||||
local orig_file = cache_prompt_dir:joinpath(Prompt.get_builtin_prompts_filepath(k))
|
local orig_file = cache_prompt_dir:joinpath(Prompt.get_builtin_prompts_filepath(k))
|
||||||
|
|||||||
Reference in New Issue
Block a user