refactor(#2827): multi instance nvim-tree.live-filter (#2849)

* feat(#2827): Multi Instance: Refactor: nvim-tree.live-filter

* refactor: all usages going through the explorer

* fix: api and filtration

* fix: style

* Update lua/nvim-tree/api.lua

Co-authored-by: Alexander Courtis <alex@courtis.org>

* docs: add missing live filter luadocs

---------

Co-authored-by: Alexander Courtis <alex@courtis.org>
This commit is contained in:
Mateusz Russak 2024-08-10 04:02:13 +02:00 committed by GitHub
parent e25eb7fa83
commit 15942df2bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 80 additions and 59 deletions

View File

@ -840,7 +840,6 @@ function M.setup(conf)
require("nvim-tree.view").setup(opts) require("nvim-tree.view").setup(opts)
require("nvim-tree.lib").setup(opts) require("nvim-tree.lib").setup(opts)
require("nvim-tree.renderer").setup(opts) require("nvim-tree.renderer").setup(opts)
require("nvim-tree.live-filter").setup(opts)
require("nvim-tree.marks").setup(opts) require("nvim-tree.marks").setup(opts)
require("nvim-tree.buffers").setup(opts) require("nvim-tree.buffers").setup(opts)
require("nvim-tree.help").setup(opts) require("nvim-tree.help").setup(opts)

View File

@ -6,7 +6,6 @@ local actions = require "nvim-tree.actions"
local appearance_diagnostics = require "nvim-tree.appearance.diagnostics" local appearance_diagnostics = require "nvim-tree.appearance.diagnostics"
local events = require "nvim-tree.events" local events = require "nvim-tree.events"
local help = require "nvim-tree.help" local help = require "nvim-tree.help"
local live_filter = require "nvim-tree.live-filter"
local marks_navigation = require "nvim-tree.marks.navigation" local marks_navigation = require "nvim-tree.marks.navigation"
local marks_bulk_delete = require "nvim-tree.marks.bulk-delete" local marks_bulk_delete = require "nvim-tree.marks.bulk-delete"
local marks_bulk_trash = require "nvim-tree.marks.bulk-trash" local marks_bulk_trash = require "nvim-tree.marks.bulk-trash"
@ -265,8 +264,8 @@ Api.git.reload = wrap(actions.reloaders.reload_git)
Api.events.subscribe = events.subscribe Api.events.subscribe = events.subscribe
Api.events.Event = events.Event Api.events.Event = events.Event
Api.live_filter.start = wrap(live_filter.start_filtering) Api.live_filter.start = wrap_explorer_member("live_filter", "start_filtering")
Api.live_filter.clear = wrap(live_filter.clear_filter) Api.live_filter.clear = wrap_explorer_member("live_filter", "clear_filter")
Api.marks.get = wrap_node(wrap_explorer_member("marks", "get_mark")) Api.marks.get = wrap_node(wrap_explorer_member("marks", "get_mark"))
Api.marks.list = wrap_explorer_member("marks", "get_marks") Api.marks.list = wrap_explorer_member("marks", "get_marks")

View File

@ -1,6 +1,5 @@
local events = require "nvim-tree.events" local events = require "nvim-tree.events"
local explorer = require "nvim-tree.explorer" local explorer = require "nvim-tree.explorer"
local live_filter = require "nvim-tree.live-filter"
local view = require "nvim-tree.view" local view = require "nvim-tree.view"
local log = require "nvim-tree.log" local log = require "nvim-tree.log"
@ -45,7 +44,7 @@ function M.get_nodes_starting_line()
if view.is_root_folder_visible(M.get_cwd()) then if view.is_root_folder_visible(M.get_cwd()) then
offset = offset + 1 offset = offset + 1
end end
if live_filter.filter then if TreeExplorer and TreeExplorer.live_filter.filter then
return offset + 1 return offset + 1
end end
return offset return offset

View File

@ -2,7 +2,6 @@ local utils = require "nvim-tree.utils"
local builders = require "nvim-tree.explorer.node-builders" local builders = require "nvim-tree.explorer.node-builders"
local explorer_node = require "nvim-tree.explorer.node" local explorer_node = require "nvim-tree.explorer.node"
local git = require "nvim-tree.git" local git = require "nvim-tree.git"
local live_filter = require "nvim-tree.live-filter"
local log = require "nvim-tree.log" local log = require "nvim-tree.log"
local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON
@ -99,7 +98,7 @@ function M.explore(node, status, parent)
end end
parent.sorters:sort(node.nodes) parent.sorters:sort(node.nodes)
live_filter.apply_filter(node) parent.live_filter:apply_filter(node)
log.profile_end(profile) log.profile_end(profile)
return node.nodes return node.nodes

View File

@ -4,6 +4,7 @@ local watch = require "nvim-tree.explorer.watch"
local explorer_node = require "nvim-tree.explorer.node" local explorer_node = require "nvim-tree.explorer.node"
local Filters = require "nvim-tree.explorer.filters" local Filters = require "nvim-tree.explorer.filters"
local Marks = require "nvim-tree.marks" local Marks = require "nvim-tree.marks"
local LiveFilter = require "nvim-tree.explorer.live-filter"
local Sorters = require "nvim-tree.explorer.sorters" local Sorters = require "nvim-tree.explorer.sorters"
local M = {} local M = {}
@ -15,6 +16,9 @@ M.reload = require("nvim-tree.explorer.reload").reload
---@field absolute_path string ---@field absolute_path string
---@field nodes Node[] ---@field nodes Node[]
---@field open boolean ---@field open boolean
---@field filters Filters
---@field live_filter LiveFilter
---@field sorters Sorter
---@field marks Marks ---@field marks Marks
local Explorer = {} local Explorer = {}
@ -45,6 +49,7 @@ function Explorer.new(path)
}, Explorer) }, Explorer)
explorer.watcher = watch.create_watcher(explorer) explorer.watcher = watch.create_watcher(explorer)
explorer.filters = Filters:new(M.config, explorer) explorer.filters = Filters:new(M.config, explorer)
explorer.live_filter = LiveFilter:new(M.config, explorer)
explorer:_load(explorer) explorer:_load(explorer)
return explorer return explorer
end end

View File

@ -2,17 +2,34 @@ local view = require "nvim-tree.view"
local utils = require "nvim-tree.utils" local utils = require "nvim-tree.utils"
local Iterator = require "nvim-tree.iterators.node-iterator" local Iterator = require "nvim-tree.iterators.node-iterator"
local M = { ---@class LiveFilter
---@field explorer Explorer
---@field prefix string
---@field always_show_folders boolean
---@field filter string
local LiveFilter = {}
---@param opts table
---@param explorer Explorer
function LiveFilter:new(opts, explorer)
local o = {
explorer = explorer,
prefix = opts.live_filter.prefix,
always_show_folders = opts.live_filter.always_show_folders,
filter = nil, filter = nil,
} }
setmetatable(o, self)
self.__index = self
return o
end
local function redraw() local function redraw()
require("nvim-tree.renderer").draw() require("nvim-tree.renderer").draw()
end end
---@param node_ Node|nil ---@param node_ Node|nil
local function reset_filter(node_) local function reset_filter(self, node_)
node_ = node_ or require("nvim-tree.core").get_explorer() node_ = node_ or self.explorer
if node_ == nil then if node_ == nil then
return return
@ -36,7 +53,7 @@ end
local overlay_bufnr = 0 local overlay_bufnr = 0
local overlay_winnr = 0 local overlay_winnr = 0
local function remove_overlay() local function remove_overlay(self)
if view.View.float.enable and view.View.float.quit_on_focus_loss then if view.View.float.enable and view.View.float.quit_on_focus_loss then
-- return to normal nvim-tree float behaviour when filter window is closed -- return to normal nvim-tree float behaviour when filter window is closed
vim.api.nvim_create_autocmd("WinLeave", { vim.api.nvim_create_autocmd("WinLeave", {
@ -55,28 +72,27 @@ local function remove_overlay()
overlay_bufnr = 0 overlay_bufnr = 0
overlay_winnr = 0 overlay_winnr = 0
if M.filter == "" then if self.filter == "" then
M.clear_filter() self:clear_filter()
end end
end end
---@param node Node ---@param node Node
---@return boolean ---@return boolean
local function matches(node) local function matches(self, node)
local explorer = require("nvim-tree.core").get_explorer() if not self.explorer.filters.config.enable then
if not explorer or not explorer.filters.config.enable then
return true return true
end end
local path = node.absolute_path local path = node.absolute_path
local name = vim.fn.fnamemodify(path, ":t") local name = vim.fn.fnamemodify(path, ":t")
return vim.regex(M.filter):match_str(name) ~= nil return vim.regex(self.filter):match_str(name) ~= nil
end end
---@param node_ Node|nil ---@param node_ Node|nil
function M.apply_filter(node_) function LiveFilter:apply_filter(node_)
if not M.filter or M.filter == "" then if not self.filter or self.filter == "" then
reset_filter(node_) reset_filter(self, node_)
return return
end end
@ -101,31 +117,35 @@ function M.apply_filter(node_)
node.hidden_stats.live_filter = filtered_nodes node.hidden_stats.live_filter = filtered_nodes
local has_nodes = nodes and (M.always_show_folders or #nodes > filtered_nodes) local has_nodes = nodes and (self.always_show_folders or #nodes > filtered_nodes)
local ok, is_match = pcall(matches, node) local ok, is_match = pcall(matches, self, node)
node.hidden = not (has_nodes or (ok and is_match)) node.hidden = not (has_nodes or (ok and is_match))
end end
iterate(node_ or require("nvim-tree.core").get_explorer()) iterate(node_ or self.explorer)
end end
local function record_char() local function record_char(self)
vim.schedule(function() vim.schedule(function()
M.filter = vim.api.nvim_buf_get_lines(overlay_bufnr, 0, -1, false)[1] self.filter = vim.api.nvim_buf_get_lines(overlay_bufnr, 0, -1, false)[1]
M.apply_filter() self:apply_filter()
redraw() redraw()
end) end)
end end
local function configure_buffer_overlay() local function configure_buffer_overlay(self)
overlay_bufnr = vim.api.nvim_create_buf(false, true) overlay_bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_attach(overlay_bufnr, true, { vim.api.nvim_buf_attach(overlay_bufnr, true, {
on_lines = record_char, on_lines = function()
return record_char(self)
end,
}) })
vim.api.nvim_create_autocmd("InsertLeave", { vim.api.nvim_create_autocmd("InsertLeave", {
callback = remove_overlay, callback = function()
return remove_overlay(self)
end,
once = true, once = true,
}) })
@ -133,17 +153,17 @@ local function configure_buffer_overlay()
end end
---@return integer ---@return integer
local function calculate_overlay_win_width() local function calculate_overlay_win_width(self)
local wininfo = vim.fn.getwininfo(view.get_winnr())[1] local wininfo = vim.fn.getwininfo(view.get_winnr())[1]
if wininfo then if wininfo then
return wininfo.width - wininfo.textoff - #M.prefix return wininfo.width - wininfo.textoff - #self.prefix
end end
return 20 return 20
end end
local function create_overlay() local function create_overlay(self)
if view.View.float.enable then if view.View.float.enable then
-- don't close nvim-tree float when focus is changed to filter window -- don't close nvim-tree float when focus is changed to filter window
vim.api.nvim_clear_autocmds { vim.api.nvim_clear_autocmds {
@ -153,12 +173,12 @@ local function create_overlay()
} }
end end
configure_buffer_overlay() configure_buffer_overlay(self)
overlay_winnr = vim.api.nvim_open_win(overlay_bufnr, true, { overlay_winnr = vim.api.nvim_open_win(overlay_bufnr, true, {
col = 1, col = 1,
row = 0, row = 0,
relative = "cursor", relative = "cursor",
width = calculate_overlay_win_width(), width = calculate_overlay_win_width(self),
height = 1, height = 1,
border = "none", border = "none",
style = "minimal", style = "minimal",
@ -170,29 +190,31 @@ local function create_overlay()
vim.api.nvim_buf_set_option(overlay_bufnr, "modifiable", true) ---@diagnostic disable-line: deprecated vim.api.nvim_buf_set_option(overlay_bufnr, "modifiable", true) ---@diagnostic disable-line: deprecated
end end
vim.api.nvim_buf_set_lines(overlay_bufnr, 0, -1, false, { M.filter }) vim.api.nvim_buf_set_lines(overlay_bufnr, 0, -1, false, { self.filter })
vim.cmd "startinsert" vim.cmd "startinsert"
vim.api.nvim_win_set_cursor(overlay_winnr, { 1, #M.filter + 1 }) vim.api.nvim_win_set_cursor(overlay_winnr, { 1, #self.filter + 1 })
end end
function M.start_filtering() function LiveFilter:start_filtering()
view.View.live_filter.prev_focused_node = require("nvim-tree.lib").get_node_at_cursor() view.View.live_filter.prev_focused_node = require("nvim-tree.lib").get_node_at_cursor()
M.filter = M.filter or "" self.filter = self.filter or ""
redraw() redraw()
local row = require("nvim-tree.core").get_nodes_starting_line() - 1 local row = require("nvim-tree.core").get_nodes_starting_line() - 1
local col = #M.prefix > 0 and #M.prefix - 1 or 1 local col = #self.prefix > 0 and #self.prefix - 1 or 1
view.set_cursor { row, col } view.set_cursor { row, col }
-- needs scheduling to let the cursor move before initializing the window -- needs scheduling to let the cursor move before initializing the window
vim.schedule(create_overlay) vim.schedule(function()
return create_overlay(self)
end)
end end
function M.clear_filter() function LiveFilter:clear_filter()
local node = require("nvim-tree.lib").get_node_at_cursor() local node = require("nvim-tree.lib").get_node_at_cursor()
local last_node = view.View.live_filter.prev_focused_node local last_node = view.View.live_filter.prev_focused_node
M.filter = nil self.filter = nil
reset_filter() reset_filter(self)
redraw() redraw()
if node then if node then
@ -202,9 +224,4 @@ function M.clear_filter()
end end
end end
function M.setup(opts) return LiveFilter
M.prefix = opts.live_filter.prefix
M.always_show_folders = opts.live_filter.always_show_folders
end
return M

View File

@ -1,7 +1,6 @@
local utils = require "nvim-tree.utils" local utils = require "nvim-tree.utils"
local builders = require "nvim-tree.explorer.node-builders" local builders = require "nvim-tree.explorer.node-builders"
local explorer_node = require "nvim-tree.explorer.node" local explorer_node = require "nvim-tree.explorer.node"
local live_filter = require "nvim-tree.live-filter"
local git = require "nvim-tree.git" local git = require "nvim-tree.git"
local log = require "nvim-tree.log" local log = require "nvim-tree.log"
@ -183,7 +182,7 @@ function M.reload(node, git_status)
end end
explorer.sorters:sort(node.nodes) explorer.sorters:sort(node.nodes)
live_filter.apply_filter(node) explorer.live_filter:apply_filter(node)
log.profile_end(profile) log.profile_end(profile)
return node.nodes return node.nodes
end end

View File

@ -1,5 +1,4 @@
local core = require "nvim-tree.core" local core = require "nvim-tree.core"
local live_filter = require "nvim-tree.live-filter"
local notify = require "nvim-tree.notify" local notify = require "nvim-tree.notify"
local utils = require "nvim-tree.utils" local utils = require "nvim-tree.utils"
local view = require "nvim-tree.view" local view = require "nvim-tree.view"
@ -389,7 +388,8 @@ end
---@private ---@private
function Builder:get_nodes_number(nodes) function Builder:get_nodes_number(nodes)
if not live_filter.filter then local explorer = core.get_explorer()
if not explorer or not explorer.live_filter.filter then
return #nodes return #nodes
end end
@ -436,6 +436,7 @@ end
---@private ---@private
function Builder:build_header() function Builder:build_header()
local explorer = core.get_explorer()
if view.is_root_folder_visible(core.get_cwd()) then if view.is_root_folder_visible(core.get_cwd()) then
local root_name = self:format_root_name(M.opts.renderer.root_folder_label) local root_name = self:format_root_name(M.opts.renderer.root_folder_label)
table.insert(self.lines, root_name) table.insert(self.lines, root_name)
@ -443,8 +444,8 @@ function Builder:build_header()
self.index = 1 self.index = 1
end end
if live_filter.filter then if explorer and explorer.live_filter.filter then
local filter_line = string.format("%s/%s/", M.opts.live_filter.prefix, live_filter.filter) local filter_line = string.format("%s/%s/", M.opts.live_filter.prefix, explorer.live_filter.filter)
table.insert(self.lines, filter_line) table.insert(self.lines, filter_line)
local prefix_length = string.len(M.opts.live_filter.prefix) local prefix_length = string.len(M.opts.live_filter.prefix)
self:insert_highlight({ "NvimTreeLiveFilterPrefix" }, 0, prefix_length) self:insert_highlight({ "NvimTreeLiveFilterPrefix" }, 0, prefix_length)

View File

@ -112,7 +112,10 @@ function M.find_node(nodes, fn)
end) end)
:iterate() :iterate()
i = require("nvim-tree.view").is_root_folder_visible() and i or i - 1 i = require("nvim-tree.view").is_root_folder_visible() and i or i - 1
i = require("nvim-tree.live-filter").filter and i + 1 or i local explorer = require("nvim-tree.core").get_explorer()
if explorer and explorer.live_filter.filter then
i = i + 1
end
return node, i return node, i
end end