Skip to content

Commit

Permalink
refactor(#2830): multi instance nvim-tree.marks (#2838)
Browse files Browse the repository at this point in the history
refactor(#2380): multi instance nvim-tree.marks
  • Loading branch information
alex-courtis authored Jul 21, 2024
1 parent 48a9290 commit 4e396b2
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 66 deletions.
51 changes: 39 additions & 12 deletions lua/nvim-tree/api.lua
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
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"
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"
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 5 additions & 3 deletions lua/nvim-tree/explorer/filters.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
local utils = require "nvim-tree.utils"
local marks = require "nvim-tree.marks"

local M = {
ignore_list = {},
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions lua/nvim-tree/explorer/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}

Expand All @@ -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
Expand All @@ -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)
Expand Down
21 changes: 14 additions & 7 deletions lua/nvim-tree/marks/bulk-delete.lua
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -10,21 +9,29 @@ 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()
end
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
Expand All @@ -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

Expand Down
15 changes: 10 additions & 5 deletions lua/nvim-tree/marks/bulk-move.lua
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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()
Expand Down
16 changes: 11 additions & 5 deletions lua/nvim-tree/marks/bulk-trash.lua
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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
Expand All @@ -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

Expand Down
62 changes: 36 additions & 26 deletions lua/nvim-tree/marks/init.lua
Original file line number Diff line number Diff line change
@@ -1,68 +1,78 @@
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)
require("nvim-tree.marks.bulk-trash").setup(opts)
require("nvim-tree.marks.bulk-move").setup(opts)
end

return M
return Marks
Loading

0 comments on commit 4e396b2

Please sign in to comment.