Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Aug 10, 2024
1 change: 0 additions & 1 deletion lua/nvim-tree.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 2 additions & 3 deletions lua/nvim-tree/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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")
Expand Down
3 changes: 1 addition & 2 deletions lua/nvim-tree/core.lua
Original file line number Diff line number Diff line change
@@ -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"

Expand Down Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions lua/nvim-tree/explorer/explore.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions lua/nvim-tree/explorer/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}
Expand All @@ -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 = {}
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
filter = nil,
}
---@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
Expand All @@ -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", {
Expand All @@ -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

Expand All @@ -101,49 +117,53 @@ 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,
})

vim.api.nvim_buf_set_keymap(overlay_bufnr, "i", "<CR>", "<cmd>stopinsert<CR>", {})
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 {
Expand All @@ -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",
Expand All @@ -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
Expand All @@ -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
3 changes: 1 addition & 2 deletions lua/nvim-tree/explorer/reload.lua
Original file line number Diff line number Diff line change
@@ -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"

Expand Down Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions lua/nvim-tree/renderer/builder.lua
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -436,15 +436,16 @@ 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)
self:insert_highlight({ "NvimTreeRootFolder" }, 0, string.len(root_name))
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)
Expand Down
5 changes: 4 additions & 1 deletion lua/nvim-tree/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you.

local explorer = require("nvim-tree.core").get_explorer()
if explorer and explorer.live_filter.filter then
i = i + 1
end
return node, i
end

Expand Down
Loading