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.lib").setup(opts)
require("nvim-tree.renderer").setup(opts)
require("nvim-tree.live-filter").setup(opts)
require("nvim-tree.marks").setup(opts)
require("nvim-tree.buffers").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 events = require "nvim-tree.events"
local help = require "nvim-tree.help"
local live_filter = require "nvim-tree.live-filter"
local marks_navigation = require "nvim-tree.marks.navigation"
local marks_bulk_delete = require "nvim-tree.marks.bulk-delete"
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.Event = events.Event
Api.live_filter.start = wrap(live_filter.start_filtering)
Api.live_filter.clear = wrap(live_filter.clear_filter)
Api.live_filter.start = wrap_explorer_member("live_filter", "start_filtering")
Api.live_filter.clear = wrap_explorer_member("live_filter", "clear_filter")
Api.marks.get = wrap_node(wrap_explorer_member("marks", "get_mark"))
Api.marks.list = wrap_explorer_member("marks", "get_marks")

View File

@ -1,6 +1,5 @@
local events = require "nvim-tree.events"
local explorer = require "nvim-tree.explorer"
local live_filter = require "nvim-tree.live-filter"
local view = require "nvim-tree.view"
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
offset = offset + 1
end
if live_filter.filter then
if TreeExplorer and TreeExplorer.live_filter.filter then
return offset + 1
end
return offset

View File

@ -2,7 +2,6 @@ local utils = require "nvim-tree.utils"
local builders = require "nvim-tree.explorer.node-builders"
local explorer_node = require "nvim-tree.explorer.node"
local git = require "nvim-tree.git"
local live_filter = require "nvim-tree.live-filter"
local log = require "nvim-tree.log"
local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON
@ -99,7 +98,7 @@ function M.explore(node, status, parent)
end
parent.sorters:sort(node.nodes)
live_filter.apply_filter(node)
parent.live_filter:apply_filter(node)
log.profile_end(profile)
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 Filters = require "nvim-tree.explorer.filters"
local Marks = require "nvim-tree.marks"
local LiveFilter = require "nvim-tree.explorer.live-filter"
local Sorters = require "nvim-tree.explorer.sorters"
local M = {}
@ -15,6 +16,9 @@ M.reload = require("nvim-tree.explorer.reload").reload
---@field absolute_path string
---@field nodes Node[]
---@field open boolean
---@field filters Filters
---@field live_filter LiveFilter
---@field sorters Sorter
---@field marks Marks
local Explorer = {}
@ -45,6 +49,7 @@ function Explorer.new(path)
}, Explorer)
explorer.watcher = watch.create_watcher(explorer)
explorer.filters = Filters:new(M.config, explorer)
explorer.live_filter = LiveFilter:new(M.config, explorer)
explorer:_load(explorer)
return explorer
end

View File

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

View File

@ -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 live_filter = require "nvim-tree.live-filter"
local git = require "nvim-tree.git"
local log = require "nvim-tree.log"
@ -183,7 +182,7 @@ function M.reload(node, git_status)
end
explorer.sorters:sort(node.nodes)
live_filter.apply_filter(node)
explorer.live_filter:apply_filter(node)
log.profile_end(profile)
return node.nodes
end

View File

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

View File

@ -112,7 +112,10 @@ function M.find_node(nodes, fn)
end)
:iterate()
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
end