diff --git a/README.md b/README.md
index 3585033..78c676b 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,7 @@
### [Warp, the intelligent terminal for developers](https://www.warp.dev/avantenvim)
+
[Available for MacOS, Linux, & Windows](https://www.warp.dev/avantenvim)
@@ -954,6 +955,43 @@ If you have the following structure:
>
> `*.avanterules` is a jinja template file, in which will be rendered using [minijinja](https://github.com/mitsuhiko/minijinja). See [templates](https://github.com/yetone/avante.nvim/blob/main/lua/avante/templates) for example on how to extend current templates.
+## Integration
+
+Avante.nvim can be extended to work with other plugins by using its extension modules. Below is an example of integrating Avante with [`nvim-tree`](https://github.com/nvim-tree/nvim-tree.lua), allowing you to select or deselect files directly from the NvimTree UI:
+
+```lua
+{
+ "yetone/avante.nvim",
+ event = "VeryLazy",
+ keys = {
+ {
+ "a+",
+ function()
+ local tree_ext = require("avante.extensions.nvim_tree")
+ tree_ext.add_file()
+ end,
+ desc = "Select file in NvimTree",
+ ft = "NvimTree",
+ },
+ {
+ "a-",
+ function()
+ local tree_ext = require("avante.extensions.nvim_tree")
+ tree_ext.remove_file()
+ end,
+ desc = "Deselect file in NvimTree",
+ ft = "NvimTree",
+ },
+ },
+ opts = {
+ --- other configurations
+ selector = {
+ exclude_auto_select = { "NvimTree" },
+ },
+ },
+}
+```
+
## TODOs
- [x] Chat with current file
diff --git a/README_zh.md b/README_zh.md
index 5b133f9..f3bd4c6 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -951,6 +951,43 @@ vim.keymap.set("n", "am", function() vim.api.nvim_exec_autocmds("User",
>
> `*.avanterules` 是一个 jinja 模板文件,将使用 [minijinja](https://github.com/mitsuhiko/minijinja) 渲染。有关如何扩展当前模板的示例,请参见 [templates](https://github.com/yetone/avante.nvim/blob/main/lua/avante/templates)。
+## 集成
+
+Avante.nvim 可以通过其扩展模块与其他插件协同工作。下面是一个将 Avante 与 nvim-tree 集成的示例,允许你直接从 NvimTree UI 中选择或取消选择文件:
+
+```lua
+{
+ "yetone/avante.nvim",
+ event = "VeryLazy",
+ keys = {
+ {
+ "a+",
+ function()
+ local tree_ext = require("avante.extensions.nvim_tree")
+ tree_ext.add_file()
+ end,
+ desc = "Select file in NvimTree",
+ ft = "NvimTree",
+ },
+ {
+ "a-",
+ function()
+ local tree_ext = require("avante.extensions.nvim_tree")
+ tree_ext.remove_file()
+ end,
+ desc = "Deselect file in NvimTree",
+ ft = "NvimTree",
+ },
+ },
+ opts = {
+ --- 其他配置
+ selector = {
+ exclude_auto_select = { "NvimTree" },
+ },
+ },
+}
+```
+
## TODOs
- [x] 与当前文件聊天
diff --git a/lua/avante/api.lua b/lua/avante/api.lua
index 6711668..d1f11b0 100644
--- a/lua/avante/api.lua
+++ b/lua/avante/api.lua
@@ -249,6 +249,42 @@ function M.add_buffer_files()
sidebar.file_selector:add_buffer_files()
end
+function M.add_selected_file(filepath)
+ local rel_path = Utils.uniform_path(filepath)
+
+ local sidebar = require("avante").get()
+ if not sidebar then
+ require("avante.api").ask()
+ sidebar = require("avante").get()
+ end
+ if not sidebar:is_open() then sidebar:open({}) end
+ sidebar.file_selector:add_selected_file(rel_path)
+end
+
+function M.remove_selected_file(filepath)
+ ---@diagnostic disable-next-line: undefined-field
+ local stat = vim.loop.fs_stat(filepath)
+ local files
+ if stat and stat.type == "directory" then
+ files = Utils.scan_directory({ directory = filepath, add_dirs = true })
+ else
+ files = { filepath }
+ end
+
+ local sidebar = require("avante").get()
+ if not sidebar then
+ require("avante.api").ask()
+ sidebar = require("avante").get()
+ end
+ if not sidebar:is_open() then sidebar:open({}) end
+
+ for _, file in ipairs(files) do
+ local rel_path = Utils.uniform_path(file)
+ vim.notify(rel_path)
+ sidebar.file_selector:remove_selected_file(rel_path)
+ end
+end
+
function M.stop() require("avante.llm").cancel_inflight_request() end
return setmetatable(M, {
diff --git a/lua/avante/extensions/init.lua b/lua/avante/extensions/init.lua
new file mode 100644
index 0000000..198faaa
--- /dev/null
+++ b/lua/avante/extensions/init.lua
@@ -0,0 +1,10 @@
+---@class avante.extensions
+local M = {}
+
+setmetatable(M, {
+ __index = function(t, k)
+ ---@diagnostic disable-next-line: no-unknown
+ t[k] = require("avante.extensions." .. k)
+ return t[k]
+ end,
+})
diff --git a/lua/avante/extensions/nvim_tree.lua b/lua/avante/extensions/nvim_tree.lua
new file mode 100644
index 0000000..c3b3dc2
--- /dev/null
+++ b/lua/avante/extensions/nvim_tree.lua
@@ -0,0 +1,56 @@
+local Api = require("avante.api")
+
+--- @class avante.extensions.nvim_tree
+local M = {}
+
+--- Adds the currently selected file in NvimTree to the selection via Api.add_selected_file.
+-- Notifies the user if not invoked within NvimTree or if errors occur.
+--- @return nil
+function M.add_file()
+ if vim.bo.filetype ~= "NvimTree" then
+ vim.notify("This action can only be used inside NvimTree.", vim.log.levels.WARN)
+ return
+ end
+
+ local ok, nvim_tree_api = pcall(require, "nvim-tree.api")
+ if not ok then
+ vim.notify("nvim-tree needed", vim.log.levels.ERROR)
+ return
+ end
+
+ local success, node = pcall(function() return nvim_tree_api.tree.get_node_under_cursor() end)
+ if not success then
+ vim.notify("Error getting node: " .. tostring(node), vim.log.levels.ERROR)
+ return
+ end
+
+ local filepath = node.absolute_path
+ Api.add_selected_file(filepath)
+end
+
+--- Removes the currently selected file in NvimTree from the selection via Api.remove_selected_file.
+-- Notifies the user if not invoked within NvimTree or if errors occur.
+--- @return nil
+function M.remove_file()
+ if vim.bo.filetype ~= "NvimTree" then
+ vim.notify("This action can only be used inside NvimTree.", vim.log.levels.WARN)
+ return
+ end
+
+ local ok, nvim_tree_api = pcall(require, "nvim-tree.api")
+ if not ok then
+ vim.notify("nvim-tree needed", vim.log.levels.ERROR)
+ return
+ end
+
+ local success, node = pcall(function() return nvim_tree_api.tree.get_node_under_cursor() end)
+ if not success then
+ vim.notify("Error getting node: " .. tostring(node), vim.log.levels.ERROR)
+ return
+ end
+
+ local filepath = node.absolute_path
+ Api.remove_selected_file(filepath)
+end
+
+return M