* refactor(#2828): multi instance nvim-tree.explorer.filters * fix: style * fix: apply suggestions from code review Co-authored-by: Alexander Courtis <alex@courtis.org> --------- Co-authored-by: Alexander Courtis <alex@courtis.org>
This commit is contained in:
parent
1aa9852cad
commit
908478a0e0
@ -9,7 +9,6 @@ local actions = require "nvim-tree.actions"
|
||||
local legacy = require "nvim-tree.legacy"
|
||||
local core = require "nvim-tree.core"
|
||||
local git = require "nvim-tree.git"
|
||||
local filters = require "nvim-tree.explorer.filters"
|
||||
local buffers = require "nvim-tree.buffers"
|
||||
local notify = require "nvim-tree.notify"
|
||||
|
||||
@ -210,7 +209,13 @@ local function setup_autocommands(opts)
|
||||
create_nvim_tree_autocmd("BufReadPost", {
|
||||
callback = function(data)
|
||||
-- update opened file buffers
|
||||
if (filters.config.filter_no_buffer or renderer.config.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then
|
||||
local explorer = core.get_explorer()
|
||||
if not explorer then
|
||||
return
|
||||
end
|
||||
if
|
||||
(explorer.filters.config.filter_no_buffer or renderer.config.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == ""
|
||||
then
|
||||
utils.debounce("Buf:filter_buffer", opts.view.debounce_delay, function()
|
||||
actions.reloaders.reload_explorer()
|
||||
end)
|
||||
@ -221,7 +226,13 @@ local function setup_autocommands(opts)
|
||||
create_nvim_tree_autocmd("BufUnload", {
|
||||
callback = function(data)
|
||||
-- update opened file buffers
|
||||
if (filters.config.filter_no_buffer or renderer.config.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then
|
||||
local explorer = core.get_explorer()
|
||||
if not explorer then
|
||||
return
|
||||
end
|
||||
if
|
||||
(explorer.filters.config.filter_no_buffer or renderer.config.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == ""
|
||||
then
|
||||
utils.debounce("Buf:filter_buffer", opts.view.debounce_delay, function()
|
||||
actions.reloaders.reload_explorer()
|
||||
end)
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
local core = require "nvim-tree.core"
|
||||
local filters = require "nvim-tree.explorer.filters"
|
||||
local find_file = require("nvim-tree.actions.finders.find-file").fn
|
||||
|
||||
local M = {}
|
||||
@ -9,6 +8,11 @@ local M = {}
|
||||
---@return string|nil
|
||||
local function search(search_dir, input_path)
|
||||
local realpaths_searched = {}
|
||||
local explorer = core.get_explorer()
|
||||
|
||||
if not explorer then
|
||||
return
|
||||
end
|
||||
|
||||
if not search_dir then
|
||||
return
|
||||
@ -19,7 +23,7 @@ local function search(search_dir, input_path)
|
||||
local function iter(dir)
|
||||
local realpath, path, name, stat, handle, _
|
||||
|
||||
local filter_status = filters.prepare()
|
||||
local filter_status = explorer.filters:prepare()
|
||||
|
||||
handle, _ = vim.loop.fs_scandir(dir)
|
||||
if not handle then
|
||||
@ -42,7 +46,7 @@ local function search(search_dir, input_path)
|
||||
break
|
||||
end
|
||||
|
||||
if not filters.should_filter(path, stat, filter_status) then
|
||||
if not explorer.filters:should_filter(path, stat, filter_status) then
|
||||
if string.find(path, "/" .. input_path .. "$") then
|
||||
return path
|
||||
end
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
local lib = require "nvim-tree.lib"
|
||||
local utils = require "nvim-tree.utils"
|
||||
local filters = require "nvim-tree.explorer.filters"
|
||||
local reloaders = require "nvim-tree.actions.reloaders"
|
||||
|
||||
local core = require "nvim-tree.core"
|
||||
local M = {}
|
||||
|
||||
local function reload()
|
||||
@ -11,39 +10,56 @@ local function reload()
|
||||
utils.focus_node_or_parent(node)
|
||||
end
|
||||
|
||||
function M.custom()
|
||||
filters.config.filter_custom = not filters.config.filter_custom
|
||||
local function wrap_explorer(fn)
|
||||
return function(...)
|
||||
local explorer = core.get_explorer()
|
||||
if explorer then
|
||||
return fn(explorer, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function custom(explorer)
|
||||
explorer.filters.config.filter_custom = not explorer.filters.config.filter_custom
|
||||
reload()
|
||||
end
|
||||
|
||||
function M.git_ignored()
|
||||
filters.config.filter_git_ignored = not filters.config.filter_git_ignored
|
||||
local function git_ignored(explorer)
|
||||
explorer.filters.config.filter_git_ignored = not explorer.filters.config.filter_git_ignored
|
||||
reload()
|
||||
end
|
||||
|
||||
function M.git_clean()
|
||||
filters.config.filter_git_clean = not filters.config.filter_git_clean
|
||||
local function git_clean(explorer)
|
||||
explorer.filters.config.filter_git_clean = not explorer.filters.config.filter_git_clean
|
||||
reload()
|
||||
end
|
||||
|
||||
function M.no_buffer()
|
||||
filters.config.filter_no_buffer = not filters.config.filter_no_buffer
|
||||
local function no_buffer(explorer)
|
||||
explorer.filters.config.filter_no_buffer = not explorer.filters.config.filter_no_buffer
|
||||
reload()
|
||||
end
|
||||
|
||||
function M.no_bookmark()
|
||||
filters.config.filter_no_bookmark = not filters.config.filter_no_bookmark
|
||||
local function no_bookmark(explorer)
|
||||
explorer.filters.config.filter_no_bookmark = not explorer.filters.config.filter_no_bookmark
|
||||
reload()
|
||||
end
|
||||
|
||||
function M.dotfiles()
|
||||
filters.config.filter_dotfiles = not filters.config.filter_dotfiles
|
||||
local function dotfiles(explorer)
|
||||
explorer.filters.config.filter_dotfiles = not explorer.filters.config.filter_dotfiles
|
||||
reload()
|
||||
end
|
||||
|
||||
function M.enable()
|
||||
filters.config.enable = not filters.config.enable
|
||||
local function enable(explorer)
|
||||
explorer.filters.config.enable = not explorer.filters.config.enable
|
||||
reload()
|
||||
end
|
||||
|
||||
M.custom = wrap_explorer(custom)
|
||||
M.git_ignored = wrap_explorer(git_ignored)
|
||||
M.git_clean = wrap_explorer(git_clean)
|
||||
M.no_buffer = wrap_explorer(no_buffer)
|
||||
M.no_bookmark = wrap_explorer(no_bookmark)
|
||||
M.dotfiles = wrap_explorer(dotfiles)
|
||||
M.enable = wrap_explorer(enable)
|
||||
|
||||
return M
|
||||
|
||||
@ -3,7 +3,6 @@ local builders = require "nvim-tree.explorer.node-builders"
|
||||
local explorer_node = require "nvim-tree.explorer.node"
|
||||
local git = require "nvim-tree.git"
|
||||
local sorters = require "nvim-tree.explorer.sorters"
|
||||
local filters = require "nvim-tree.explorer.filters"
|
||||
local live_filter = require "nvim-tree.live-filter"
|
||||
local log = require "nvim-tree.log"
|
||||
|
||||
@ -15,10 +14,11 @@ local M = {}
|
||||
---@param cwd string
|
||||
---@param node Node
|
||||
---@param git_status table
|
||||
local function populate_children(handle, cwd, node, git_status)
|
||||
---@param parent Explorer
|
||||
local function populate_children(handle, cwd, node, git_status, parent)
|
||||
local node_ignored = explorer_node.is_git_ignored(node)
|
||||
local nodes_by_path = utils.bool_record(node.nodes, "absolute_path")
|
||||
local filter_status = filters.prepare(git_status)
|
||||
local filter_status = parent.filters:prepare(git_status)
|
||||
while true do
|
||||
local name, t = vim.loop.fs_scandir_next(handle)
|
||||
if not name then
|
||||
@ -31,7 +31,7 @@ local function populate_children(handle, cwd, node, git_status)
|
||||
---@type uv.fs_stat.result|nil
|
||||
local stat = vim.loop.fs_stat(abs)
|
||||
|
||||
if not filters.should_filter(abs, stat, filter_status) and not nodes_by_path[abs] and Watcher.is_fs_event_capable(abs) then
|
||||
if not parent.filters:should_filter(abs, stat, filter_status) and not nodes_by_path[abs] and Watcher.is_fs_event_capable(abs) then
|
||||
local child = nil
|
||||
if t == "directory" and vim.loop.fs_access(abs, "R") then
|
||||
child = builders.folder(node, abs, name, stat)
|
||||
@ -56,8 +56,9 @@ end
|
||||
|
||||
---@param node Node
|
||||
---@param status table
|
||||
---@param parent Explorer
|
||||
---@return Node[]|nil
|
||||
function M.explore(node, status)
|
||||
function M.explore(node, status, parent)
|
||||
local cwd = node.link_to or node.absolute_path
|
||||
local handle = vim.loop.fs_scandir(cwd)
|
||||
if not handle then
|
||||
@ -66,7 +67,7 @@ function M.explore(node, status)
|
||||
|
||||
local profile = log.profile_start("explore init %s", node.absolute_path)
|
||||
|
||||
populate_children(handle, cwd, node, status)
|
||||
populate_children(handle, cwd, node, status, parent)
|
||||
|
||||
local is_root = not node.parent
|
||||
local child_folder_only = explorer_node.has_one_child_folder(node) and node.nodes[1]
|
||||
@ -74,7 +75,7 @@ function M.explore(node, status)
|
||||
local child_cwd = child_folder_only.link_to or child_folder_only.absolute_path
|
||||
local child_status = git.load_project_status(child_cwd)
|
||||
node.group_next = child_folder_only
|
||||
local ns = M.explore(child_folder_only, child_status)
|
||||
local ns = M.explore(child_folder_only, child_status, parent)
|
||||
node.nodes = ns or {}
|
||||
|
||||
log.profile_end(profile)
|
||||
|
||||
@ -1,15 +1,52 @@
|
||||
local utils = require "nvim-tree.utils"
|
||||
|
||||
local M = {
|
||||
ignore_list = {},
|
||||
exclude_list = {},
|
||||
custom_function = nil,
|
||||
}
|
||||
---@class Filters to handle all opts.filters and related API
|
||||
---@field config table hydrated user opts.filters
|
||||
---@field private explorer Explorer
|
||||
---@field private exclude_list string[] filters.exclude
|
||||
---@field private ignore_list string[] filters.custom string table
|
||||
---@field private custom_function (fun(absolute_path: string): boolean)|nil filters.custom function
|
||||
local Filters = {}
|
||||
|
||||
---@param opts table user options
|
||||
---@param explorer Explorer
|
||||
---@return Filters
|
||||
function Filters:new(opts, explorer)
|
||||
local o = {
|
||||
explorer = explorer,
|
||||
ignore_list = {},
|
||||
exclude_list = opts.filters.exclude,
|
||||
custom_function = nil,
|
||||
config = {
|
||||
enable = opts.filters.enable,
|
||||
filter_custom = true,
|
||||
filter_dotfiles = opts.filters.dotfiles,
|
||||
filter_git_ignored = opts.filters.git_ignored,
|
||||
filter_git_clean = opts.filters.git_clean,
|
||||
filter_no_buffer = opts.filters.no_buffer,
|
||||
filter_no_bookmark = opts.filters.no_bookmark,
|
||||
},
|
||||
}
|
||||
|
||||
local custom_filter = opts.filters.custom
|
||||
if type(custom_filter) == "function" then
|
||||
o.custom_function = custom_filter
|
||||
else
|
||||
if custom_filter and #custom_filter > 0 then
|
||||
for _, filter_name in pairs(custom_filter) do
|
||||
o.ignore_list[filter_name] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
---@param path string
|
||||
---@return boolean
|
||||
local function is_excluded(path)
|
||||
for _, node in ipairs(M.exclude_list) do
|
||||
local function is_excluded(self, path)
|
||||
for _, node in ipairs(self.exclude_list) do
|
||||
if path:match(node) then
|
||||
return true
|
||||
end
|
||||
@ -21,7 +58,7 @@ end
|
||||
---@param path string Absolute path
|
||||
---@param git_status table from prepare
|
||||
---@return boolean
|
||||
local function git(path, git_status)
|
||||
local function git(self, path, git_status)
|
||||
if type(git_status) ~= "table" or type(git_status.files) ~= "table" or type(git_status.dirs) ~= "table" then
|
||||
return false
|
||||
end
|
||||
@ -32,12 +69,12 @@ local function git(path, git_status)
|
||||
status = status or git_status.dirs.indirect[path] and git_status.dirs.indirect[path][1]
|
||||
|
||||
-- filter ignored; overrides clean as they are effectively dirty
|
||||
if M.config.filter_git_ignored and status == "!!" then
|
||||
if self.config.filter_git_ignored and status == "!!" then
|
||||
return true
|
||||
end
|
||||
|
||||
-- filter clean
|
||||
if M.config.filter_git_clean and not status then
|
||||
if self.config.filter_git_clean and not status then
|
||||
return true
|
||||
end
|
||||
|
||||
@ -48,8 +85,8 @@ end
|
||||
---@param path string Absolute path
|
||||
---@param bufinfo table vim.fn.getbufinfo { buflisted = 1 }
|
||||
---@return boolean
|
||||
local function buf(path, bufinfo)
|
||||
if not M.config.filter_no_buffer or type(bufinfo) ~= "table" then
|
||||
local function buf(self, path, bufinfo)
|
||||
if not self.config.filter_no_buffer or type(bufinfo) ~= "table" then
|
||||
return false
|
||||
end
|
||||
|
||||
@ -65,15 +102,15 @@ end
|
||||
|
||||
---@param path string
|
||||
---@return boolean
|
||||
local function dotfile(path)
|
||||
return M.config.filter_dotfiles and utils.path_basename(path):sub(1, 1) == "."
|
||||
local function dotfile(self, path)
|
||||
return self.config.filter_dotfiles and utils.path_basename(path):sub(1, 1) == "."
|
||||
end
|
||||
|
||||
---@param path string
|
||||
---@param path_type string|nil filetype of path
|
||||
---@param bookmarks table<string, string|nil> path, filetype table of bookmarked files
|
||||
local function bookmark(path, path_type, bookmarks)
|
||||
if not M.config.filter_no_bookmark then
|
||||
local function bookmark(self, path, path_type, bookmarks)
|
||||
if not self.config.filter_no_bookmark then
|
||||
return false
|
||||
end
|
||||
-- if bookmark is empty, we should see a empty filetree
|
||||
@ -107,21 +144,21 @@ end
|
||||
|
||||
---@param path string
|
||||
---@return boolean
|
||||
local function custom(path)
|
||||
if not M.config.filter_custom then
|
||||
local function custom(self, path)
|
||||
if not self.config.filter_custom then
|
||||
return false
|
||||
end
|
||||
|
||||
local basename = utils.path_basename(path)
|
||||
|
||||
-- filter user's custom function
|
||||
if M.custom_function and M.custom_function(path) then
|
||||
if self.custom_function and self.custom_function(path) then
|
||||
return true
|
||||
end
|
||||
|
||||
-- filter custom regexes
|
||||
local relpath = utils.path_relative(path, vim.loop.cwd())
|
||||
for pat, _ in pairs(M.ignore_list) do
|
||||
for pat, _ in pairs(self.ignore_list) do
|
||||
if vim.fn.match(relpath, pat) ~= -1 or vim.fn.match(basename, pat) ~= -1 then
|
||||
return true
|
||||
end
|
||||
@ -129,7 +166,7 @@ local function custom(path)
|
||||
|
||||
local idx = path:match ".+()%.[^.]+$"
|
||||
if idx then
|
||||
if M.ignore_list["*" .. string.sub(path, idx)] == true then
|
||||
if self.ignore_list["*" .. string.sub(path, idx)] == true then
|
||||
return true
|
||||
end
|
||||
end
|
||||
@ -143,14 +180,14 @@ end
|
||||
--- git_status: reference
|
||||
--- bufinfo: empty unless no_buffer set: vim.fn.getbufinfo { buflisted = 1 }
|
||||
--- bookmarks: absolute paths to boolean
|
||||
function M.prepare(git_status)
|
||||
function Filters:prepare(git_status)
|
||||
local status = {
|
||||
git_status = git_status or {},
|
||||
bufinfo = {},
|
||||
bookmarks = {},
|
||||
}
|
||||
|
||||
if M.config.filter_no_buffer then
|
||||
if self.config.filter_no_buffer then
|
||||
status.bufinfo = vim.fn.getbufinfo { buflisted = 1 }
|
||||
end
|
||||
|
||||
@ -169,47 +206,21 @@ end
|
||||
---@param fs_stat uv.fs_stat.result|nil fs_stat of file
|
||||
---@param status table from prepare
|
||||
---@return boolean
|
||||
function M.should_filter(path, fs_stat, status)
|
||||
if not M.config.enable then
|
||||
function Filters:should_filter(path, fs_stat, status)
|
||||
if not self.config.enable then
|
||||
return false
|
||||
end
|
||||
|
||||
-- exclusions override all filters
|
||||
if is_excluded(path) then
|
||||
if is_excluded(self, path) then
|
||||
return false
|
||||
end
|
||||
|
||||
return git(path, status.git_status)
|
||||
or buf(path, status.bufinfo)
|
||||
or dotfile(path)
|
||||
or custom(path)
|
||||
or bookmark(path, fs_stat and fs_stat.type, status.bookmarks)
|
||||
return git(self, path, status.git_status)
|
||||
or buf(self, path, status.bufinfo)
|
||||
or dotfile(self, path)
|
||||
or custom(self, path)
|
||||
or bookmark(self, path, fs_stat and fs_stat.type, status.bookmarks)
|
||||
end
|
||||
|
||||
function M.setup(opts)
|
||||
M.config = {
|
||||
enable = opts.filters.enable,
|
||||
filter_custom = true,
|
||||
filter_dotfiles = opts.filters.dotfiles,
|
||||
filter_git_ignored = opts.filters.git_ignored,
|
||||
filter_git_clean = opts.filters.git_clean,
|
||||
filter_no_buffer = opts.filters.no_buffer,
|
||||
filter_no_bookmark = opts.filters.no_bookmark,
|
||||
}
|
||||
|
||||
M.ignore_list = {}
|
||||
M.exclude_list = opts.filters.exclude
|
||||
|
||||
local custom_filter = opts.filters.custom
|
||||
if type(custom_filter) == "function" then
|
||||
M.custom_function = custom_filter
|
||||
else
|
||||
if custom_filter and #custom_filter > 0 then
|
||||
for _, filter_name in pairs(custom_filter) do
|
||||
M.ignore_list[filter_name] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
return Filters
|
||||
|
||||
@ -2,6 +2,7 @@ local git = require "nvim-tree.git"
|
||||
local notify = require "nvim-tree.notify"
|
||||
local watch = require "nvim-tree.explorer.watch"
|
||||
local explorer_node = require "nvim-tree.explorer.node"
|
||||
local Filters = require "nvim-tree.explorer.filters"
|
||||
local Marks = require "nvim-tree.marks"
|
||||
|
||||
local M = {}
|
||||
@ -41,6 +42,7 @@ function Explorer.new(path)
|
||||
marks = Marks:new(),
|
||||
}, Explorer)
|
||||
explorer.watcher = watch.create_watcher(explorer)
|
||||
explorer.filters = Filters:new(M.config, explorer)
|
||||
explorer:_load(explorer)
|
||||
return explorer
|
||||
end
|
||||
@ -50,7 +52,7 @@ end
|
||||
function Explorer:_load(node)
|
||||
local cwd = node.link_to or node.absolute_path
|
||||
local git_status = git.load_project_status(cwd)
|
||||
M.explore(node, git_status)
|
||||
M.explore(node, git_status, self)
|
||||
end
|
||||
|
||||
---@param node Node
|
||||
@ -71,9 +73,9 @@ function Explorer:destroy()
|
||||
end
|
||||
|
||||
function M.setup(opts)
|
||||
M.config = opts
|
||||
require("nvim-tree.explorer.node").setup(opts)
|
||||
require("nvim-tree.explorer.explore").setup(opts)
|
||||
require("nvim-tree.explorer.filters").setup(opts)
|
||||
require("nvim-tree.explorer.sorters").setup(opts)
|
||||
require("nvim-tree.explorer.reload").setup(opts)
|
||||
require("nvim-tree.explorer.watch").setup(opts)
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
local utils = require "nvim-tree.utils"
|
||||
local builders = require "nvim-tree.explorer.node-builders"
|
||||
local explorer_node = require "nvim-tree.explorer.node"
|
||||
local filters = require "nvim-tree.explorer.filters"
|
||||
local sorters = require "nvim-tree.explorer.sorters"
|
||||
local live_filter = require "nvim-tree.live-filter"
|
||||
local git = require "nvim-tree.git"
|
||||
@ -70,6 +69,10 @@ end
|
||||
---@param node Node
|
||||
---@param git_status table
|
||||
function M.reload(node, git_status)
|
||||
local explorer = require("nvim-tree.core").get_explorer()
|
||||
if not explorer then
|
||||
return
|
||||
end
|
||||
local cwd = node.link_to or node.absolute_path
|
||||
local handle = vim.loop.fs_scandir(cwd)
|
||||
if not handle then
|
||||
@ -78,7 +81,7 @@ function M.reload(node, git_status)
|
||||
|
||||
local profile = log.profile_start("reload %s", node.absolute_path)
|
||||
|
||||
local filter_status = filters.prepare(git_status)
|
||||
local filter_status = explorer.filters:prepare(git_status)
|
||||
|
||||
if node.group_next then
|
||||
node.nodes = { node.group_next }
|
||||
@ -100,7 +103,7 @@ function M.reload(node, git_status)
|
||||
---@type uv.fs_stat.result|nil
|
||||
local stat = vim.loop.fs_stat(abs)
|
||||
|
||||
if not filters.should_filter(abs, stat, filter_status) then
|
||||
if not explorer.filters:should_filter(abs, stat, filter_status) then
|
||||
remain_childs[abs] = true
|
||||
|
||||
-- Recreate node if type changes.
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
local view = require "nvim-tree.view"
|
||||
local utils = require "nvim-tree.utils"
|
||||
local Iterator = require "nvim-tree.iterators.node-iterator"
|
||||
local filters = require "nvim-tree.explorer.filters"
|
||||
|
||||
local M = {
|
||||
filter = nil,
|
||||
@ -57,7 +56,8 @@ end
|
||||
---@param node Node
|
||||
---@return boolean
|
||||
local function matches(node)
|
||||
if not filters.config.enable then
|
||||
local explorer = require("nvim-tree.core").get_explorer()
|
||||
if not explorer or not explorer.filters.config.enable then
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user