feat: allow configurable file select provider (#944)
- add file_selector config - add providers for fzf and telescope
This commit is contained in:
parent
4d6f8e65fb
commit
a1da07097d
@ -234,6 +234,13 @@ M.defaults = {
|
|||||||
ignore_patterns = { "%.git", "%.worktree", "__pycache__", "node_modules" }, -- ignore files matching these
|
ignore_patterns = { "%.git", "%.worktree", "__pycache__", "node_modules" }, -- ignore files matching these
|
||||||
negate_patterns = {}, -- negate ignore files matching these.
|
negate_patterns = {}, -- negate ignore files matching these.
|
||||||
},
|
},
|
||||||
|
--- @class AvanteFileSelectorConfig
|
||||||
|
--- @field provider "native" | "fzf" | "telescope"
|
||||||
|
file_selector = {
|
||||||
|
provider = "native",
|
||||||
|
-- Options override for custom providers
|
||||||
|
provider_opts = {},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
---@type avante.Config
|
---@type avante.Config
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
local Utils = require("avante.utils")
|
local Utils = require("avante.utils")
|
||||||
local Path = require("plenary.path")
|
local Path = require("plenary.path")
|
||||||
local scan = require("plenary.scandir")
|
local scan = require("plenary.scandir")
|
||||||
|
local Config = require("avante.config")
|
||||||
|
|
||||||
|
local PROMPT_TITLE = "(Avante) Add a file"
|
||||||
|
|
||||||
--- @class FileSelector
|
--- @class FileSelector
|
||||||
local FileSelector = {}
|
local FileSelector = {}
|
||||||
@ -11,6 +14,8 @@ local FileSelector = {}
|
|||||||
--- @field file_cache string[]
|
--- @field file_cache string[]
|
||||||
--- @field event_handlers table<string, function[]>
|
--- @field event_handlers table<string, function[]>
|
||||||
|
|
||||||
|
---@alias FileSelectorHandler fun(self: FileSelector, on_select: fun(on_select: fun(filepath: string)|nil)): nil
|
||||||
|
|
||||||
---@param id integer
|
---@param id integer
|
||||||
---@return FileSelector
|
---@return FileSelector
|
||||||
function FileSelector:new(id)
|
function FileSelector:new(id)
|
||||||
@ -66,7 +71,7 @@ end
|
|||||||
|
|
||||||
---@return nil
|
---@return nil
|
||||||
function FileSelector:open()
|
function FileSelector:open()
|
||||||
self:update_file_cache()
|
if Config.file_selector.provider == "native" then self:update_file_cache() end
|
||||||
self:show_select_ui()
|
self:show_select_ui()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -87,22 +92,105 @@ function FileSelector:update_file_cache()
|
|||||||
:totable()
|
:totable()
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return nil
|
---@type FileSelectorHandler
|
||||||
function FileSelector:show_select_ui()
|
function FileSelector:fzf_ui(handler)
|
||||||
vim.schedule(function()
|
local success, fzf_lua = pcall(require, "fzf-lua")
|
||||||
|
if not success then
|
||||||
|
Utils.error("fzf-lua is not installed. Please install fzf-lua to use it as a file selector.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local close_action = function() handler(nil) end
|
||||||
|
fzf_lua.files(vim.tbl_deep_extend("force", Config.file_selector.provider_opts, {
|
||||||
|
prompt = string.format("%s> ", PROMPT_TITLE),
|
||||||
|
fzf_opts = {},
|
||||||
|
git_icons = false,
|
||||||
|
actions = {
|
||||||
|
["default"] = function(selected)
|
||||||
|
local file = fzf_lua.path.entry_to_file(selected[1])
|
||||||
|
handler(file.path)
|
||||||
|
end,
|
||||||
|
["esc"] = close_action,
|
||||||
|
["ctrl-c"] = close_action,
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
|
||||||
|
function FileSelector:telescope_ui(handler)
|
||||||
|
local success, _ = pcall(require, "telescope")
|
||||||
|
if not success then
|
||||||
|
Utils.error("telescope is not installed. Please install telescope to use it as a file selector.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local pickers = require("telescope.pickers")
|
||||||
|
local finders = require("telescope.finders")
|
||||||
|
local conf = require("telescope.config").values
|
||||||
|
local actions = require("telescope.actions")
|
||||||
|
local action_state = require("telescope.actions.state")
|
||||||
|
|
||||||
|
pickers
|
||||||
|
.new(
|
||||||
|
{},
|
||||||
|
vim.tbl_extend("force", Config.file_selector.provider_opts, {
|
||||||
|
prompt_title = string.format("%s> ", PROMPT_TITLE),
|
||||||
|
finder = finders.new_oneshot_job({ "git", "ls-files" }, { cwd = Utils.get_project_root() }),
|
||||||
|
sorter = conf.file_sorter(),
|
||||||
|
attach_mappings = function(prompt_bufnr, map)
|
||||||
|
map("i", "<esc>", require("telescope.actions").close)
|
||||||
|
|
||||||
|
actions.select_default:replace(function()
|
||||||
|
actions.close(prompt_bufnr)
|
||||||
|
local selection = action_state.get_selected_entry()
|
||||||
|
handler(selection[1])
|
||||||
|
end)
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
:find()
|
||||||
|
end
|
||||||
|
|
||||||
|
---@type FileSelectorHandler
|
||||||
|
function FileSelector:native_ui(handler)
|
||||||
local filepaths = vim
|
local filepaths = vim
|
||||||
.iter(self.file_cache)
|
.iter(self.file_cache)
|
||||||
:filter(function(filepath) return not vim.tbl_contains(self.selected_filepaths, filepath) end)
|
:filter(function(filepath) return not vim.tbl_contains(self.selected_filepaths, filepath) end)
|
||||||
:totable()
|
:totable()
|
||||||
|
|
||||||
vim.ui.select(filepaths, {
|
vim.ui.select(filepaths, {
|
||||||
prompt = "(Avante) Add a file:",
|
prompt = string.format("%s:", PROMPT_TITLE),
|
||||||
format_item = function(item) return item end,
|
format_item = function(item) return item end,
|
||||||
}, function(filepath)
|
}, handler)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return nil
|
||||||
|
function FileSelector:show_select_ui()
|
||||||
|
local handler = function(filepath)
|
||||||
if not filepath then return end
|
if not filepath then return end
|
||||||
table.insert(self.selected_filepaths, Utils.uniform_path(filepath))
|
local uniform_path = Utils.uniform_path(filepath)
|
||||||
|
if Config.file_selector.provider == "native" then
|
||||||
|
-- Native handler filters out already selected files
|
||||||
|
table.insert(self.selected_filepaths, uniform_path)
|
||||||
self:emit("update")
|
self:emit("update")
|
||||||
end)
|
else
|
||||||
|
if not vim.tbl_contains(self.selected_filepaths, uniform_path) then
|
||||||
|
table.insert(self.selected_filepaths, uniform_path)
|
||||||
|
self:emit("update")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.schedule(function()
|
||||||
|
if Config.file_selector.provider == "native" then
|
||||||
|
self:native_ui(handler)
|
||||||
|
elseif Config.file_selector.provider == "fzf" then
|
||||||
|
self:fzf_ui(handler)
|
||||||
|
elseif Config.file_selector.provider == "telescope" then
|
||||||
|
self:telescope_ui(handler)
|
||||||
|
else
|
||||||
|
Utils.error("Unknown file selector provider: " .. Config.file_selector.provider)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- unlist the current buffer as vim.ui.select will be listed
|
-- unlist the current buffer as vim.ui.select will be listed
|
||||||
|
Loading…
x
Reference in New Issue
Block a user