Compare commits

...

13 Commits

Author SHA1 Message Date
uanela
91a288ca57 Merge branch 'feat/add-download-from-path' of https://github.com/nvim-tree/nvim-tree.lua into feat/add-download-from-path 2026-06-29 08:30:01 +02:00
uanela
582bc35ce2 Merge branch 'chore/remove-operation-between-instances-protocol' of https://github.com/nvim-tree/nvim-tree.lua into feat/add-download-from-path 2026-06-29 08:29:38 +02:00
uanela
cb58a0721c fix: _meta/api/fs.lua and docs 2026-06-25 10:27:26 +02:00
uanela
4b13775b45 chore: destroy dummy nodes and prevent empty paths nodes parsing 2026-06-25 10:14:57 +02:00
uanela
4fcbafea04 chore: add fs.move api and update docs 2026-06-25 10:14:16 +02:00
uanela
1b6737155a chore: update docs 2026-06-22 09:06:33 +02:00
uanela
30c5036368 Merge branch 'chore/remove-operation-between-instances-protocol' of https://github.com/nvim-tree/nvim-tree.lua into chore/remove-operation-between-instances-protocol 2026-06-22 09:02:31 +02:00
uanela
f10f779baf refactor: remove visual mode from copy.basename|filename|path 2026-06-22 09:00:31 +02:00
uanela
062a2d2800 chore: revert copy_node_attribute 2026-06-22 08:59:51 +02:00
uanela
4bd13ec53b chore: copy clipboard.data to register on copy/cut 2026-06-22 08:58:50 +02:00
uanela
fa2b18661c fix: remove unused apis 2026-06-22 08:57:05 +02:00
Uanela Como
5eba88e119 Merge branch 'master' into chore/remove-operation-between-instances-protocol 2026-06-22 07:55:41 +02:00
dependabot[bot]
8e8be709c9 chore(deps): bump actions/checkout from 6 to 7 (#3340)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-20 13:16:28 +10:00
9 changed files with 98 additions and 102 deletions

View File

@@ -26,7 +26,7 @@ jobs:
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: install lua ${{ matrix.lua_version }}
uses: leafo/gh-actions-lua@v13
@@ -60,7 +60,7 @@ jobs:
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: install nvim ${{ matrix.nvim_version }}
uses: rhysd/action-setup-vim@v1

View File

@@ -10,7 +10,7 @@ jobs:
luarocks-upload:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: LuaRocks Upload
uses: nvim-neorocks/luarocks-tag-release@v7
env:

View File

@@ -16,7 +16,7 @@ jobs:
steps:
- uses: googleapis/release-please-action@v5
id: release
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: tag major and minor versions
if: ${{ steps.release.outputs.release_created }}
run: |

View File

@@ -20,7 +20,8 @@ Features
- Git integration
- Diagnostics integration: LSP and COC
- (Live) filtering
- Cut, copy, paste, rename, delete, create
- Rename, delete, create
- Cut, copy, paste locally and between instances
- Highly customisable
File Icons
@@ -143,7 +144,7 @@ Show the mappings: `g?`
`f` n Live Filter: Start |nvim_tree.api.filter.live.start()|
`g?` n Help |nvim_tree.api.tree.toggle_help()|
`gy` nx Copy Absolute Path |nvim_tree.api.fs.copy.absolute_path()|
`ge` nx Copy Basename |nvim_tree.api.fs.copy.basename()|
`ge` n 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()|
@@ -165,8 +166,8 @@ Show the mappings: `g?`
`U` n Toggle Filter: Custom |nvim_tree.api.filter.custom.toggle()|
`W` n Collapse All |nvim_tree.api.tree.collapse_all()|
`x` nx Cut |nvim_tree.api.fs.cut()|
`y` nx Copy Name |nvim_tree.api.fs.copy.filename()|
`Y` nx Copy Relative Path |nvim_tree.api.fs.copy.relative_path()|
`y` n Copy Name |nvim_tree.api.fs.copy.filename()|
`Y` n Copy Relative Path |nvim_tree.api.fs.copy.relative_path()|
`<2-LeftMouse>` n Open |nvim_tree.api.node.open.edit()|
`<2-RightMouse>` n CD |nvim_tree.api.tree.change_root_to_node()|
@@ -437,7 +438,7 @@ You are encouraged to copy these to your {on_attach} function. >lua
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" }, "ge", api.fs.copy.basename, opts("Copy Basename"))
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"))
@@ -459,8 +460,8 @@ You are encouraged to copy these to your {on_attach} function. >lua
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", "x" }, "y", api.fs.copy.filename, opts("Copy Name"))
vim.keymap.set({ "n", "x" }, "Y", api.fs.copy.relative_path, opts("Copy Relative Path"))
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
@@ -2461,27 +2462,25 @@ cut({node}) *nvim_tree.api.fs.cut()*
Parameters: ~
• {node} (`nvim_tree.api.Node?`)
paste({node}) *nvim_tree.api.fs.paste()*
Paste from the nvim-tree clipboard.
move({node}) *nvim_tree.api.fs.move()*
Paste while cutting files from:
• current nvim-tree clipboard (if present)
• another nvim-tree instance via system clipboard
If {node} is a file it will pasted in the parent directory.
Parameters: ~
• {node} (`nvim_tree.api.Node?`)
*nvim_tree.api.fs.paste_from_register_copying()*
paste_from_register_copying({node_or_nodes})
Paste nodes from the system register as files to nvim-tree while copying.
paste({node}) *nvim_tree.api.fs.paste()*
Paste files from:
• current nvim-tree clipboard (if present)
• another nvim-tree instance via system clipboard
If {node} is a file it will pasted in the parent directory.
Parameters: ~
• {node_or_nodes} (`nvim_tree.api.Node|nvim_tree.api.Node[]?`)
*nvim_tree.api.fs.paste_from_register_cutting()*
paste_from_register_cutting({node_or_nodes})
Paste nodes from the system register as files to nvim-tree while cutting.
Parameters: ~
• {node_or_nodes} (`nvim_tree.api.Node|nvim_tree.api.Node[]?`)
• {node} (`nvim_tree.api.Node?`)
print_clipboard() *nvim_tree.api.fs.print_clipboard()*
Print the contents of the nvim-tree clipboard.

View File

@@ -59,7 +59,9 @@ function nvim_tree.api.fs.create(node) end
function nvim_tree.api.fs.cut(node) end
---
---Paste from the nvim-tree clipboard.
---Paste files from:
---- current nvim-tree clipboard (if present)
---- another nvim-tree instance via system clipboard
---
---If {node} is a file it will pasted in the parent directory.
---
@@ -67,16 +69,14 @@ function nvim_tree.api.fs.cut(node) end
function nvim_tree.api.fs.paste(node) end
---
---Paste nodes from the system register as files to nvim-tree while copying.
---Paste while cutting files from:
---- current nvim-tree clipboard (if present)
---- another nvim-tree instance via system clipboard
---
---@param node_or_nodes? nvim_tree.api.Node | nvim_tree.api.Node[]
function nvim_tree.api.fs.paste_from_register_copying(node_or_nodes) end
---If {node} is a file it will pasted in the parent directory.
---
---Paste nodes from the system register as files to nvim-tree while cutting.
---
---@param node_or_nodes? nvim_tree.api.Node | nvim_tree.api.Node[]
function nvim_tree.api.fs.paste_from_register_cutting(node_or_nodes) end
---@param node? nvim_tree.api.Node
function nvim_tree.api.fs.move(node) end
---
---Print the contents of the nvim-tree clipboard.

View File

@@ -24,6 +24,8 @@ error("Cannot require a meta file")
---[nvim_tree.config.actions.remove_file]
---@field remove_file? nvim_tree.config.actions.remove_file
--- vim [current-directory] behaviour
---@class nvim_tree.config.actions.change_dir
---

View File

@@ -194,7 +194,7 @@ function Clipboard:copy(node_or_nodes)
else
self:bulk_clipboard(utils.filter_descendant_nodes(node_or_nodes), self.data.cut, self.data.copy, "added to")
end
self:copy_node_attribute(node_or_nodes, "absolute_path", { notify = false })
self:copy_absolute_path(self.data.copy, { notify = false })
end
---Cut one or more nodes
@@ -207,7 +207,7 @@ function Clipboard:cut(node_or_nodes)
else
self:bulk_clipboard(utils.filter_descendant_nodes(node_or_nodes), self.data.copy, self.data.cut, "cut to")
end
self:copy_node_attribute(node_or_nodes, "absolute_path", { notify = false })
self:copy_absolute_path(self.data.cut, { notify = false })
end
---Clear clipboard for action and reload to reflect filesystem changes from paste.
@@ -327,12 +327,14 @@ function Clipboard:get_nodes_from_reg()
local absolute_paths = vim.split(content:sub(1, #content), "\n")
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))
if absolute_path:match("^%s*(.-)%s*s") then
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
end
return nodes
@@ -405,6 +407,10 @@ function Clipboard:do_paste(node, action, action_fn)
else
self:finish_paste(action)
end
for _, n in ipairs(clip) do
n:destroy()
end
end
---@param source string
@@ -473,61 +479,34 @@ function Clipboard:copy_to_reg(content, message, opts)
end
---@param node Node
---@return string
function Clipboard:get_node_filename(node)
function Clipboard:copy_filename(node)
if node.name == ".." then
-- root
return vim.fn.fnamemodify(self.explorer.absolute_path, ":t")
self:copy_to_reg(vim.fn.fnamemodify(self.explorer.absolute_path, ":t"))
else
-- node
return node.name
self:copy_to_reg(node.name)
end
end
---@param node_or_nodes Node|Node[]
---@param attribute "absolute_path" | "basename" | "filename" | "relative_path"
---@param opts? { notify?: boolean }
function Clipboard:copy_node_attribute(node_or_nodes, attribute, opts)
opts = opts and opts or {}
local content
local node_attribute_getters = {
basename = function(n) return self:get_node_basename(n) end,
filename = function(n) return self:get_node_filename(n) end,
relative_path = function(n) return self:get_node_relative_path(n) end,
absolute_path = function(n) return self:get_node_absolute_path(n) end,
}
local attribute_getter = node_attribute_getters[attribute]
local is_single = self:is_nodes_array(node_or_nodes) == false
if is_single then
local node = #node_or_nodes == 1 and node_or_nodes[0] or node_or_nodes
content = attribute_getter(node)
else
node_or_nodes = utils.filter_descendant_nodes(node_or_nodes)
content = {}
for _, node in ipairs(node_or_nodes) do
table.insert(content, attribute_getter(node))
end
---@private
---@param node Node
---@return string
function Clipboard:get_absolute_path(node)
if node.name == ".." then
node = self.explorer
end
if content ~= nil then
local message = nil
if not is_single then
message = string.format("%s %s copied to register", #content, attribute:gsub("_", " ") .. "s")
end
self:copy_to_reg(content, message, opts)
end
local absolute_path = node.absolute_path
return node.nodes ~= nil and utils.path_add_trailing(absolute_path) or absolute_path
end
---@param node Node
---@return string|nil
function Clipboard:get_node_relative_path(node)
function Clipboard:copy_path(node)
if node.name == ".." then
-- root
return utils.path_add_trailing("")
self:copy_to_reg(utils.path_add_trailing(""))
else
-- node
local absolute_path = node.absolute_path
@@ -538,34 +517,50 @@ function Clipboard:get_node_relative_path(node)
local relative_path = utils.path_relative(absolute_path, cwd)
if node:is(DirectoryNode) then
return utils.path_add_trailing(relative_path)
self:copy_to_reg(utils.path_add_trailing(relative_path))
else
return relative_path
self:copy_to_reg(relative_path)
end
end
end
---@private
---@param node Node
---@return string
function Clipboard:get_node_absolute_path(node)
if node.name == ".." then
node = self.explorer
---@param node_or_nodes Node|Node[]
---@param opts? { notify?: boolean }
function Clipboard:copy_absolute_path(node_or_nodes, opts)
opts = opts and opts or {}
local content
local is_single = self:is_nodes_array(node_or_nodes) == false
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)
content = {}
for _, node in ipairs(node_or_nodes) do
table.insert(content, self:get_absolute_path(node))
end
end
local absolute_path = node.absolute_path
return node.nodes ~= nil and utils.path_add_trailing(absolute_path) or absolute_path
if content ~= nil then
local message = nil
if not is_single then
message = string.format("%s %s copied to register", #content, #content > 1 and "absolute paths" or "absolute path")
end
self:copy_to_reg(content, message, opts)
end
end
---@param node Node
---@return string
function Clipboard:get_node_basename(node)
function Clipboard:copy_basename(node)
if node.name == ".." then
-- root
return vim.fn.fnamemodify(node.explorer.absolute_path, ":t:r")
self:copy_to_reg(vim.fn.fnamemodify(node.explorer.absolute_path, ":t:r"))
else
-- node
return vim.fn.fnamemodify(node.name, ":r")
self:copy_to_reg(vim.fn.fnamemodify(node.name, ":r"))
end
end

View File

@@ -155,10 +155,10 @@ 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 = ev(function(e, n) e.clipboard:copy_node_attribute(n, "absolute_path") end)
api.fs.copy.basename = ev(function(e, n) e.clipboard:copy_node_attribute(n, "basename") end)
api.fs.copy.filename = ev(function(e, n) e.clipboard:copy_node_attribute(n, "filename") end)
api.fs.copy.relative_path = ev(function(e, n) e.clipboard:copy_node_attribute(n, "relative_path") end)
api.fs.copy.absolute_path = ev(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.filename = en(function(e, n) e.clipboard:copy_filename(n) end)
api.fs.copy.relative_path = en(function(e, n) e.clipboard:copy_path(n) end)
api.fs.copy.node = ev(function(e, n) e.clipboard:copy(n) end)
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)

View File

@@ -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" }, "ge", api.fs.copy.basename, opts("Copy Basename"))
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"))
@@ -113,8 +113,8 @@ function M.on_attach_default(bufnr)
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", "x" }, "y", api.fs.copy.filename, opts("Copy Name"))
vim.keymap.set({ "n", "x" }, "Y", api.fs.copy.relative_path, opts("Copy Relative Path"))
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