refactor(#2830): multi instance nvim-tree.marks (#2838)

refactor(#2380): multi instance nvim-tree.marks
This commit is contained in:
Alexander Courtis 2024-07-21 16:12:42 +10:00 committed by GitHub
parent 48a9290757
commit 4e396b2624
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 135 additions and 66 deletions

View file

@ -1,4 +1,5 @@
local lib = require "nvim-tree.lib"
local core = require "nvim-tree.core"
local view = require "nvim-tree.view"
local utils = require "nvim-tree.utils"
local actions = require "nvim-tree.actions"
@ -6,7 +7,6 @@ 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 = require "nvim-tree.marks"
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"
@ -43,9 +43,10 @@ local Api = {
diagnostics = {},
}
--- Do nothing when setup not called.
--- Print error when setup not called.
--- f function to invoke
---@param f function
---@return fun(...) : any
local function wrap(f)
return function(...)
if vim.g.NvimTreeSetup == 1 then
@ -56,13 +57,13 @@ local function wrap(f)
end
end
---Inject the node as the first argument if absent.
---Inject the node as the first argument if present otherwise do nothing.
---@param fn function function to invoke
local function wrap_node(fn)
return function(node, ...)
node = node or lib.get_node_at_cursor()
if node then
fn(node, ...)
return fn(node, ...)
end
end
end
@ -72,10 +73,36 @@ end
local function wrap_node_or_nil(fn)
return function(node, ...)
node = node or lib.get_node_at_cursor()
fn(node, ...)
return fn(node, ...)
end
end
---Inject the explorer as the first argument if present otherwise do nothing.
---@param fn function function to invoke
---@return fun(...) : any
local function wrap_explorer(fn)
return function(...)
local explorer = core.get_explorer()
if explorer then
return fn(explorer, ...)
end
end
end
---Invoke a member's method on the singleton explorer.
---Print error when setup not called.
---@param explorer_member string explorer member name
---@param member_method string method name to invoke on member
---@return fun(...) : any
local function wrap_explorer_member(explorer_member, member_method)
return wrap(function(...)
local explorer = core.get_explorer()
if explorer then
return explorer[explorer_member][member_method](explorer[explorer_member], ...)
end
end)
end
---@class ApiTreeOpenOpts
---@field path string|nil path
---@field current_window boolean|nil default false
@ -241,13 +268,13 @@ Api.events.Event = events.Event
Api.live_filter.start = wrap(live_filter.start_filtering)
Api.live_filter.clear = wrap(live_filter.clear_filter)
Api.marks.get = wrap_node(marks.get_mark)
Api.marks.list = wrap(marks.get_marks)
Api.marks.toggle = wrap_node(marks.toggle_mark)
Api.marks.clear = wrap(marks.clear_marks)
Api.marks.bulk.delete = wrap(marks_bulk_delete.bulk_delete)
Api.marks.bulk.trash = wrap(marks_bulk_trash.bulk_trash)
Api.marks.bulk.move = wrap(marks_bulk_move.bulk_move)
Api.marks.get = wrap_node(wrap_explorer_member("marks", "get_mark"))
Api.marks.list = wrap_explorer_member("marks", "get_marks")
Api.marks.toggle = wrap_node(wrap_explorer_member("marks", "toggle_mark"))
Api.marks.clear = wrap_explorer_member("marks", "clear_marks")
Api.marks.bulk.delete = wrap_explorer(marks_bulk_delete.bulk_delete)
Api.marks.bulk.trash = wrap_explorer(marks_bulk_trash.bulk_trash)
Api.marks.bulk.move = wrap_explorer(marks_bulk_move.bulk_move)
Api.marks.navigate.next = wrap(marks_navigation.next)
Api.marks.navigate.prev = wrap(marks_navigation.prev)
Api.marks.navigate.select = wrap(marks_navigation.select)

View file

@ -1,5 +1,4 @@
local utils = require "nvim-tree.utils"
local marks = require "nvim-tree.marks"
local M = {
ignore_list = {},
@ -155,8 +154,11 @@ function M.prepare(git_status)
status.bufinfo = vim.fn.getbufinfo { buflisted = 1 }
end
for _, node in pairs(marks.get_marks()) do
status.bookmarks[node.absolute_path] = node.type
local explorer = require("nvim-tree.core").get_explorer()
if explorer then
for _, node in pairs(explorer.marks:get_marks()) do
status.bookmarks[node.absolute_path] = node.type
end
end
return status

View file

@ -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 Marks = require "nvim-tree.marks"
local M = {}
@ -12,6 +13,7 @@ M.reload = require("nvim-tree.explorer.reload").reload
---@field absolute_path string
---@field nodes Node[]
---@field open boolean
---@field marks Marks
local Explorer = {}
Explorer.__index = Explorer
@ -36,6 +38,7 @@ function Explorer.new(path)
absolute_path = path,
nodes = {},
open = true,
marks = Marks:new(),
}, Explorer)
explorer.watcher = watch.create_watcher(explorer)
explorer:_load(explorer)

View file

@ -1,4 +1,3 @@
local marks = require "nvim-tree.marks"
local utils = require "nvim-tree.utils"
local remove_file = require "nvim-tree.actions.fs.remove-file"
local notify = require "nvim-tree.notify"
@ -10,12 +9,13 @@ local M = {
--- Delete nodes; each removal will be optionally notified
---@param nodes Node[]
local function do_delete(nodes)
---@param marks Marks
local function do_delete(marks, nodes)
for _, node in pairs(nodes) do
remove_file.remove(node)
end
marks.clear_marks()
marks:clear_marks()
if not M.config.filesystem_watchers.enable then
require("nvim-tree.actions.reloaders").reload_explorer()
@ -23,8 +23,15 @@ local function do_delete(nodes)
end
--- Delete marked nodes, optionally prompting
function M.bulk_delete()
local nodes = marks.get_marks()
---@param explorer Explorer
function M.bulk_delete(explorer)
if not explorer then
return
end
local marks = explorer.marks
local nodes = marks:get_marks()
if not nodes or #nodes == 0 then
notify.warn "No bookmarksed to delete."
return
@ -36,11 +43,11 @@ function M.bulk_delete()
lib.prompt(prompt_input, prompt_select, { "", "y" }, { "No", "Yes" }, "nvimtree_bulk_delete", function(item_short)
utils.clear_prompt()
if item_short == "y" then
do_delete(nodes)
do_delete(marks, nodes)
end
end)
else
do_delete(nodes)
do_delete(marks, nodes)
end
end

View file

@ -1,4 +1,3 @@
local marks = require "nvim-tree.marks"
local core = require "nvim-tree.core"
local utils = require "nvim-tree.utils"
local rename_file = require "nvim-tree.actions.fs.rename-file"
@ -9,8 +8,14 @@ local M = {
config = {},
}
function M.bulk_move()
if #marks.get_marks() == 0 then
---@param explorer Explorer
function M.bulk_move(explorer)
if not explorer then
return
end
local marks = explorer.marks
if #marks:get_marks() == 0 then
notify.warn "No bookmarks to move."
return
end
@ -40,14 +45,14 @@ function M.bulk_move()
return
end
local nodes = marks.get_marks()
local nodes = marks:get_marks()
for _, node in pairs(nodes) do
local head = vim.fn.fnamemodify(node.absolute_path, ":t")
local to = utils.path_join { location, head }
rename_file.rename(node, to)
end
marks.clear_marks()
marks:clear_marks()
if not M.config.filesystem_watchers.enable then
require("nvim-tree.actions.reloaders").reload_explorer()

View file

@ -1,4 +1,3 @@
local marks = require "nvim-tree.marks"
local utils = require "nvim-tree.utils"
local remove_file = require "nvim-tree.actions.fs.trash"
local notify = require "nvim-tree.notify"
@ -14,12 +13,17 @@ local function do_trash(nodes)
for _, node in pairs(nodes) do
remove_file.remove(node)
end
marks.clear_marks()
end
function M.bulk_trash()
local nodes = marks.get_marks()
---@param explorer Explorer
function M.bulk_trash(explorer)
if not explorer then
return
end
local marks = explorer.marks
local nodes = marks:get_marks()
if not nodes or #nodes == 0 then
notify.warn "No bookmarks to trash."
return
@ -32,10 +36,12 @@ function M.bulk_trash()
utils.clear_prompt()
if item_short == "y" then
do_trash(nodes)
marks:clear_marks()
end
end)
else
do_trash(nodes)
marks:clear_marks()
end
end

View file

@ -1,63 +1,73 @@
local renderer = {} -- circular dependency
local NvimTreeMarks = {}
---@class Marks
---@field private marks Node[]
local Marks = {}
local M = {}
---@return Marks
function Marks:new()
local o = {}
setmetatable(o, self)
self.__index = self
---@class MinimalNode
---@field absolute_path string
o.marks = {}
---@param node Node|MinimalNode
local function add_mark(node)
NvimTreeMarks[node.absolute_path] = node
return o
end
---@private
---@param node Node
function Marks:add_mark(node)
self.marks[node.absolute_path] = node
renderer.draw()
end
---@param node Node|MinimalNode
local function remove_mark(node)
NvimTreeMarks[node.absolute_path] = nil
---@private
---@param node Node
function Marks:remove_mark(node)
self.marks[node.absolute_path] = nil
renderer.draw()
end
---@param node Node|MinimalNode
function M.toggle_mark(node)
---@param node Node
function Marks:toggle_mark(node)
if node.absolute_path == nil then
return
end
if M.get_mark(node) then
remove_mark(node)
if self:get_mark(node) then
self:remove_mark(node)
else
add_mark(node)
self:add_mark(node)
end
renderer.draw()
end
function M.clear_marks()
NvimTreeMarks = {}
function Marks:clear_marks()
self.marks = {}
renderer.draw()
end
---@param node Node|MinimalNode
---@return table|nil
function M.get_mark(node)
return node and NvimTreeMarks[node.absolute_path]
---@param node Node
---@return Node|nil
function Marks:get_mark(node)
return node and self.marks[node.absolute_path]
end
---@return table
function M.get_marks()
---@return Node[]
function Marks:get_marks()
local list = {}
for _, node in pairs(NvimTreeMarks) do
for _, node in pairs(self.marks) do
table.insert(list, node)
end
return list
end
function M.setup(opts)
function Marks.setup(opts)
renderer = require "nvim-tree.renderer"
require("nvim-tree.marks.bulk-delete").setup(opts)
@ -65,4 +75,4 @@ function M.setup(opts)
require("nvim-tree.marks.bulk-move").setup(opts)
end
return M
return Marks

View file

@ -1,6 +1,5 @@
local Iterator = require "nvim-tree.iterators.node-iterator"
local core = require "nvim-tree.core"
local Marks = require "nvim-tree.marks"
local open_file = require "nvim-tree.actions.node.open-file"
local utils = require "nvim-tree.utils"
local lib = require "nvim-tree.lib"
@ -9,10 +8,15 @@ local lib = require "nvim-tree.lib"
---@param where string
---@return Node|nil
local function get_nearest(node, where)
local explorer = core.get_explorer()
if not explorer then
return
end
local first, prev, next, last = nil, nil, nil, nil
local found = false
Iterator.builder(core.get_explorer().nodes)
Iterator.builder(explorer.nodes)
:recursor(function(n)
return n.open and n.nodes
end)
@ -22,7 +26,7 @@ local function get_nearest(node, where)
return
end
if not Marks.get_mark(n) then
if not explorer.marks:get_mark(n) then
return
end
@ -84,9 +88,14 @@ M.next = navigate_to "next"
M.prev = navigate_to "prev"
function M.select()
local explorer = core.get_explorer()
if not explorer then
return
end
local list = vim.tbl_map(function(n)
return n.absolute_path
end, Marks.get_marks())
end, explorer.marks:get_marks())
vim.ui.select(list, {
prompt = "Select a file to open or a folder to focus",
@ -94,7 +103,7 @@ function M.select()
if not choice or choice == "" then
return
end
local node = Marks.get_mark { absolute_path = choice }
local node = explorer.marks:get_mark { absolute_path = choice }
open_or_focus(node)
end)
end

View file

@ -1,4 +1,4 @@
local marks = require "nvim-tree.marks"
local core = require "nvim-tree.core"
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT
@ -34,7 +34,7 @@ end
---@param node Node
---@return HighlightedString[]|nil icons
function DecoratorBookmarks:calculate_icons(node)
if marks.get_mark(node) then
if core.get_explorer() and core.get_explorer().marks:get_mark(node) then
return { self.icon }
end
end
@ -43,7 +43,7 @@ end
---@param node Node
---@return string|nil group
function DecoratorBookmarks:calculate_highlight(node)
if self.hl_pos ~= HL_POSITION.none and marks.get_mark(node) then
if self.hl_pos ~= HL_POSITION.none and core.get_explorer() and core.get_explorer().marks:get_mark(node) then
return "NvimTreeBookmarkHL"
end
end