diff --git a/lua/nvim-tree/api.lua b/lua/nvim-tree/api.lua index b442f7bd..fdc1eb35 100644 --- a/lua/nvim-tree/api.lua +++ b/lua/nvim-tree/api.lua @@ -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) diff --git a/lua/nvim-tree/explorer/filters.lua b/lua/nvim-tree/explorer/filters.lua index c04d42cc..7b8be131 100644 --- a/lua/nvim-tree/explorer/filters.lua +++ b/lua/nvim-tree/explorer/filters.lua @@ -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 diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 6b150359..25ad242e 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -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) diff --git a/lua/nvim-tree/marks/bulk-delete.lua b/lua/nvim-tree/marks/bulk-delete.lua index 45dfbfff..c09bb423 100644 --- a/lua/nvim-tree/marks/bulk-delete.lua +++ b/lua/nvim-tree/marks/bulk-delete.lua @@ -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 diff --git a/lua/nvim-tree/marks/bulk-move.lua b/lua/nvim-tree/marks/bulk-move.lua index 9e6e9a9d..44c30c43 100644 --- a/lua/nvim-tree/marks/bulk-move.lua +++ b/lua/nvim-tree/marks/bulk-move.lua @@ -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() diff --git a/lua/nvim-tree/marks/bulk-trash.lua b/lua/nvim-tree/marks/bulk-trash.lua index fd2a5c3f..7e792324 100644 --- a/lua/nvim-tree/marks/bulk-trash.lua +++ b/lua/nvim-tree/marks/bulk-trash.lua @@ -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 diff --git a/lua/nvim-tree/marks/init.lua b/lua/nvim-tree/marks/init.lua index d92e43e8..c5ab5291 100644 --- a/lua/nvim-tree/marks/init.lua +++ b/lua/nvim-tree/marks/init.lua @@ -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 diff --git a/lua/nvim-tree/marks/navigation.lua b/lua/nvim-tree/marks/navigation.lua index 8ee3edbc..a960cee6 100644 --- a/lua/nvim-tree/marks/navigation.lua +++ b/lua/nvim-tree/marks/navigation.lua @@ -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 diff --git a/lua/nvim-tree/renderer/decorator/bookmarks.lua b/lua/nvim-tree/renderer/decorator/bookmarks.lua index 8692c22b..700ee8e7 100644 --- a/lua/nvim-tree/renderer/decorator/bookmarks.lua +++ b/lua/nvim-tree/renderer/decorator/bookmarks.lua @@ -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