From ddbc033b904badc65b28d5f96e0cb9df23717284 Mon Sep 17 00:00:00 2001 From: uanela Date: Thu, 11 Jun 2026 10:07:58 +0200 Subject: [PATCH 01/12] feat: add copy absolute path with protocol into public api --- lua/nvim-tree/_meta/api/fs.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lua/nvim-tree/_meta/api/fs.lua b/lua/nvim-tree/_meta/api/fs.lua index dfab8610434..3ab3625414c 100644 --- a/lua/nvim-tree/_meta/api/fs.lua +++ b/lua/nvim-tree/_meta/api/fs.lua @@ -14,6 +14,12 @@ nvim_tree.api.fs.copy = {} ---@param node? nvim_tree.api.Node function nvim_tree.api.fs.copy.absolute_path(node) end +--- +---Copy the absolute path to the system clipboard with nvim-tree protocol. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.copy.absolute_path_with_protocol(node) end + --- ---Copy the name with extension omitted to the system clipboard. --- From c842a086a3eb0e02ca80a43c7ec99c3b2b591b4e Mon Sep 17 00:00:00 2001 From: uanela Date: Thu, 11 Jun 2026 10:08:41 +0200 Subject: [PATCH 02/12] feat: add helper get_basename into node --- lua/nvim-tree/node/init.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lua/nvim-tree/node/init.lua b/lua/nvim-tree/node/init.lua index c89d9e7171c..d2fd2c208c6 100644 --- a/lua/nvim-tree/node/init.lua +++ b/lua/nvim-tree/node/init.lua @@ -159,4 +159,14 @@ function Node:expand(expand_opts) end end +function Node:get_basename() + if self.name == ".." then + -- root + return vim.fn.fnamemodify(self.explorer.absolute_path, ":t:r") + else + -- node + return vim.fn.fnamemodify(self.name, ":r") + end +end + return Node From 058e5081cd39de8d6a3ad6776aa08daef7c6ff72 Mon Sep 17 00:00:00 2001 From: uanela Date: Thu, 11 Jun 2026 10:11:10 +0200 Subject: [PATCH 03/12] feat: add gby keymap, and allow visual mode for copy.basename|absolute_path --- lua/nvim-tree/keymap.lua | 119 ++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/lua/nvim-tree/keymap.lua b/lua/nvim-tree/keymap.lua index 044bf6c9a9b..0fc6e5bae5e 100644 --- a/lua/nvim-tree/keymap.lua +++ b/lua/nvim-tree/keymap.lua @@ -57,65 +57,66 @@ function M.on_attach_default(bufnr) end -- BEGIN_ON_ATTACH_DEFAULT - vim.keymap.set("n", "", api.tree.change_root_to_node, opts("CD")) - vim.keymap.set("n", "", api.node.open.replace_tree_buffer, opts("Open: In Place")) - vim.keymap.set("n", "", api.node.show_info_popup, opts("Info")) - vim.keymap.set("n", "", api.fs.rename_sub, opts("Rename: Omit Filename")) - vim.keymap.set("n", "", api.node.open.tab, opts("Open: New Tab")) - vim.keymap.set("n", "", api.node.open.vertical, opts("Open: Vertical Split")) - vim.keymap.set("n", "", api.node.open.horizontal, opts("Open: Horizontal Split")) - vim.keymap.set("n", "", api.node.navigate.parent_close, opts("Close Directory")) - vim.keymap.set("n", "", api.node.open.edit, opts("Open")) - vim.keymap.set({ "n", "x" }, "", api.fs.remove, opts("Delete")) - vim.keymap.set("n", "", api.node.open.preview, opts("Open Preview")) - vim.keymap.set("n", ">", api.node.navigate.sibling.next, opts("Next Sibling")) - vim.keymap.set("n", "<", api.node.navigate.sibling.prev, opts("Previous Sibling")) - vim.keymap.set("n", ".", api.node.run.cmd, opts("Run Command")) - vim.keymap.set("n", "-", api.tree.change_root_to_parent, opts("Up")) - vim.keymap.set("n", "a", api.fs.create, opts("Create File Or Directory")) - vim.keymap.set("n", "bd", api.marks.bulk.delete, opts("Delete Bookmarked")) - vim.keymap.set("n", "bt", api.marks.bulk.trash, opts("Trash Bookmarked")) - vim.keymap.set("n", "bmv", api.marks.bulk.move, opts("Move Bookmarked")) - vim.keymap.set("n", "B", api.filter.no_buffer.toggle, opts("Toggle Filter: No Buffer")) - vim.keymap.set({ "n", "x" }, "c", api.fs.copy.node, opts("Copy")) - vim.keymap.set("n", "C", api.filter.git.clean.toggle, opts("Toggle Filter: Git Clean")) - vim.keymap.set("n", "[c", api.node.navigate.git.prev, opts("Prev Git")) - vim.keymap.set("n", "]c", api.node.navigate.git.next, opts("Next Git")) - vim.keymap.set({ "n", "x" }, "d", api.fs.remove, opts("Delete")) - vim.keymap.set({ "n", "x" }, "D", api.fs.trash, opts("Trash")) - vim.keymap.set("n", "E", api.tree.expand_all, opts("Expand All")) - vim.keymap.set("n", "e", api.fs.rename_basename, opts("Rename: Basename")) - vim.keymap.set("n", "]e", api.node.navigate.diagnostics.next, opts("Next Diagnostic")) - vim.keymap.set("n", "[e", api.node.navigate.diagnostics.prev, opts("Prev Diagnostic")) - vim.keymap.set("n", "F", api.filter.live.clear, opts("Live Filter: Clear")) - vim.keymap.set("n", "f", api.filter.live.start, opts("Live Filter: Start")) - vim.keymap.set("n", "g?", api.tree.toggle_help, opts("Help")) - vim.keymap.set("n", "gy", api.fs.copy.absolute_path, opts("Copy Absolute Path")) - vim.keymap.set("n", "ge", api.fs.copy.basename, opts("Copy Basename")) - vim.keymap.set("n", "H", api.filter.dotfiles.toggle, opts("Toggle Filter: Dotfiles")) - vim.keymap.set("n", "I", api.filter.git.ignored.toggle, opts("Toggle Filter: Git Ignored")) - vim.keymap.set("n", "J", api.node.navigate.sibling.last, opts("Last Sibling")) - vim.keymap.set("n", "K", api.node.navigate.sibling.first, opts("First Sibling")) - vim.keymap.set("n", "L", api.node.open.toggle_group_empty, opts("Toggle Group Empty")) - vim.keymap.set("n", "M", api.filter.no_bookmark.toggle, opts("Toggle Filter: No Bookmark")) - vim.keymap.set({ "n", "x" }, "m", api.marks.toggle, opts("Toggle Bookmark")) - vim.keymap.set("n", "o", api.node.open.edit, opts("Open")) - vim.keymap.set("n", "O", api.node.open.no_window_picker, opts("Open: No Window Picker")) - vim.keymap.set("n", "p", api.fs.paste, opts("Paste")) - vim.keymap.set("n", "P", api.node.navigate.parent, opts("Parent Directory")) - vim.keymap.set("n", "q", api.tree.close, opts("Close")) - vim.keymap.set("n", "r", api.fs.rename, opts("Rename")) - vim.keymap.set("n", "R", api.tree.reload, opts("Refresh")) - vim.keymap.set("n", "s", api.node.run.system, opts("Run System")) - vim.keymap.set("n", "S", api.tree.search_node, opts("Search")) - vim.keymap.set("n", "u", api.fs.rename_full, opts("Rename: Full Path")) - vim.keymap.set("n", "U", api.filter.custom.toggle, opts("Toggle Filter: Custom")) - vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse All")) - vim.keymap.set({ "n", "x" }, "x", api.fs.cut, opts("Cut")) - vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name")) - vim.keymap.set("n", "Y", api.fs.copy.relative_path, opts("Copy Relative Path")) - vim.keymap.set("n", "<2-LeftMouse>", api.node.open.edit, opts("Open")) - vim.keymap.set("n", "<2-RightMouse>", api.tree.change_root_to_node, opts("CD")) + vim.keymap.set("n", "", api.tree.change_root_to_node, opts("CD")) + vim.keymap.set("n", "", api.node.open.replace_tree_buffer, opts("Open: In Place")) + vim.keymap.set("n", "", api.node.show_info_popup, opts("Info")) + vim.keymap.set("n", "", api.fs.rename_sub, opts("Rename: Omit Filename")) + vim.keymap.set("n", "", api.node.open.tab, opts("Open: New Tab")) + vim.keymap.set("n", "", api.node.open.vertical, opts("Open: Vertical Split")) + vim.keymap.set("n", "", api.node.open.horizontal, opts("Open: Horizontal Split")) + vim.keymap.set("n", "", api.node.navigate.parent_close, opts("Close Directory")) + vim.keymap.set("n", "", api.node.open.edit, opts("Open")) + vim.keymap.set({ "n", "x" }, "", api.fs.remove, opts("Delete")) + vim.keymap.set("n", "", api.node.open.preview, opts("Open Preview")) + vim.keymap.set("n", ">", api.node.navigate.sibling.next, opts("Next Sibling")) + vim.keymap.set("n", "<", api.node.navigate.sibling.prev, opts("Previous Sibling")) + vim.keymap.set("n", ".", api.node.run.cmd, opts("Run Command")) + vim.keymap.set("n", "-", api.tree.change_root_to_parent, opts("Up")) + vim.keymap.set("n", "a", api.fs.create, opts("Create File Or Directory")) + vim.keymap.set("n", "bd", api.marks.bulk.delete, opts("Delete Bookmarked")) + vim.keymap.set("n", "bt", api.marks.bulk.trash, opts("Trash Bookmarked")) + vim.keymap.set("n", "bmv", api.marks.bulk.move, opts("Move Bookmarked")) + vim.keymap.set("n", "B", api.filter.no_buffer.toggle, opts("Toggle Filter: No Buffer")) + vim.keymap.set({ "n", "x" }, "c", api.fs.copy.node, opts("Copy")) + vim.keymap.set("n", "C", api.filter.git.clean.toggle, opts("Toggle Filter: Git Clean")) + vim.keymap.set("n", "[c", api.node.navigate.git.prev, opts("Prev Git")) + vim.keymap.set("n", "]c", api.node.navigate.git.next, opts("Next Git")) + vim.keymap.set({ "n", "x" }, "d", api.fs.remove, opts("Delete")) + vim.keymap.set({ "n", "x" }, "D", api.fs.trash, opts("Trash")) + vim.keymap.set("n", "E", api.tree.expand_all, opts("Expand All")) + vim.keymap.set("n", "e", api.fs.rename_basename, opts("Rename: Basename")) + vim.keymap.set("n", "]e", api.node.navigate.diagnostics.next, opts("Next Diagnostic")) + vim.keymap.set("n", "[e", api.node.navigate.diagnostics.prev, opts("Prev Diagnostic")) + vim.keymap.set("n", "F", api.filter.live.clear, opts("Live Filter: Clear")) + vim.keymap.set("n", "f", api.filter.live.start, opts("Live Filter: Start")) + vim.keymap.set("n", "g?", api.tree.toggle_help, opts("Help")) + vim.keymap.set({ "n", "x" }, "gy", api.fs.copy.absolute_path, opts("Copy Absolute Path")) + vim.keymap.set({ "n", "x" }, "bgy", api.fs.copy.absolute_path_with_protocol, opts("Copy Absolute Path With Protocol")) + vim.keymap.set({ "n", "x" }, "ge", api.fs.copy.basename, opts("Copy Basename")) + vim.keymap.set("n", "H", api.filter.dotfiles.toggle, opts("Toggle Filter: Dotfiles")) + vim.keymap.set("n", "I", api.filter.git.ignored.toggle, opts("Toggle Filter: Git Ignored")) + vim.keymap.set("n", "J", api.node.navigate.sibling.last, opts("Last Sibling")) + vim.keymap.set("n", "K", api.node.navigate.sibling.first, opts("First Sibling")) + vim.keymap.set("n", "L", api.node.open.toggle_group_empty, opts("Toggle Group Empty")) + vim.keymap.set("n", "M", api.filter.no_bookmark.toggle, opts("Toggle Filter: No Bookmark")) + vim.keymap.set({ "n", "x" }, "m", api.marks.toggle, opts("Toggle Bookmark")) + vim.keymap.set("n", "o", api.node.open.edit, opts("Open")) + vim.keymap.set("n", "O", api.node.open.no_window_picker, opts("Open: No Window Picker")) + vim.keymap.set("n", "p", api.fs.paste, opts("Paste")) + vim.keymap.set("n", "P", api.node.navigate.parent, opts("Parent Directory")) + vim.keymap.set("n", "q", api.tree.close, opts("Close")) + vim.keymap.set("n", "r", api.fs.rename, opts("Rename")) + vim.keymap.set("n", "R", api.tree.reload, opts("Refresh")) + vim.keymap.set("n", "s", api.node.run.system, opts("Run System")) + vim.keymap.set("n", "S", api.tree.search_node, opts("Search")) + vim.keymap.set("n", "u", api.fs.rename_full, opts("Rename: Full Path")) + vim.keymap.set("n", "U", api.filter.custom.toggle, opts("Toggle Filter: Custom")) + vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse All")) + vim.keymap.set({ "n", "x" }, "x", api.fs.cut, opts("Cut")) + vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name")) + vim.keymap.set("n", "Y", api.fs.copy.relative_path, opts("Copy Relative Path")) + vim.keymap.set("n", "<2-LeftMouse>", api.node.open.edit, opts("Open")) + vim.keymap.set("n", "<2-RightMouse>", api.tree.change_root_to_node, opts("CD")) -- END_ON_ATTACH_DEFAULT end From 89edce64c1e30c5d19b9b041672b0365b64a99ce Mon Sep 17 00:00:00 2001 From: uanela Date: Thu, 11 Jun 2026 10:14:19 +0200 Subject: [PATCH 04/12] feat(clipboard): add opts for adding protocol in reg operations --- lua/nvim-tree/actions/fs/clipboard.lua | 73 +++++++++++++++++++++----- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/lua/nvim-tree/actions/fs/clipboard.lua b/lua/nvim-tree/actions/fs/clipboard.lua index e3abe5efd1f..cc7b2741ed4 100644 --- a/lua/nvim-tree/actions/fs/clipboard.lua +++ b/lua/nvim-tree/actions/fs/clipboard.lua @@ -43,6 +43,9 @@ function Clipboard:new(args) self.reg = self.explorer.opts.actions.use_system_clipboard and "+" or "1" end +---@class RegOperationOptions +---@field use_protocol? boolean + ---@param source string ---@param destination string ---@return boolean @@ -176,10 +179,20 @@ function Clipboard:bulk_clipboard(nodes, from, to, verb) self.explorer.renderer:draw() end +---@private +---@param node_or_nodes Node|Node[] +---@return boolean +function Clipboard:is_nodes_array(node_or_nodes) + if type(node_or_nodes) == "table" and node_or_nodes.is and node_or_nodes:is(Node) then + return false + end + return true +end + ---Copy one or more nodes ---@param node_or_nodes Node|Node[] function Clipboard:copy(node_or_nodes) - if type(node_or_nodes) == "table" and node_or_nodes.is and node_or_nodes:is(Node) then + if self:is_nodes_array(node_or_nodes) == false then utils.array_remove(self.data.cut, node_or_nodes) toggle(node_or_nodes, self.data.copy) self.explorer.renderer:draw() @@ -413,7 +426,14 @@ function Clipboard:print_clipboard() end ---@param content string -function Clipboard:copy_to_reg(content) +---@param opts? RegOperationOptions +function Clipboard:copy_to_reg(content, opts) + local use_protocol = opts and opts.use_protocol and true or false + + if use_protocol then + content = "nvim-tree: " .. content + end + -- manually firing TextYankPost does not set vim.v.event -- workaround: create a scratch buffer with the clipboard contents and send a yank command local temp_buf = vim.api.nvim_create_buf(false, true) @@ -437,15 +457,23 @@ function Clipboard:copy_filename(node) end end ----@param node Node -function Clipboard:copy_basename(node) - if node.name == ".." then - -- root - self:copy_to_reg(vim.fn.fnamemodify(self.explorer.absolute_path, ":t:r")) +---@param node_or_nodes Node|Node[] +---@param opts? RegOperationOptions +function Clipboard:copy_basename(node_or_nodes, opts) + local content = "" + if self:is_nodes_array(node_or_nodes) == false or #node_or_nodes == 1 then + local node = #node_or_nodes == 1 and node_or_nodes[0] or node_or_nodes + content = node:get_basename() else - -- node - self:copy_to_reg(vim.fn.fnamemodify(node.name, ":r")) + for i, node in ipairs(node_or_nodes) do + if i == 1 then + content = node:get_basename() + else + content = content .. ", " .. node:get_basename() + end + end end + self:copy_to_reg(content, opts) end ---@param node Node @@ -470,15 +498,36 @@ function Clipboard:copy_path(node) end end +---@private ---@param node Node -function Clipboard:copy_absolute_path(node) +---@return string +function Clipboard:get_absolute_path(node) if node.name == ".." then node = self.explorer end local absolute_path = node.absolute_path - local content = node.nodes ~= nil and utils.path_add_trailing(absolute_path) or absolute_path - self:copy_to_reg(content) + return node.nodes ~= nil and utils.path_add_trailing(absolute_path) or absolute_path +end + +---@param node_or_nodes Node|Node[] +---@param opts? RegOperationOptions +function Clipboard:copy_absolute_path(node_or_nodes, opts) + local content = "" + if self:is_nodes_array(node_or_nodes) == false or #node_or_nodes == 1 then + local node = #node_or_nodes == 1 and node_or_nodes[0] or node_or_nodes + content = self:get_absolute_path(node) + else + for i, node in ipairs(node_or_nodes) do + if i == 1 then + content = self:get_absolute_path(node) + else + content = content .. ", " .. self:get_absolute_path(node) + end + end + end + + self:copy_to_reg(content, opts) end ---Node is cut. Will not be copied. From b98e0c4ba4ef51c0e5443071315a6a5564d7ae4b Mon Sep 17 00:00:00 2001 From: uanela Date: Thu, 11 Jun 2026 10:15:11 +0200 Subject: [PATCH 05/12] feat(api): allow visual operation in absolute_path* --- lua/nvim-tree/api/impl.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lua/nvim-tree/api/impl.lua b/lua/nvim-tree/api/impl.lua index f17fa4ee825..efebb3ef288 100644 --- a/lua/nvim-tree/api/impl.lua +++ b/lua/nvim-tree/api/impl.lua @@ -155,8 +155,9 @@ function M.hydrate_post_setup(api) api.filter.toggle = e_(function(e) e.filters:toggle() end) api.fs.clear_clipboard = e_(function(e) e.clipboard:clear_clipboard() end) - api.fs.copy.absolute_path = en(function(e, n) e.clipboard:copy_absolute_path(n) end) - api.fs.copy.basename = en(function(e, n) e.clipboard:copy_basename(n) end) + api.fs.copy.absolute_path = ev(function(e, n) e.clipboard:copy_absolute_path(n) end) + api.fs.copy.absolute_path_with_protocol = ev(function(e, n) e.clipboard:copy_absolute_path(n, { use_protocol = true }) end) + api.fs.copy.basename = ev(function(e, n) e.clipboard:copy_basename(n) end) api.fs.copy.filename = en(function(e, n) e.clipboard:copy_filename(n) end) api.fs.copy.node = ev(function(e, n) e.clipboard:copy(n) end) api.fs.copy.relative_path = en(function(e, n) e.clipboard:copy_path(n) end) From f2269a1be749ce97e74f2a90848682fb59b5e3c0 Mon Sep 17 00:00:00 2001 From: uanela Date: Thu, 11 Jun 2026 15:41:20 +0200 Subject: [PATCH 06/12] feat: add paste with protocol to keymap+api --- lua/nvim-tree/_meta/api/fs.lua | 8 ++++++++ lua/nvim-tree/api/impl.lua | 1 + lua/nvim-tree/keymap.lua | 1 + 3 files changed, 10 insertions(+) diff --git a/lua/nvim-tree/_meta/api/fs.lua b/lua/nvim-tree/_meta/api/fs.lua index 3ab3625414c..7c5705b79bc 100644 --- a/lua/nvim-tree/_meta/api/fs.lua +++ b/lua/nvim-tree/_meta/api/fs.lua @@ -72,6 +72,14 @@ function nvim_tree.api.fs.cut(node) end ---@param node? nvim_tree.api.Node function nvim_tree.api.fs.paste(node) end +--- +---Paste nodes from the nvim-tree clipboard using protocol. +--- +---If {node} is a file it will pasted in the parent directory. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.paste_with_protocol(node) end + --- ---Print the contents of the nvim-tree clipboard. --- diff --git a/lua/nvim-tree/api/impl.lua b/lua/nvim-tree/api/impl.lua index efebb3ef288..db49404ae6c 100644 --- a/lua/nvim-tree/api/impl.lua +++ b/lua/nvim-tree/api/impl.lua @@ -164,6 +164,7 @@ function M.hydrate_post_setup(api) api.fs.create = _n(function(n) require("nvim-tree.actions.fs.create-file").fn(n) end) api.fs.cut = ev(function(e, n) e.clipboard:cut(n) end) api.fs.paste = en(function(e, n) e.clipboard:paste(n) end) + api.fs.paste_with_protocol = en(function(e, n) e.clipboard:paste(n, { use_protocol = true }) end) api.fs.print_clipboard = e_(function(e) e.clipboard:print_clipboard() end) api.fs.remove = _v(function(n) require("nvim-tree.actions.fs.remove-file").fn(n) end) api.fs.rename = _n(function(n) require("nvim-tree.actions.fs.rename-file").rename_node(n) end) diff --git a/lua/nvim-tree/keymap.lua b/lua/nvim-tree/keymap.lua index 0fc6e5bae5e..84bf4db4b44 100644 --- a/lua/nvim-tree/keymap.lua +++ b/lua/nvim-tree/keymap.lua @@ -103,6 +103,7 @@ function M.on_attach_default(bufnr) vim.keymap.set("n", "o", api.node.open.edit, opts("Open")) vim.keymap.set("n", "O", api.node.open.no_window_picker, opts("Open: No Window Picker")) vim.keymap.set("n", "p", api.fs.paste, opts("Paste")) + vim.keymap.set("n", "gp", api.fs.paste_with_protocol, opts("Paste With Protocol")) vim.keymap.set("n", "P", api.node.navigate.parent, opts("Parent Directory")) vim.keymap.set("n", "q", api.tree.close, opts("Close")) vim.keymap.set("n", "r", api.fs.rename, opts("Rename")) From cdc7b28c76f6a30e0558e9259c5bd8e9f8a7ff7d Mon Sep 17 00:00:00 2001 From: uanela Date: Thu, 11 Jun 2026 15:42:31 +0200 Subject: [PATCH 07/12] feat: add paste with protocol to clipboard --- lua/nvim-tree/actions/fs/clipboard.lua | 50 ++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/lua/nvim-tree/actions/fs/clipboard.lua b/lua/nvim-tree/actions/fs/clipboard.lua index cc7b2741ed4..7a542b3e3cb 100644 --- a/lua/nvim-tree/actions/fs/clipboard.lua +++ b/lua/nvim-tree/actions/fs/clipboard.lua @@ -9,6 +9,7 @@ local find_file = require("nvim-tree.actions.finders.find-file").fn local Class = require("nvim-tree.classic") local DirectoryNode = require("nvim-tree.node.directory") +local FileNode = require("nvim-tree.node.file") local Node = require("nvim-tree.node") ---@alias ClipboardAction "copy" | "cut" @@ -21,6 +22,7 @@ local Node = require("nvim-tree.node") ---@field private data ClipboardData ---@field private clipboard_name string ---@field private reg string +---@field private protocol string local Clipboard = Class:extend() ---@class Clipboard @@ -41,6 +43,9 @@ function Clipboard:new(args) self.clipboard_name = self.explorer.opts.actions.use_system_clipboard and "system" or "neovim" self.reg = self.explorer.opts.actions.use_system_clipboard and "+" or "1" + -- TODO + -- self.protocol = self.explorer.actions.clipboard.protocol or "nvim-tree" + self.protocol = "nvim-tree" end ---@class RegOperationOptions @@ -317,12 +322,42 @@ function Clipboard:resolve_conflicts(conflict, destination, action, action_fn) end) end +--- Transforms the copied absolute paths with protocols to node +---@private +function Clipboard:get_nodes_from_reg() + local content = vim.fn.getreg(self.reg) + + if #content == 0 then + return + end + + local prefix = self.protocol .. ": " + if content:sub(1, #prefix) ~= prefix then + return + end + + local nodes = {} + local absolute_paths = vim.split(content:sub(#prefix + 1, #content), ", ") + + for _, absolute_path in ipairs(absolute_paths) do + local node_args = { absolute_path = absolute_path, name = vim.fn.fnamemodify(absolute_path, ":t"), explorer = self.explorer } + if absolute_path:sub(-1) == "/" then + node_args.name = vim.fn.fnamemodify(absolute_path:sub(1, -2), ":t") + table.insert(nodes, DirectoryNode(node_args)) + else + table.insert(nodes, FileNode(node_args)) + end + end + return nodes +end + ---Paste cut or copy with batch conflict resolution. ---@private ---@param node Node ---@param action ClipboardAction ---@param action_fn ClipboardActionFn -function Clipboard:do_paste(node, action, action_fn) +---@param opts? RegOperationOptions +function Clipboard:do_paste(node, action, action_fn, opts) if node.name == ".." then node = self.explorer else @@ -331,7 +366,7 @@ function Clipboard:do_paste(node, action, action_fn) node = dir:last_group_node() end end - local clip = self.data[action] + local clip = opts and opts.use_protocol and self:get_nodes_from_reg() or self.data[action] if #clip == 0 then return end @@ -399,11 +434,12 @@ end ---Paste cut (if present) or copy (if present) ---@param node Node -function Clipboard:paste(node) +---@param opts? RegOperationOptions +function Clipboard:paste(node, opts) if self.data.cut[1] ~= nil then - self:do_paste(node, "cut", do_cut) - elseif self.data.copy[1] ~= nil then - self:do_paste(node, "copy", do_copy) + self:do_paste(node, "cut", do_cut, opts) + elseif self.data.copy[1] ~= nil or opts and opts.use_protocol then + self:do_paste(node, "copy", do_copy, opts) end end @@ -431,7 +467,7 @@ function Clipboard:copy_to_reg(content, opts) local use_protocol = opts and opts.use_protocol and true or false if use_protocol then - content = "nvim-tree: " .. content + content = self.protocol .. ": " .. content end -- manually firing TextYankPost does not set vim.v.event From 38ada4688120ff3d545b67e52ffa51ed997e1e85 Mon Sep 17 00:00:00 2001 From: uanela Date: Thu, 11 Jun 2026 16:34:57 +0200 Subject: [PATCH 08/12] feat: add configurable clipboard protocol --- lua/nvim-tree/_meta/config/actions.lua | 10 +++++++++- lua/nvim-tree/actions/fs/clipboard.lua | 4 +--- lua/nvim-tree/config.lua | 3 +++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lua/nvim-tree/_meta/config/actions.lua b/lua/nvim-tree/_meta/config/actions.lua index 012f4c364d9..066a50a443d 100644 --- a/lua/nvim-tree/_meta/config/actions.lua +++ b/lua/nvim-tree/_meta/config/actions.lua @@ -9,6 +9,9 @@ error("Cannot require a meta file") ---(default: `true`) ---@field use_system_clipboard? boolean --- +---[nvim_tree.config.actions.clipboard] +---@field clipboard? nvim_tree.config.actions.clipboard +--- ---[nvim_tree.config.actions.change_dir] ---@field change_dir? nvim_tree.config.actions.change_dir --- @@ -24,7 +27,12 @@ error("Cannot require a meta file") ---[nvim_tree.config.actions.remove_file] ---@field remove_file? nvim_tree.config.actions.remove_file - +--- Customizes nvim-tree clipboard behaviour +---@class nvim_tree.config.actions.clipboard +--- +---Change the protocol prefix to be used on multiple nvim instances operations +---(default: `nvim-tree`) +---@field protocol? string --- vim [current-directory] behaviour ---@class nvim_tree.config.actions.change_dir diff --git a/lua/nvim-tree/actions/fs/clipboard.lua b/lua/nvim-tree/actions/fs/clipboard.lua index 7a542b3e3cb..2e9e8365faf 100644 --- a/lua/nvim-tree/actions/fs/clipboard.lua +++ b/lua/nvim-tree/actions/fs/clipboard.lua @@ -43,9 +43,7 @@ function Clipboard:new(args) self.clipboard_name = self.explorer.opts.actions.use_system_clipboard and "system" or "neovim" self.reg = self.explorer.opts.actions.use_system_clipboard and "+" or "1" - -- TODO - -- self.protocol = self.explorer.actions.clipboard.protocol or "nvim-tree" - self.protocol = "nvim-tree" + self.protocol = self.explorer.opts.actions.clipboard.protocol or "nvim-tree" end ---@class RegOperationOptions diff --git a/lua/nvim-tree/config.lua b/lua/nvim-tree/config.lua index 24d87c389a2..3a39d283657 100644 --- a/lua/nvim-tree/config.lua +++ b/lua/nvim-tree/config.lua @@ -232,6 +232,9 @@ M.d = { -- config-default-start }, actions = { use_system_clipboard = true, + clipboard = { + protocol = "nvim-tree" + }, change_dir = { enable = true, global = false, From b9e9b7a67c690782e80474fb2636ab0f4200e952 Mon Sep 17 00:00:00 2001 From: uanela Date: Thu, 11 Jun 2026 16:36:20 +0200 Subject: [PATCH 09/12] fix: filter descendant nodes on copy_absolute_path_with_protocol --- lua/nvim-tree/actions/fs/clipboard.lua | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lua/nvim-tree/actions/fs/clipboard.lua b/lua/nvim-tree/actions/fs/clipboard.lua index 2e9e8365faf..1fd17c720c1 100644 --- a/lua/nvim-tree/actions/fs/clipboard.lua +++ b/lua/nvim-tree/actions/fs/clipboard.lua @@ -207,7 +207,7 @@ end ---Cut one or more nodes ---@param node_or_nodes Node|Node[] function Clipboard:cut(node_or_nodes) - if type(node_or_nodes) == "table" and node_or_nodes.is and node_or_nodes:is(Node) then + if self:is_nodes_array(node_or_nodes) == false then utils.array_remove(self.data.copy, node_or_nodes) toggle(node_or_nodes, self.data.cut) self.explorer.renderer:draw() @@ -461,7 +461,8 @@ end ---@param content string ---@param opts? RegOperationOptions -function Clipboard:copy_to_reg(content, opts) +---@param msg? string +function Clipboard:copy_to_reg(content, opts, msg) local use_protocol = opts and opts.use_protocol and true or false if use_protocol then @@ -477,7 +478,7 @@ function Clipboard:copy_to_reg(content, opts) end) vim.api.nvim_buf_delete(temp_buf, {}) - notify.info(string.format("Copied %s to %s clipboard!", content, self.clipboard_name)) + notify.info(msg or string.format("Copied %s to %s clipboard!", content, self.clipboard_name)) end ---@param node Node @@ -548,10 +549,12 @@ end ---@param opts? RegOperationOptions function Clipboard:copy_absolute_path(node_or_nodes, opts) local content = "" - if self:is_nodes_array(node_or_nodes) == false or #node_or_nodes == 1 then + local is_single = self:is_nodes_array(node_or_nodes) == false or #node_or_nodes == 1 + if is_single then local node = #node_or_nodes == 1 and node_or_nodes[0] or node_or_nodes content = self:get_absolute_path(node) else + node_or_nodes = utils.filter_descendant_nodes(node_or_nodes) for i, node in ipairs(node_or_nodes) do if i == 1 then content = self:get_absolute_path(node) @@ -561,7 +564,7 @@ function Clipboard:copy_absolute_path(node_or_nodes, opts) end end - self:copy_to_reg(content, opts) + self:copy_to_reg(content, opts, string.format("%s nodes copied to register", is_single and #node_or_nodes or 1)) end ---Node is cut. Will not be copied. From 877e726a77eecdc02fdf40317c7516655f4b4063 Mon Sep 17 00:00:00 2001 From: uanela Date: Thu, 11 Jun 2026 16:57:54 +0200 Subject: [PATCH 10/12] refactor: change clip protocol keymaps to bgy and bgp --- lua/nvim-tree/keymap.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/nvim-tree/keymap.lua b/lua/nvim-tree/keymap.lua index 84bf4db4b44..d7c288538af 100644 --- a/lua/nvim-tree/keymap.lua +++ b/lua/nvim-tree/keymap.lua @@ -91,7 +91,7 @@ function M.on_attach_default(bufnr) vim.keymap.set("n", "f", api.filter.live.start, opts("Live Filter: Start")) vim.keymap.set("n", "g?", api.tree.toggle_help, opts("Help")) vim.keymap.set({ "n", "x" }, "gy", api.fs.copy.absolute_path, opts("Copy Absolute Path")) - vim.keymap.set({ "n", "x" }, "bgy", api.fs.copy.absolute_path_with_protocol, opts("Copy Absolute Path With Protocol")) + vim.keymap.set({ "n", "x" }, "bgy", api.fs.copy.absolute_path_with_protocol, opts("Copy With Protocol")) vim.keymap.set({ "n", "x" }, "ge", api.fs.copy.basename, opts("Copy Basename")) vim.keymap.set("n", "H", api.filter.dotfiles.toggle, opts("Toggle Filter: Dotfiles")) vim.keymap.set("n", "I", api.filter.git.ignored.toggle, opts("Toggle Filter: Git Ignored")) @@ -103,7 +103,7 @@ function M.on_attach_default(bufnr) vim.keymap.set("n", "o", api.node.open.edit, opts("Open")) vim.keymap.set("n", "O", api.node.open.no_window_picker, opts("Open: No Window Picker")) vim.keymap.set("n", "p", api.fs.paste, opts("Paste")) - vim.keymap.set("n", "gp", api.fs.paste_with_protocol, opts("Paste With Protocol")) + vim.keymap.set("n", "bgp", api.fs.paste_with_protocol, opts("Paste With Protocol")) vim.keymap.set("n", "P", api.node.navigate.parent, opts("Parent Directory")) vim.keymap.set("n", "q", api.tree.close, opts("Close")) vim.keymap.set("n", "r", api.fs.rename, opts("Rename")) From 885b4d9ec315f97729de77256d38330202c692d6 Mon Sep 17 00:00:00 2001 From: uanela Date: Thu, 11 Jun 2026 16:59:17 +0200 Subject: [PATCH 11/12] wip --- doc/nvim-tree-lua.txt | 589 ++++++++++++++++++++++-------------------- 1 file changed, 310 insertions(+), 279 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 9892b524591..b7c29f5c037 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -142,8 +142,9 @@ Show the mappings: `g?` `F` n Live Filter: Clear |nvim_tree.api.filter.live.clear()| `f` n Live Filter: Start |nvim_tree.api.filter.live.start()| `g?` n Help |nvim_tree.api.tree.toggle_help()| - `gy` n Copy Absolute Path |nvim_tree.api.fs.copy.absolute_path()| - `ge` n Copy Basename |nvim_tree.api.fs.copy.basename()| + `gy` nx Copy Absolute Path |nvim_tree.api.fs.copy.absolute_path()| + `bgy` nx Copy With Protocol |nvim_tree.api.fs.copy.absolute_path_with_protocol()| + `ge` nx Copy Basename |nvim_tree.api.fs.copy.basename()| `H` n Toggle Filter: Dotfiles |nvim_tree.api.filter.dotfiles.toggle()| `I` n Toggle Filter: Git Ignored |nvim_tree.api.filter.git.ignored.toggle()| `J` n Last Sibling |nvim_tree.api.node.navigate.sibling.last()| @@ -154,6 +155,7 @@ Show the mappings: `g?` `o` n Open |nvim_tree.api.node.open.edit()| `O` n Open: No Window Picker |nvim_tree.api.node.open.no_window_picker()| `p` n Paste |nvim_tree.api.fs.paste()| + `bgp` n Paste With Protocol |nvim_tree.api.fs.paste_with_protocol()| `P` n Parent Directory |nvim_tree.api.node.navigate.parent()| `q` n Close |nvim_tree.api.tree.close()| `r` n Rename |nvim_tree.api.fs.rename()| @@ -402,65 +404,67 @@ You are encouraged to copy these to your {on_attach} function. >lua end -- BEGIN_ON_ATTACH_DEFAULT - vim.keymap.set("n", "", api.tree.change_root_to_node, opts("CD")) - vim.keymap.set("n", "", api.node.open.replace_tree_buffer, opts("Open: In Place")) - vim.keymap.set("n", "", api.node.show_info_popup, opts("Info")) - vim.keymap.set("n", "", api.fs.rename_sub, opts("Rename: Omit Filename")) - vim.keymap.set("n", "", api.node.open.tab, opts("Open: New Tab")) - vim.keymap.set("n", "", api.node.open.vertical, opts("Open: Vertical Split")) - vim.keymap.set("n", "", api.node.open.horizontal, opts("Open: Horizontal Split")) - vim.keymap.set("n", "", api.node.navigate.parent_close, opts("Close Directory")) - vim.keymap.set("n", "", api.node.open.edit, opts("Open")) - vim.keymap.set({ "n", "x" }, "", api.fs.remove, opts("Delete")) - vim.keymap.set("n", "", api.node.open.preview, opts("Open Preview")) - vim.keymap.set("n", ">", api.node.navigate.sibling.next, opts("Next Sibling")) - vim.keymap.set("n", "<", api.node.navigate.sibling.prev, opts("Previous Sibling")) - vim.keymap.set("n", ".", api.node.run.cmd, opts("Run Command")) - vim.keymap.set("n", "-", api.tree.change_root_to_parent, opts("Up")) - vim.keymap.set("n", "a", api.fs.create, opts("Create File Or Directory")) - vim.keymap.set("n", "bd", api.marks.bulk.delete, opts("Delete Bookmarked")) - vim.keymap.set("n", "bt", api.marks.bulk.trash, opts("Trash Bookmarked")) - vim.keymap.set("n", "bmv", api.marks.bulk.move, opts("Move Bookmarked")) - vim.keymap.set("n", "B", api.filter.no_buffer.toggle, opts("Toggle Filter: No Buffer")) - vim.keymap.set({ "n", "x" }, "c", api.fs.copy.node, opts("Copy")) - vim.keymap.set("n", "C", api.filter.git.clean.toggle, opts("Toggle Filter: Git Clean")) - vim.keymap.set("n", "[c", api.node.navigate.git.prev, opts("Prev Git")) - vim.keymap.set("n", "]c", api.node.navigate.git.next, opts("Next Git")) - vim.keymap.set({ "n", "x" }, "d", api.fs.remove, opts("Delete")) - vim.keymap.set({ "n", "x" }, "D", api.fs.trash, opts("Trash")) - vim.keymap.set("n", "E", api.tree.expand_all, opts("Expand All")) - vim.keymap.set("n", "e", api.fs.rename_basename, opts("Rename: Basename")) - vim.keymap.set("n", "]e", api.node.navigate.diagnostics.next, opts("Next Diagnostic")) - vim.keymap.set("n", "[e", api.node.navigate.diagnostics.prev, opts("Prev Diagnostic")) - vim.keymap.set("n", "F", api.filter.live.clear, opts("Live Filter: Clear")) - vim.keymap.set("n", "f", api.filter.live.start, opts("Live Filter: Start")) - vim.keymap.set("n", "g?", api.tree.toggle_help, opts("Help")) - vim.keymap.set("n", "gy", api.fs.copy.absolute_path, opts("Copy Absolute Path")) - vim.keymap.set("n", "ge", api.fs.copy.basename, opts("Copy Basename")) - vim.keymap.set("n", "H", api.filter.dotfiles.toggle, opts("Toggle Filter: Dotfiles")) - vim.keymap.set("n", "I", api.filter.git.ignored.toggle, opts("Toggle Filter: Git Ignored")) - vim.keymap.set("n", "J", api.node.navigate.sibling.last, opts("Last Sibling")) - vim.keymap.set("n", "K", api.node.navigate.sibling.first, opts("First Sibling")) - vim.keymap.set("n", "L", api.node.open.toggle_group_empty, opts("Toggle Group Empty")) - vim.keymap.set("n", "M", api.filter.no_bookmark.toggle, opts("Toggle Filter: No Bookmark")) - vim.keymap.set({ "n", "x" }, "m", api.marks.toggle, opts("Toggle Bookmark")) - vim.keymap.set("n", "o", api.node.open.edit, opts("Open")) - vim.keymap.set("n", "O", api.node.open.no_window_picker, opts("Open: No Window Picker")) - vim.keymap.set("n", "p", api.fs.paste, opts("Paste")) - vim.keymap.set("n", "P", api.node.navigate.parent, opts("Parent Directory")) - vim.keymap.set("n", "q", api.tree.close, opts("Close")) - vim.keymap.set("n", "r", api.fs.rename, opts("Rename")) - vim.keymap.set("n", "R", api.tree.reload, opts("Refresh")) - vim.keymap.set("n", "s", api.node.run.system, opts("Run System")) - vim.keymap.set("n", "S", api.tree.search_node, opts("Search")) - vim.keymap.set("n", "u", api.fs.rename_full, opts("Rename: Full Path")) - vim.keymap.set("n", "U", api.filter.custom.toggle, opts("Toggle Filter: Custom")) - vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse All")) - vim.keymap.set({ "n", "x" }, "x", api.fs.cut, opts("Cut")) - vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name")) - vim.keymap.set("n", "Y", api.fs.copy.relative_path, opts("Copy Relative Path")) - vim.keymap.set("n", "<2-LeftMouse>", api.node.open.edit, opts("Open")) - vim.keymap.set("n", "<2-RightMouse>", api.tree.change_root_to_node, opts("CD")) + vim.keymap.set("n", "", api.tree.change_root_to_node, opts("CD")) + vim.keymap.set("n", "", api.node.open.replace_tree_buffer, opts("Open: In Place")) + vim.keymap.set("n", "", api.node.show_info_popup, opts("Info")) + vim.keymap.set("n", "", api.fs.rename_sub, opts("Rename: Omit Filename")) + vim.keymap.set("n", "", api.node.open.tab, opts("Open: New Tab")) + vim.keymap.set("n", "", api.node.open.vertical, opts("Open: Vertical Split")) + vim.keymap.set("n", "", api.node.open.horizontal, opts("Open: Horizontal Split")) + vim.keymap.set("n", "", api.node.navigate.parent_close, opts("Close Directory")) + vim.keymap.set("n", "", api.node.open.edit, opts("Open")) + vim.keymap.set({ "n", "x" }, "", api.fs.remove, opts("Delete")) + vim.keymap.set("n", "", api.node.open.preview, opts("Open Preview")) + vim.keymap.set("n", ">", api.node.navigate.sibling.next, opts("Next Sibling")) + vim.keymap.set("n", "<", api.node.navigate.sibling.prev, opts("Previous Sibling")) + vim.keymap.set("n", ".", api.node.run.cmd, opts("Run Command")) + vim.keymap.set("n", "-", api.tree.change_root_to_parent, opts("Up")) + vim.keymap.set("n", "a", api.fs.create, opts("Create File Or Directory")) + vim.keymap.set("n", "bd", api.marks.bulk.delete, opts("Delete Bookmarked")) + vim.keymap.set("n", "bt", api.marks.bulk.trash, opts("Trash Bookmarked")) + vim.keymap.set("n", "bmv", api.marks.bulk.move, opts("Move Bookmarked")) + vim.keymap.set("n", "B", api.filter.no_buffer.toggle, opts("Toggle Filter: No Buffer")) + vim.keymap.set({ "n", "x" }, "c", api.fs.copy.node, opts("Copy")) + vim.keymap.set("n", "C", api.filter.git.clean.toggle, opts("Toggle Filter: Git Clean")) + vim.keymap.set("n", "[c", api.node.navigate.git.prev, opts("Prev Git")) + vim.keymap.set("n", "]c", api.node.navigate.git.next, opts("Next Git")) + vim.keymap.set({ "n", "x" }, "d", api.fs.remove, opts("Delete")) + vim.keymap.set({ "n", "x" }, "D", api.fs.trash, opts("Trash")) + vim.keymap.set("n", "E", api.tree.expand_all, opts("Expand All")) + vim.keymap.set("n", "e", api.fs.rename_basename, opts("Rename: Basename")) + vim.keymap.set("n", "]e", api.node.navigate.diagnostics.next, opts("Next Diagnostic")) + vim.keymap.set("n", "[e", api.node.navigate.diagnostics.prev, opts("Prev Diagnostic")) + vim.keymap.set("n", "F", api.filter.live.clear, opts("Live Filter: Clear")) + vim.keymap.set("n", "f", api.filter.live.start, opts("Live Filter: Start")) + vim.keymap.set("n", "g?", api.tree.toggle_help, opts("Help")) + vim.keymap.set({ "n", "x" }, "gy", api.fs.copy.absolute_path, opts("Copy Absolute Path")) + vim.keymap.set({ "n", "x" }, "bgy", api.fs.copy.absolute_path_with_protocol, opts("Copy With Protocol")) + vim.keymap.set({ "n", "x" }, "ge", api.fs.copy.basename, opts("Copy Basename")) + vim.keymap.set("n", "H", api.filter.dotfiles.toggle, opts("Toggle Filter: Dotfiles")) + vim.keymap.set("n", "I", api.filter.git.ignored.toggle, opts("Toggle Filter: Git Ignored")) + vim.keymap.set("n", "J", api.node.navigate.sibling.last, opts("Last Sibling")) + vim.keymap.set("n", "K", api.node.navigate.sibling.first, opts("First Sibling")) + vim.keymap.set("n", "L", api.node.open.toggle_group_empty, opts("Toggle Group Empty")) + vim.keymap.set("n", "M", api.filter.no_bookmark.toggle, opts("Toggle Filter: No Bookmark")) + vim.keymap.set({ "n", "x" }, "m", api.marks.toggle, opts("Toggle Bookmark")) + vim.keymap.set("n", "o", api.node.open.edit, opts("Open")) + vim.keymap.set("n", "O", api.node.open.no_window_picker, opts("Open: No Window Picker")) + vim.keymap.set("n", "p", api.fs.paste, opts("Paste")) + vim.keymap.set("n", "bgp", api.fs.paste_with_protocol, opts("Paste With Protocol")) + vim.keymap.set("n", "P", api.node.navigate.parent, opts("Parent Directory")) + vim.keymap.set("n", "q", api.tree.close, opts("Close")) + vim.keymap.set("n", "r", api.fs.rename, opts("Rename")) + vim.keymap.set("n", "R", api.tree.reload, opts("Refresh")) + vim.keymap.set("n", "s", api.node.run.system, opts("Run System")) + vim.keymap.set("n", "S", api.tree.search_node, opts("Search")) + vim.keymap.set("n", "u", api.fs.rename_full, opts("Rename: Full Path")) + vim.keymap.set("n", "U", api.filter.custom.toggle, opts("Toggle Filter: Custom")) + vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse All")) + vim.keymap.set({ "n", "x" }, "x", api.fs.cut, opts("Cut")) + vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name")) + vim.keymap.set("n", "Y", api.fs.copy.relative_path, opts("Copy Relative Path")) + vim.keymap.set("n", "<2-LeftMouse>", api.node.open.edit, opts("Open")) + vim.keymap.set("n", "<2-RightMouse>", api.tree.change_root_to_node, opts("CD")) -- END_ON_ATTACH_DEFAULT < Alternatively, you may apply these default mappings from your @@ -1021,59 +1025,59 @@ Config *nvim-tree-config* telescope-ui-select.nvim Fields: ~ - • {on_attach}? (`"default"|(fun(bufnr: integer))`) - (default: `default`) - • {hijack_cursor}? (`boolean`) (default: `false`) + • {actions}? (`nvim_tree.config.actions`) + |nvim_tree.config.actions| • {auto_reload_on_write}? (`boolean`) (default: `true`) + • {bookmarks}? (`nvim_tree.config.bookmarks`) + |nvim_tree.config.bookmarks| + • {diagnostics}? (`nvim_tree.config.diagnostics`) + |nvim_tree.config.diagnostics| • {disable_netrw}? (`boolean`) (default: `false`) + • {experimental}? (`nvim_tree.config.experimental`) + |nvim_tree.config.experimental| + • {filesystem_watchers}? (`nvim_tree.config.filesystem_watchers`) + |nvim_tree.config.filesystem_watchers| + • {filters}? (`nvim_tree.config.filters`) + |nvim_tree.config.filters| + • {git}? (`nvim_tree.config.git`) + |nvim_tree.config.git| + • {help}? (`nvim_tree.config.help`) + |nvim_tree.config.help| + • {hijack_cursor}? (`boolean`) (default: `false`) + • {hijack_directories}? (`nvim_tree.config.hijack_directories`) + |nvim_tree.config.hijack_directories| • {hijack_netrw}? (`boolean`) (default: `true`) • {hijack_unnamed_buffer_when_opening}? (`boolean`) (default: `false`) - • {root_dirs}? (`string[]`) (default: `{}`) + • {live_filter}? (`nvim_tree.config.live_filter`) + |nvim_tree.config.live_filter| + • {log}? (`nvim_tree.config.log`) + |nvim_tree.config.log| + • {modified}? (`nvim_tree.config.modified`) + |nvim_tree.config.modified| + • {notify}? (`nvim_tree.config.notify`) + |nvim_tree.config.notify| + • {on_attach}? (`"default"|(fun(bufnr: integer))`) + (default: `default`) • {prefer_startup_root}? (`boolean`) (default: `false`) - • {sync_root_with_cwd}? (`boolean`) (default: `false`) • {reload_on_bufenter}? (`boolean`) (default: `false`) + • {renderer}? (`nvim_tree.config.renderer`) + |nvim_tree.config.renderer| • {respect_buf_cwd}? (`boolean`) (default: `false`) + • {root_dirs}? (`string[]`) (default: `{}`) • {select_prompts}? (`boolean`) (default: `false`) • {sort}? (`nvim_tree.config.sort`) |nvim_tree.config.sort| - • {view}? (`nvim_tree.config.view`) - |nvim_tree.config.view| - • {renderer}? (`nvim_tree.config.renderer`) - |nvim_tree.config.renderer| - • {hijack_directories}? (`nvim_tree.config.hijack_directories`) - |nvim_tree.config.hijack_directories| - • {update_focused_file}? (`nvim_tree.config.update_focused_file`) - |nvim_tree.config.update_focused_file| - • {git}? (`nvim_tree.config.git`) - |nvim_tree.config.git| - • {diagnostics}? (`nvim_tree.config.diagnostics`) - |nvim_tree.config.diagnostics| - • {modified}? (`nvim_tree.config.modified`) - |nvim_tree.config.modified| - • {filters}? (`nvim_tree.config.filters`) - |nvim_tree.config.filters| - • {live_filter}? (`nvim_tree.config.live_filter`) - |nvim_tree.config.live_filter| - • {filesystem_watchers}? (`nvim_tree.config.filesystem_watchers`) - |nvim_tree.config.filesystem_watchers| - • {actions}? (`nvim_tree.config.actions`) - |nvim_tree.config.actions| - • {trash}? (`nvim_tree.config.trash`) - |nvim_tree.config.trash| + • {sync_root_with_cwd}? (`boolean`) (default: `false`) • {tab}? (`nvim_tree.config.tab`) |nvim_tree.config.tab| - • {bookmarks}? (`nvim_tree.config.bookmarks`) - |nvim_tree.config.bookmarks| - • {notify}? (`nvim_tree.config.notify`) - |nvim_tree.config.notify| - • {help}? (`nvim_tree.config.help`) - |nvim_tree.config.help| + • {trash}? (`nvim_tree.config.trash`) + |nvim_tree.config.trash| • {ui}? (`nvim_tree.config.ui`) |nvim_tree.config.ui| - • {experimental}? (`nvim_tree.config.experimental`) - |nvim_tree.config.experimental| - • {log}? (`nvim_tree.config.log`) - |nvim_tree.config.log| + • {update_focused_file}? (`nvim_tree.config.update_focused_file`) + |nvim_tree.config.update_focused_file| + • {view}? (`nvim_tree.config.view`) + |nvim_tree.config.view| ============================================================================== Config: sort *nvim-tree-config-sort* @@ -1105,13 +1109,13 @@ Config: sort *nvim-tree-config-sort* {sorter} may be a function that returns a |nvim_tree.config.sort.Sorter| Fields: ~ - • {sorter}? (`nvim_tree.config.sort.Sorter|(fun(nodes: nvim_tree.api.Node[]): nvim_tree.config.sort.Sorter?)`) - (default: `"name"`) - • {folders_first}? (`boolean`, default: `true`) Sort folders before - files. Has no effect when {sorter} is a function. • {files_first}? (`boolean`, default: `false`) Sort files before folders. Has no effect when {sorter} is a function. Overrides {folders_first}. + • {folders_first}? (`boolean`, default: `true`) Sort folders before + files. Has no effect when {sorter} is a function. + • {sorter}? (`nvim_tree.config.sort.Sorter|(fun(nodes: nvim_tree.api.Node[]): nvim_tree.config.sort.Sorter?)`) + (default: `"name"`) ============================================================================== Config: view *nvim-tree-config-view* @@ -1145,22 +1149,22 @@ Config: view *nvim-tree-config-view* refresh operations. Increase if you experience performance issues around screen refresh. - • {side}? (`"left"|"right"`) (default: `"left"`) + • {float}? (`nvim_tree.config.view.float`) + |nvim_tree.config.view.float| + • {number}? (`boolean`, default: `false`) + |'number'| • {preserve_window_proportions}? (`boolean`, default: `false`) Preserves window proportions when opening a file. If `false`, the height and width of windows other than nvim-tree will be equalized. - • {number}? (`boolean`, default: `false`) - |'number'| • {relativenumber}? (`boolean`, default: `false`) |'relativenumber'| + • {side}? (`"left"|"right"`) (default: `"left"`) • {signcolumn}? (`"yes"|"auto"|"no"`, default: `"yes"`) |'signcolumn'| • {width}? (`nvim_tree.config.view.width.spec|nvim_tree.config.view.width`) (default: `30`) - • {float}? (`nvim_tree.config.view.float`) - |nvim_tree.config.view.float| *nvim_tree.config.view.float* Configure floating window behaviour @@ -1178,22 +1182,22 @@ Config: view *nvim-tree-config-view* Fields: ~ • {enable}? (`boolean`) (default: `false`) - • {quit_on_focus_loss}? (`boolean`, default: `true`) Close the floating - window when it loses focus. • {open_win_config}? (`vim.api.keyset.win_config|(fun(): vim.api.keyset.win_config)`) (default: `{ relative = "editor", border = "rounded", width = 30, height = 30, row = 1, col = 1, }`) + • {quit_on_focus_loss}? (`boolean`, default: `true`) Close the floating + window when it loses focus. *nvim_tree.config.view.width* Configure dynamic width based on longest line. Fields: ~ - • {min}? (`nvim_tree.config.view.width.spec`) (default: - `30`) - • {max}? (`nvim_tree.config.view.width.spec`, default: `-1`) - -1 for unbounded. • {lines_excluded}? (`("root")[]`, default: `{ "root" }`) Exclude these lines when computing width. + • {max}? (`nvim_tree.config.view.width.spec`, default: `-1`) + -1 for unbounded. + • {min}? (`nvim_tree.config.view.width.spec`) (default: + `30`) • {padding}? (`nvim_tree.config.view.width.spec`, default: `1`) Extra padding to the right. @@ -1258,46 +1262,46 @@ Config: renderer *nvim-tree-config-renderer* • {add_trailing}? (`boolean`, default: `false`) Appends a trailing slash to folder and symlink folder target names. + • {decorators}? (`nvim_tree.config.renderer.decorator[]`, default: `{ "Git", "Open", "Hidden", "Modified", "Bookmark", "Diagnostics", "Copied", "Cut", }`) + List in order of additive precedence. + • {full_name}? (`boolean`, default: `false`) Display nodes + whose name length is wider than the width + of nvim-tree window in floating window. • {group_empty}? (`boolean|(fun(relative_path: string): string)`, default: `false`) Compact folders that only contain a single folder into one node. Function variant takes the relative path of grouped folders and returns a string to be displayed. - • {full_name}? (`boolean`, default: `false`) Display nodes - whose name length is wider than the width - of nvim-tree window in floating window. - • {root_folder_label}? (`nvim_tree.config.renderer.root_folder_label`, default: `":~:s?$?/..?"`) - |nvim_tree.config.renderer.root_folder_label| - • {indent_width}? (`integer`, default: `2`) Number of spaces - for each tree nesting level. Minimum 1. • {hidden_display}? (`nvim_tree.config.renderer.hidden_display`, default: `none`) |nvim_tree.config.renderer.hidden_display| - • {symlink_destination}? (`boolean`, default: `true`) Appends an - arrow followed by the target of the - symlink. - • {decorators}? (`nvim_tree.config.renderer.decorator[]`, default: `{ "Git", "Open", "Hidden", "Modified", "Bookmark", "Diagnostics", "Copied", "Cut", }`) - List in order of additive precedence. - • {highlight_git}? (`nvim_tree.config.renderer.highlight`) + • {highlight_bookmarks}? (`nvim_tree.config.renderer.highlight`) (default: `"none"`) - • {highlight_opened_files}? (`nvim_tree.config.renderer.highlight`) + • {highlight_clipboard}? (`nvim_tree.config.renderer.highlight`) + (default: `"name"`) + • {highlight_diagnostics}? (`nvim_tree.config.renderer.highlight`) + (default: `"none"`) + • {highlight_git}? (`nvim_tree.config.renderer.highlight`) (default: `"none"`) • {highlight_hidden}? (`nvim_tree.config.renderer.highlight`) (default: `"none"`) • {highlight_modified}? (`nvim_tree.config.renderer.highlight`) (default: `"none"`) - • {highlight_bookmarks}? (`nvim_tree.config.renderer.highlight`) - (default: `"none"`) - • {highlight_diagnostics}? (`nvim_tree.config.renderer.highlight`) + • {highlight_opened_files}? (`nvim_tree.config.renderer.highlight`) (default: `"none"`) - • {highlight_clipboard}? (`nvim_tree.config.renderer.highlight`) - (default: `"name"`) + • {icons}? (`nvim_tree.config.renderer.icons`) + |nvim_tree.config.renderer.icons| + • {indent_markers}? (`nvim_tree.config.renderer.indent_markers`) + |nvim_tree.config.renderer.indent_markers| + • {indent_width}? (`integer`, default: `2`) Number of spaces + for each tree nesting level. Minimum 1. + • {root_folder_label}? (`nvim_tree.config.renderer.root_folder_label`, default: `":~:s?$?/..?"`) + |nvim_tree.config.renderer.root_folder_label| • {special_files}? (`string[]`, default: `{ "Cargo.toml", "Makefile", "README.md", "readme.md", }`) Highlight special files and directories with `NvimTreeSpecial*`. - • {indent_markers}? (`nvim_tree.config.renderer.indent_markers`) - |nvim_tree.config.renderer.indent_markers| - • {icons}? (`nvim_tree.config.renderer.icons`) - |nvim_tree.config.renderer.icons| + • {symlink_destination}? (`boolean`, default: `true`) Appends an + arrow followed by the target of the + symlink. *nvim_tree.config.renderer.hidden_stats* Number of hidden nodes in a directory by reason: the filter that hid the @@ -1338,29 +1342,29 @@ Config: renderer *nvim-tree-config-renderer* • `"right_align"`: far right Fields: ~ + • {bookmarks_placement}? (`nvim_tree.config.renderer.icons.placement`) + (default: `signcolumn`) + • {diagnostics_placement}? (`nvim_tree.config.renderer.icons.placement`) + (default: `signcolumn`) • {git_placement}? (`nvim_tree.config.renderer.icons.placement`) (default: `before`) + • {glyphs}? (`nvim_tree.config.renderer.icons.glyphs`) + |nvim_tree.config.renderer.icons.glyphs| • {hidden_placement}? (`nvim_tree.config.renderer.icons.placement`) (default: `after`) • {modified_placement}? (`nvim_tree.config.renderer.icons.placement`) (default: `after`) - • {bookmarks_placement}? (`nvim_tree.config.renderer.icons.placement`) - (default: `signcolumn`) - • {diagnostics_placement}? (`nvim_tree.config.renderer.icons.placement`) - (default: `signcolumn`) • {padding}? (`table`) *nvim_tree.config.renderer.icons.padding* - • {icon}? (`string`, default: `" "`) Between - icon and filename. • {folder_arrow}? (`string`, default: `" "`) Between folder arrow icon and file/folder icon. - • {symlink_arrow}? (`string`, default: `" ➛ "`) Separator - between symlink source and target. + • {icon}? (`string`, default: `" "`) Between + icon and filename. • {show}? (`nvim_tree.config.renderer.icons.show`) |nvim_tree.config.renderer.icons.show| - • {glyphs}? (`nvim_tree.config.renderer.icons.glyphs`) - |nvim_tree.config.renderer.icons.glyphs| + • {symlink_arrow}? (`string`, default: `" ➛ "`) Separator + between symlink source and target. • {web_devicons}? (`nvim_tree.config.renderer.icons.web_devicons`) |nvim_tree.config.renderer.icons.web_devicons| @@ -1370,44 +1374,44 @@ Config: renderer *nvim-tree-config-renderer* Glyphs that appear in the sign column must have length <= 2 Fields: ~ - • {default}? (`string`, default: `""`) Files - • {symlink}? (`string`) (default: `""`) • {bookmark}? (`string`) (default: `"󰆤"`) - • {modified}? (`string`) (default: `"●"`) - • {hidden}? (`string`) (default: `"󰜌"`) + • {default}? (`string`, default: `""`) Files • {folder}? (`table`) *nvim_tree.config.renderer.icons.glyphs.folder* • {arrow_closed}? (`string`) (default: left arrow) • {arrow_open}? (`string`) (default: down arrow) • {default}? (`string`) (default: `""`) - • {open}? (`string`) (default: `""`) • {empty}? (`string`) (default: `""`) • {empty_open}? (`string`) (default: `""`) + • {open}? (`string`) (default: `""`) • {symlink}? (`string`) (default: `""`) • {symlink_open}? (`string`) (default: `""`) • {git}? (`table`) *nvim_tree.config.renderer.icons.glyphs.git* - • {unstaged}? (`string`) (default: `"✗"`) + • {deleted}? (`string`) (default: `""`) + • {ignored}? (`string`) (default: `"◌"`) + • {renamed}? (`string`) (default: `"➜"`) • {staged}? (`string`) (default: `"✓"`) • {unmerged}? (`string`) (default: `""`) - • {renamed}? (`string`) (default: `"➜"`) + • {unstaged}? (`string`) (default: `"✗"`) • {untracked}? (`string`) (default: `"★"`) - • {deleted}? (`string`) (default: `""`) - • {ignored}? (`string`) (default: `"◌"`) + • {hidden}? (`string`) (default: `"󰜌"`) + • {modified}? (`string`) (default: `"●"`) + • {symlink}? (`string`) (default: `""`) *nvim_tree.config.renderer.icons.show* See |nvim-tree-icons-highlighting|. Fields: ~ + • {bookmarks}? (`boolean`) (default: `true`) + • {diagnostics}? (`boolean`) (default: `true`) • {file}? (`boolean`) (default: `true`) • {folder}? (`boolean`) (default: `true`) - • {git}? (`boolean`) (default: `true`) - • {modified}? (`boolean`) (default: `true`) - • {hidden}? (`boolean`) (default: `false`) - • {diagnostics}? (`boolean`) (default: `true`) - • {bookmarks}? (`boolean`) (default: `true`) • {folder_arrow}? (`boolean`, default: `true`) Show a small arrow before the folder node. Arrow will be a part of the node when using |nvim_tree.config.renderer.indent_markers|. + • {git}? (`boolean`) (default: `true`) + • {hidden}? (`boolean`) (default: `false`) + • {modified}? (`boolean`) (default: `true`) *nvim_tree.config.renderer.icons.web_devicons* Configure optional plugin `nvim-tree/nvim-web-devicons`, see @@ -1416,30 +1420,30 @@ Config: renderer *nvim-tree-config-renderer* Fields: ~ • {file}? (`table`) *nvim_tree.config.renderer.icons.web_devicons.file* - • {enable}? (`boolean`) (default: `true`) • {color}? (`boolean`) (default: `true`) + • {enable}? (`boolean`) (default: `true`) • {folder}? (`table`) *nvim_tree.config.renderer.icons.web_devicons.folder* - • {enable}? (`boolean`) (default: `false`) • {color}? (`boolean`) (default: `true`) + • {enable}? (`boolean`) (default: `false`) *nvim_tree.config.renderer.indent_markers* Fields: ~ • {enable}? (`boolean`, default: `false`) Display indent markers when folders are open. - • {inline_arrows}? (`boolean`, default: `true`) Display folder arrows - in the same column as indent marker when using - |nvim_tree.config.renderer.icons.padding| - {folder_arrow} • {icons}? (`table`) *nvim_tree.config.renderer.indent_markers.icons* Before the file/directory, length 1. + • {bottom}? (`string`) (default: `"─"`) • {corner}? (`string`) (default: `"└"`) • {edge}? (`string`) (default: `"│"`) • {item}? (`string`) (default: `"│"`) - • {bottom}? (`string`) (default: `"─"`) • {none}? (`string`) (default: `" "`) + • {inline_arrows}? (`boolean`, default: `true`) Display folder arrows + in the same column as indent marker when using + |nvim_tree.config.renderer.icons.padding| + {folder_arrow} ============================================================================== Config: hijack_directories *nvim-tree-config-hijack-directories* @@ -1453,9 +1457,9 @@ Config: hijack_directories *nvim-tree-config-hijack-directories* feature will be disabled. Fields: ~ - • {enable}? (`boolean`) (default: `true`) • {auto_open}? (`boolean`, default: `true`) Open if the tree was previously closed. + • {enable}? (`boolean`) (default: `true`) ============================================================================== Config: update_focused_file *nvim-tree-config-update-focused-file* @@ -1465,11 +1469,11 @@ Config: update_focused_file *nvim-tree-config-update-focused-file* Fields: ~ • {enable}? (`boolean`) (default: `false`) - • {update_root}? (`nvim_tree.config.update_focused_file.update_root`) - |nvim_tree.config.update_focused_file.update_root| • {exclude}? (`boolean|(fun(args: vim.api.keyset.create_autocmd.callback_args): boolean)`, default: `false`) A function called on |BufEnter| that returns true if the file should not be focused when opening. + • {update_root}? (`nvim_tree.config.update_focused_file.update_root`) + |nvim_tree.config.update_focused_file.update_root| *nvim_tree.config.update_focused_file.update_root* Update the root directory of the tree if the file is not under the current @@ -1505,6 +1509,10 @@ Config: git *nvim-tree-config-git* See |nvim-tree-icons-highlighting|. Fields: ~ + • {cygwin_support}? (`boolean`, default: `false`) Use `cygpath` if + available to resolve paths for git. + • {disable_for_dirs}? (`string[]|(fun(path: string): boolean)`, + default: `{}`) Disable for top level paths. • {enable}? (`boolean`) (default: `true`) • {show_on_dirs}? (`boolean`, default: `true`) Show status icons of children when directory itself has no status @@ -1512,12 +1520,8 @@ Config: git *nvim-tree-config-git* • {show_on_open_dirs}? (`boolean`, default: `true`) Show status icons of children on directories that are open. Requires {show_on_dirs}. - • {disable_for_dirs}? (`string[]|(fun(path: string): boolean)`, - default: `{}`) Disable for top level paths. • {timeout}? (`integer`, default: `400`) `git` processes timeout milliseconds. - • {cygwin_support}? (`boolean`, default: `false`) Use `cygpath` if - available to resolve paths for git. ============================================================================== Config: diagnostics *nvim-tree-config-diagnostics* @@ -1528,28 +1532,28 @@ Config: diagnostics *nvim-tree-config-diagnostics* See |nvim-tree-icons-highlighting|. Fields: ~ - • {enable}? (`boolean`) (default: `false`) • {debounce_delay}? (`integer`, default: `500`) Idle milliseconds between diagnostic event and tree update. - • {show_on_dirs}? (`boolean`, default: `false`) Show diagnostic - icons on parent directories. - • {show_on_open_dirs}? (`boolean`, default: `true`) Show diagnostics - icons on directories that are open. Requires - {show_on_dirs}. • {diagnostic_opts}? (`boolean`, default: `false`) Global |vim.diagnostic.Opts| overrides {severity} and {icons} - • {severity}? (`table`) - *nvim_tree.config.diagnostics.severity* - • {min}? (`vim.diagnostic.Severity`, default: - HINT) |vim.diagnostic.severity| - • {max}? (`vim.diagnostic.Severity`, default: - ERROR) |vim.diagnostic.severity| + • {enable}? (`boolean`) (default: `false`) • {icons}? (`table`) *nvim_tree.config.diagnostics.icons* + • {error}? (`string`) (default: `""` ) • {hint}? (`string`) (default: `""` ) • {info}? (`string`) (default: `""` ) • {warning}? (`string`) (default: `""` ) - • {error}? (`string`) (default: `""` ) + • {severity}? (`table`) + *nvim_tree.config.diagnostics.severity* + • {max}? (`vim.diagnostic.Severity`, default: + ERROR) |vim.diagnostic.severity| + • {min}? (`vim.diagnostic.Severity`, default: + HINT) |vim.diagnostic.severity| + • {show_on_dirs}? (`boolean`, default: `false`) Show diagnostic + icons on parent directories. + • {show_on_open_dirs}? (`boolean`, default: `true`) Show diagnostics + icons on directories that are open. Requires + {show_on_dirs}. ============================================================================== Config: modified *nvim-tree-config-modified* @@ -1614,15 +1618,15 @@ Config: filters *nvim-tree-config-filters* shown, overriding {git_ignored}, {dotfiles} and {custom}. Fields: ~ - • {enable}? (`boolean`, default: `true`) Enable all filters. - • {git_ignored}? (`boolean`) (default: `true`) - • {dotfiles}? (`boolean`) (default: `false`) - • {git_clean}? (`boolean`) (default: `false`) - • {no_buffer}? (`boolean`) (default: `false`) - • {no_bookmark}? (`boolean`) (default: `false`) • {custom}? (`string[]|(fun(absolute_path: string): boolean)`) (default: `{}`) + • {dotfiles}? (`boolean`) (default: `false`) + • {enable}? (`boolean`, default: `true`) Enable all filters. • {exclude}? (`string[]`) (default: `{}`) + • {git_clean}? (`boolean`) (default: `false`) + • {git_ignored}? (`boolean`) (default: `true`) + • {no_bookmark}? (`boolean`) (default: `false`) + • {no_buffer}? (`boolean`) (default: `false`) ============================================================================== Config: live_filter *nvim-tree-config-live-filter* @@ -1635,10 +1639,10 @@ Config: live_filter *nvim-tree-config-live-filter* with the `F` key by default. Fields: ~ - • {prefix}? (`string`, default: `"[FILTER]: "`) Prefix of - the filter displayed in the buffer. • {always_show_folders}? (`boolean`, default: `true`) Whether to filter folders or not. + • {prefix}? (`string`, default: `"[FILTER]: "`) Prefix of + the filter displayed in the buffer. ============================================================================== Config: filesystem_watchers *nvim-tree-config-filesystem-watchers* @@ -1672,19 +1676,19 @@ Config: filesystem_watchers *nvim-tree-config-filesystem-watchers* By default, {max_events} is only enabled for windows. Fields: ~ - • {enable}? (`boolean`) (default: `true`) • {debounce_delay}? (`integer`, default: `50`) Idle milliseconds between filesystem change and tree update. + • {enable}? (`boolean`) (default: `true`) • {ignore_dirs}? (`string[]|(fun(path: string): boolean)`, default: `{ "/.ccls-cache", "/build", "/node_modules", "/target", "/.zig-cache"}`) Disable for specific directories. - • {whitelist_dirs}? (`string[]|(fun(path: string): boolean)`, default: - `{}`) Optionally enable only for specific - directories. • {max_events}? (`integer`, default: `0` or `1000` on windows) Disable for a single directory after {max_events} consecutive events with an interval < {debounce_delay}. Set to 0 to allow unlimited consecutive events. + • {whitelist_dirs}? (`string[]|(fun(path: string): boolean)`, default: + `{}`) Optionally enable only for specific + directories. ============================================================================== Config: actions *nvim-tree-config-actions* @@ -1692,12 +1696,10 @@ Config: actions *nvim-tree-config-actions* *nvim_tree.config.actions* Fields: ~ - • {use_system_clipboard}? (`boolean`, default: `true`) Use the system - clipboard for copy/paste. Copied text will be - stored in registers `+` (system), otherwise, - it will be stored in `1` and `"` • {change_dir}? (`nvim_tree.config.actions.change_dir`) |nvim_tree.config.actions.change_dir| + • {clipboard}? (`nvim_tree.config.actions.clipboard`) + |nvim_tree.config.actions.clipboard| • {expand_all}? (`nvim_tree.config.actions.expand_all`) |nvim_tree.config.actions.expand_all| • {file_popup}? (`nvim_tree.config.actions.file_popup`) @@ -1706,6 +1708,10 @@ Config: actions *nvim-tree-config-actions* |nvim_tree.config.actions.open_file| • {remove_file}? (`nvim_tree.config.actions.remove_file`) |nvim_tree.config.actions.remove_file| + • {use_system_clipboard}? (`boolean`, default: `true`) Use the system + clipboard for copy/paste. Copied text will be + stored in registers `+` (system), otherwise, + it will be stored in `1` and `"` *nvim_tree.config.actions.change_dir* vim |current-directory| behaviour @@ -1718,19 +1724,26 @@ Config: actions *nvim-tree-config-actions* • {restrict_above_cwd}? (`boolean`, default: `false`) Restrict changing to a directory above the global cwd. +*nvim_tree.config.actions.clipboard* + Customizes nvim-tree clipboard behaviour + + Fields: ~ + • {protocol}? (`string`, default: `nvim-tree`) Change the protocol + prefix to be used on multiple nvim instances operations + *nvim_tree.config.actions.expand_all* Configure |nvim_tree.api.tree.expand_all()| and |nvim_tree.api.node.expand()| Fields: ~ - • {max_folder_discovery}? (`integer`, default: `300`) Limit the number - of folders being explored when expanding - every folder. Avoids hanging Nvim when - running this action on very large folders. • {exclude}? (`string[]`, default: `{}`) A list of directories that should not be expanded automatically e.g `{ ".git", "target", "build" }` + • {max_folder_discovery}? (`integer`, default: `300`) Limit the number + of folders being explored when expanding + every folder. Avoids hanging Nvim when + running this action on very large folders. *nvim_tree.config.actions.file_popup* {file_popup} floating window. @@ -1756,10 +1769,10 @@ Config: actions *nvim-tree-config-actions* Opening files. Fields: ~ - • {quit_on_open}? (`boolean`, default: `false`) Closes the explorer - when opening a file • {eject}? (`boolean`, default: `true`) Prevent new opened file from opening in the same window as the tree. + • {quit_on_open}? (`boolean`, default: `false`) Closes the explorer + when opening a file • {resize_window}? (`boolean`, default: `true`) Resizes the tree when opening a file • {window_picker}? (`nvim_tree.config.actions.open_file.window_picker`) @@ -1778,14 +1791,14 @@ Config: actions *nvim-tree-config-actions* cancelled the action. The picker may create a new window. Fields: ~ - • {enable}? (`boolean`) (default: `true`) - • {picker}? (`"default"|(fun(): integer)`, default: `"default"`) - Change the default window picker or define your own. • {chars}? (`string`, default: `"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"`) Identifier characters to use. + • {enable}? (`boolean`) (default: `true`) • {exclude}? (`nvim_tree.config.actions.open_file.window_picker.exclude`) |nvim_tree.config.actions.open_file.window_picker.exclude| + • {picker}? (`"default"|(fun(): integer)`, default: `"default"`) + Change the default window picker or define your own. *nvim_tree.config.actions.open_file.window_picker.exclude* Tables of buffer option names mapped to a list of option values. Windows @@ -1794,10 +1807,10 @@ Config: actions *nvim-tree-config-actions* • selected when not using a window picker Fields: ~ - • {filetype}? (`string[]`) (default: - `{ "notify", "lazy", "qf", "diff", "fugitive", "fugitiveblame", }`) • {buftype}? (`string[]`) (default: `{ "nofile", "terminal", "help", }`) + • {filetype}? (`string[]`) (default: + `{ "notify", "lazy", "qf", "diff", "fugitive", "fugitiveblame", }`) *nvim_tree.config.actions.remove_file* Removing files. @@ -1831,13 +1844,13 @@ Config: tab *nvim-tree-config-tab* *nvim_tree.config.tab.sync* Fields: ~ - • {open}? (`boolean`, default: `false`) Opens the tree automatically - when switching tabpage or opening a new tabpage if the tree - was previously open. • {close}? (`boolean`, default: `false`) Closes the tree across all tabpages when the tree is closed. • {ignore}? (`string[]`, default: `{}`) List of filetypes or buffer names on new tab that will prevent `open` and `close` + • {open}? (`boolean`, default: `false`) Opens the tree automatically + when switching tabpage or opening a new tabpage if the tree + was previously open. ============================================================================== Config: notify *nvim-tree-config-notify* @@ -1851,10 +1864,10 @@ Config: notify *nvim-tree-config-notify* closing operations. Fields: ~ - • {threshold}? (`vim.log.levels`, default: `vim.log.levels.INFO`) - Specify minimum notification |vim.log.levels| • {absolute_path}? (`boolean`, default: `true`) Use absolute paths in FS action notifications, otherwise item names. + • {threshold}? (`vim.log.levels`, default: `vim.log.levels.INFO`) + Specify minimum notification |vim.log.levels| ============================================================================== Config: bookmarks *nvim-tree-config-bookmarks* @@ -1894,10 +1907,10 @@ Config: ui *nvim-tree-config-ui* Confirmation prompts. Fields: ~ - • {remove}? (`boolean`, default: `true`) Prompt before removing. - • {trash}? (`boolean`, default: `true`) Prompt before trashing. • {default_yes}? (`boolean`, default: `false`) If `true` the prompt will be `Y/n`, otherwise `y/N` + • {remove}? (`boolean`, default: `true`) Prompt before removing. + • {trash}? (`boolean`, default: `true`) Prompt before trashing. ============================================================================== Config: experimental *nvim-tree-config-experimental* @@ -1927,8 +1940,6 @@ Config: log *nvim-tree-config-log* Fields: ~ • {all}? (`boolean`, default: `false`) Everything. - • {profile}? (`boolean`, default: `false`) Timing of some - operations. • {config}? (`boolean`, default: `false`) Config and mappings, at startup. • {copy_paste}? (`boolean`, default: `false`) File copy and paste @@ -1938,6 +1949,8 @@ Config: log *nvim-tree-config-log* • {diagnostics}? (`boolean`, default: `false`) LSP and COC processing, verbose. • {git}? (`boolean`, default: `false`) Git processing, verbose. + • {profile}? (`boolean`, default: `false`) Timing of some + operations. • {watcher}? (`boolean`, default: `false`) |nvim_tree.config.filesystem_watchers| processing, verbose. @@ -2148,6 +2161,9 @@ Following is the default configuration, see |nvim_tree.config| for details. >lua }, actions = { use_system_clipboard = true, + clipboard = { + protocol = "nvim-tree" + }, change_dir = { enable = true, global = false, @@ -2284,16 +2300,16 @@ e.g. the following are functionally identical: >lua Fields: ~ • {absolute_path} (`string`) of the file or directory - • {name} (`string`) file or directory name - • {parent}? (`nvim_tree.api.DirectoryNode`) parent directory, - nil for root - • {type} (`"file"|"directory"|"link"`) |uv.fs_stat()| {type} + • {diag_severity}? (`lsp.DiagnosticSeverity`) diagnostic status • {executable} (`boolean`) file is executable • {fs_stat}? (`uv.fs_stat.result`) at time of last tree display, see |uv.fs_stat()| • {git_status} (`nvim_tree.git.Status?`) for files and directories - • {diag_severity}? (`lsp.DiagnosticSeverity`) diagnostic status • {hidden} (`boolean`) node is not visible in the tree + • {name} (`string`) file or directory name + • {parent}? (`nvim_tree.api.DirectoryNode`) parent directory, + nil for root + • {type} (`"file"|"directory"|"link"`) |uv.fs_stat()| {type} *nvim_tree.git.Status* Git statuses for a single node. @@ -2306,9 +2322,9 @@ e.g. the following are functionally identical: >lua • `indirect`: inherited from child directories Fields: ~ - • {file}? (`nvim_tree.git.XY`) status of a file node • {dir}? (`table<"direct"|"indirect", nvim_tree.git.XY[]>`) direct inclusive-or indirect status + • {file}? (`nvim_tree.git.XY`) status of a file node ============================================================================== API: appearance *nvim-tree-api-appearance* @@ -2331,10 +2347,10 @@ get() *nvim_tree.api.commands.get()* Return: ~ (`table[]`) - • {name} (`string`) name of the `:NvimTree*` command • {command} (`fun(args: vim.api.keyset.create_user_command.command_args)`) function that the command will execute + • {name} (`string`) name of the `:NvimTree*` command • {opts} (`vim.api.keyset.user_command`) |command-attributes| @@ -2412,6 +2428,13 @@ clear_clipboard() *nvim_tree.api.fs.clear_clipboard()* copy.absolute_path({node}) *nvim_tree.api.fs.copy.absolute_path()* Copy the absolute path to the system clipboard. + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + + *nvim_tree.api.fs.copy.absolute_path_with_protocol()* +copy.absolute_path_with_protocol({node}) + Copy the absolute path to the system clipboard with nvim-tree protocol. + Parameters: ~ • {node} (`nvim_tree.api.Node?`) @@ -2467,6 +2490,14 @@ paste({node}) *nvim_tree.api.fs.paste()* Parameters: ~ • {node} (`nvim_tree.api.Node?`) +paste_with_protocol({node}) *nvim_tree.api.fs.paste_with_protocol()* + Paste nodes from the nvim-tree clipboard using protocol. + + If {node} is a file it will pasted in the parent directory. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + print_clipboard() *nvim_tree.api.fs.print_clipboard()* Print the contents of the nvim-tree clipboard. @@ -2780,10 +2811,10 @@ open.edit({node}, {opts}) *nvim_tree.api.node.open.edit()* Parameters: ~ • {node} (`nvim_tree.api.Node?`) directory or file • {opts} (`table?`) optional - • {quit_on_open}? (`boolean`, default: false) Quits the tree - when opening the file. • {focus}? (`boolean`, default: false) Keep focus in the tree when opening the file. + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. open.horizontal({node}, {opts}) *nvim_tree.api.node.open.horizontal()* Open file in a new horizontal split. @@ -2791,9 +2822,9 @@ open.horizontal({node}, {opts}) *nvim_tree.api.node.open.horizontal()* Parameters: ~ • {node} (`nvim_tree.api.Node?`) file • {opts} (`table?`) optional - • {quit_on_open}? (`boolean`, default: false) Quits the tree - when opening the file. • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + • {quit_on_open}? (`boolean`, default: false) Quits the tree when opening the file. *nvim_tree.api.node.open.horizontal_no_picker()* @@ -2803,9 +2834,9 @@ open.horizontal_no_picker({node}, {opts}) Parameters: ~ • {node} (`nvim_tree.api.Node?`) file • {opts} (`table?`) optional - • {quit_on_open}? (`boolean`, default: false) Quits the tree - when opening the file. • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + • {quit_on_open}? (`boolean`, default: false) Quits the tree when opening the file. *nvim_tree.api.node.open.no_window_picker()* @@ -2815,10 +2846,10 @@ open.no_window_picker({node}, {opts}) Parameters: ~ • {node} (`nvim_tree.api.Node?`) file • {opts} (`table?`) optional - • {quit_on_open}? (`boolean`, default: false) Quits the tree - when opening the file. • {focus}? (`boolean`, default: false) Keep focus in the tree when opening the file. + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. open.preview({node}, {opts}) *nvim_tree.api.node.open.preview()* Open file with |'bufhidden'| set to `delete`. @@ -2826,9 +2857,9 @@ open.preview({node}, {opts}) *nvim_tree.api.node.open.preview()* Parameters: ~ • {node} (`nvim_tree.api.Node?`) directory or file • {opts} (`table?`) optional - • {quit_on_open}? (`boolean`, default: false) Quits the tree - when opening the file. • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + • {quit_on_open}? (`boolean`, default: false) Quits the tree when opening the file. *nvim_tree.api.node.open.preview_no_picker()* @@ -2839,9 +2870,9 @@ open.preview_no_picker({node}, {opts}) Parameters: ~ • {node} (`nvim_tree.api.Node?`) directory or file • {opts} (`table?`) optional - • {quit_on_open}? (`boolean`, default: false) Quits the tree - when opening the file. • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + • {quit_on_open}? (`boolean`, default: false) Quits the tree when opening the file. *nvim_tree.api.node.open.replace_tree_buffer()* @@ -2857,10 +2888,10 @@ open.tab({node}, {opts}) *nvim_tree.api.node.open.tab()* Parameters: ~ • {node} (`nvim_tree.api.Node?`) directory or file • {opts} (`table?`) optional - • {quit_on_open}? (`boolean`, default: false) Quits the tree - when opening the file. • {focus}? (`boolean`, default: false) Keep focus in the tree when opening the file. + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. open.tab_drop({node}) *nvim_tree.api.node.open.tab_drop()* Switch to tab containing window with selected file if it exists, otherwise @@ -2883,9 +2914,9 @@ open.vertical({node}, {opts}) *nvim_tree.api.node.open.vertical()* Parameters: ~ • {node} (`nvim_tree.api.Node?`) file • {opts} (`table?`) optional - • {quit_on_open}? (`boolean`, default: false) Quits the tree - when opening the file. • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + • {quit_on_open}? (`boolean`, default: false) Quits the tree when opening the file. *nvim_tree.api.node.open.vertical_no_picker()* @@ -2895,10 +2926,10 @@ open.vertical_no_picker({node}, {opts}) Parameters: ~ • {node} (`nvim_tree.api.Node?`) file • {opts} (`table?`) optional - • {quit_on_open}? (`boolean`, default: false) Quits the tree - when opening the file. • {focus}? (`boolean`, default: false) Keep focus in the tree when opening the file. + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. run.cmd({node}) *nvim_tree.api.node.run.cmd()* Enter |cmdline| with the full path of the node and the cursor at the start @@ -2979,16 +3010,16 @@ find_file({opts}) *nvim_tree.api.tree.find_file()* • {opts} (`table?`) optional • {buf}? (`string|integer`) Absolute/relative path OR `bufnr` to find. - • {open}? (`boolean`, default: false) Open the tree if - necessary. • {current_window}? (`boolean`, default: false) Requires {open}: open in the current window. - • {winid}? (`integer`) Open the tree in the specified - |window-ID|, overrides {current_window} + • {focus}? (`boolean`, default: false) Focus the tree window. + • {open}? (`boolean`, default: false) Open the tree if + necessary. • {update_root}? (`boolean`, default: false) Update root after find, see |nvim_tree.config.update_focused_file| {update_root} - • {focus}? (`boolean`, default: false) Focus the tree window. + • {winid}? (`integer`) Open the tree in the specified + |window-ID|, overrides {current_window} focus() *nvim_tree.api.tree.focus()* Focus the tree, opening it if necessary. Retained for compatibility, use @@ -3020,9 +3051,9 @@ is_visible({opts}) *nvim_tree.api.tree.is_visible()* Parameters: ~ • {opts} (`table?`) optional - • {tabpage}? (`integer`) |tab-ID| 0 or nil for current. • {any_tabpage}? (`boolean`, default: false) Visible on any tab. + • {tabpage}? (`integer`) |tab-ID| 0 or nil for current. Return: ~ (`boolean`) @@ -3032,16 +3063,16 @@ open({opts}) *nvim_tree.api.tree.open()* Parameters: ~ • {opts} (`table?`) optional - • {path}? (`string`) Root directory for the tree • {current_window}? (`boolean`, default: false) Open the tree in the current window - • {winid}? (`integer`) Open the tree in the specified - |window-ID|, overrides {current_window} • {find_file}? (`boolean`, default: false) Find the current buffer. + • {path}? (`string`) Root directory for the tree • {update_root}? (`boolean`, default: false) Update root following {find_file}, see |nvim_tree.config.update_focused_file| {update_root} + • {winid}? (`integer`) Open the tree in the specified + |window-ID|, overrides {current_window} reload() *nvim_tree.api.tree.reload()* Refresh the tree. Does nothing if closed. @@ -3058,11 +3089,11 @@ resize({opts}) *nvim_tree.api.tree.resize()* Parameters: ~ • {opts} (`table?`) optional + • {absolute}? (`integer`) Set the width. + • {relative}? (`integer`) Increase or decrease the width. • {width}? (`nvim_tree.config.view.width.spec|nvim_tree.config.view.width`) New |nvim_tree.config.view| {width} value. - • {absolute}? (`integer`) Set the width. - • {relative}? (`integer`) Increase or decrease the width. search_node() *nvim_tree.api.tree.search_node()* Open the search dialogue. @@ -3072,18 +3103,18 @@ toggle({opts}) *nvim_tree.api.tree.toggle()* Parameters: ~ • {opts} (`table?`) optional - • {path}? (`string`) Root directory for the tree • {current_window}? (`boolean`, default: false) Open the tree in the current window - • {winid}? (`integer`) Open the tree in the specified - |window-ID|, overrides {current_window} • {find_file}? (`boolean`, default: false) Find the current buffer. + • {focus}? (`boolean`, default: true) Focus the tree when + opening. + • {path}? (`string`) Root directory for the tree • {update_root}? (`boolean`, default: false) Update root following {find_file}, see |nvim_tree.config.update_focused_file| {update_root} - • {focus}? (`boolean`, default: true) Focus the tree when - opening. + • {winid}? (`integer`) Open the tree in the specified + |window-ID|, overrides {current_window} toggle_help() *nvim_tree.api.tree.toggle_help()* Toggle help view. @@ -3171,10 +3202,8 @@ the meta method `__call` with arguments and return: >lua *nvim_tree.Class* Fields: ~ - • {super} (`nvim_tree.Class`) Parent class, `Class` for base - classes. - • {new} (`fun(self: nvim_tree.Class, ...: any)`) See - |nvim_tree.Class:new()|. + • {as} (`fun(self: nvim_tree.Class, class: T): T?`) See + |nvim_tree.Class:as()|. • {destroy} (`fun(self: nvim_tree.Class)`) See |nvim_tree.Class:destroy()|. • {extend} (`fun(self: nvim_tree.Class): [nvim_tree.Class]`) See @@ -3183,10 +3212,12 @@ the meta method `__call` with arguments and return: >lua See |nvim_tree.Class:implement()|. • {is} (`fun(self: nvim_tree.Class, class: T): boolean`) See |nvim_tree.Class:is()|. - • {as} (`fun(self: nvim_tree.Class, class: T): T?`) See - |nvim_tree.Class:as()|. + • {new} (`fun(self: nvim_tree.Class, ...: any)`) See + |nvim_tree.Class:new()|. • {nop} (`fun(self: nvim_tree.Class, ...: any)`) See |nvim_tree.Class:nop()|. + • {super} (`nvim_tree.Class`) Parent class, `Class` for base + classes. Class:as({class}) *nvim_tree.Class:as()* @@ -3298,28 +3329,28 @@ Your class may: Decorator interface Fields: ~ + • {define_sign} (`fun(self: nvim_tree.api.Decorator, icon: nvim_tree.api.highlighted_string?)`) + See |nvim_tree.api.Decorator:define_sign()|. • {enabled} (`boolean`) Enable this decorator. + • {highlight_group} (`fun(self: nvim_tree.api.Decorator, node: nvim_tree.api.Node): string?`) + See |nvim_tree.api.Decorator:highlight_group()|. • {highlight_range} (`nvim_tree.config.renderer.highlight`) What to highlight: |nvim_tree.config.renderer.highlight| + • {icon_node} (`fun(self: nvim_tree.api.Decorator, node: nvim_tree.api.Node): nvim_tree.api.highlighted_string?`) + See |nvim_tree.api.Decorator:icon_node()|. • {icon_placement} (`"none"|nvim_tree.config.renderer.icons.placement`) Where to place the icons: |nvim_tree.config.renderer.icons.placement| - • {icon_node} (`fun(self: nvim_tree.api.Decorator, node: nvim_tree.api.Node): nvim_tree.api.highlighted_string?`) - See |nvim_tree.api.Decorator:icon_node()|. • {icons} (`fun(self: nvim_tree.api.Decorator, node: nvim_tree.api.Node): nvim_tree.api.highlighted_string[]?`) See |nvim_tree.api.Decorator:icons()|. - • {highlight_group} (`fun(self: nvim_tree.api.Decorator, node: nvim_tree.api.Node): string?`) - See |nvim_tree.api.Decorator:highlight_group()|. - • {define_sign} (`fun(self: nvim_tree.api.Decorator, icon: nvim_tree.api.highlighted_string?)`) - See |nvim_tree.api.Decorator:define_sign()|. *nvim_tree.api.highlighted_string* Text or glyphs with optional highlight group names to apply to it. Fields: ~ - • {str} (`string`) One or many glyphs/characters. • {hl} (`string[]`) Highlight group names to apply in order. Empty table for no highlighting. + • {str} (`string`) One or many glyphs/characters. Decorator:define_sign({icon}) *nvim_tree.api.Decorator:define_sign()* From 2c56cc6a1ace72e18dbac4fbba0d5daac94bcc8f Mon Sep 17 00:00:00 2001 From: uanela Date: Thu, 11 Jun 2026 17:20:09 +0200 Subject: [PATCH 12/12] fix(clipboad): correctly show the number of copied nodes on bgy --- lua/nvim-tree/actions/fs/clipboard.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/nvim-tree/actions/fs/clipboard.lua b/lua/nvim-tree/actions/fs/clipboard.lua index 1fd17c720c1..34a3963bd3e 100644 --- a/lua/nvim-tree/actions/fs/clipboard.lua +++ b/lua/nvim-tree/actions/fs/clipboard.lua @@ -564,7 +564,7 @@ function Clipboard:copy_absolute_path(node_or_nodes, opts) end end - self:copy_to_reg(content, opts, string.format("%s nodes copied to register", is_single and #node_or_nodes or 1)) + self:copy_to_reg(content, opts, string.format("%s nodes copied to register", is_single and 1 or #node_or_nodes)) end ---Node is cut. Will not be copied.