mirror of
https://github.com/nvim-tree/nvim-tree.lua.git
synced 2026-07-28 07:49:46 +05:30
Compare commits
8 Commits
feat/add-d
...
084bf35e75
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
084bf35e75 | ||
|
|
4213bd6eab | ||
|
|
cf18a662cd | ||
|
|
a797d5e201 | ||
|
|
35d3511e7a | ||
|
|
7ff7040bf6 | ||
|
|
531b807b8f | ||
|
|
c760c92667 |
@@ -1,3 +1,3 @@
|
||||
{
|
||||
".": "1.17.0"
|
||||
".": "1.19.0"
|
||||
}
|
||||
|
||||
27
CHANGELOG.md
27
CHANGELOG.md
@@ -1,5 +1,32 @@
|
||||
# Changelog
|
||||
|
||||
## [1.19.0](https://github.com/nvim-tree/nvim-tree.lua/compare/nvim-tree-v1.18.0...nvim-tree-v1.19.0) (2026-07-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* experiment: restore nvim-tree on session load, see https://github.com/nvim-tree/nvim-tree.lua/issues/3343 ([#3335](https://github.com/nvim-tree/nvim-tree.lua/issues/3335)) ([cf18a66](https://github.com/nvim-tree/nvim-tree.lua/commit/cf18a662cd5f200361b6fedfb794eed583e075e1))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **#3346:** api.tree.resize: 'configure_width' (a nil value) ([#3347](https://github.com/nvim-tree/nvim-tree.lua/issues/3347)) ([a797d5e](https://github.com/nvim-tree/nvim-tree.lua/commit/a797d5e20133fc031fba4aa7d1272f5b1d950a1c))
|
||||
|
||||
## [1.18.0](https://github.com/nvim-tree/nvim-tree.lua/compare/nvim-tree-v1.17.0...nvim-tree-v1.18.0) (2026-07-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **#1549:** p will paste files from another nvim-tree instance, gp will cut/paste ([#3336](https://github.com/nvim-tree/nvim-tree.lua/issues/3336)) ([c760c92](https://github.com/nvim-tree/nvim-tree.lua/commit/c760c92667fe5febf99e2a5bb8a543b0208c743b))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **#3312:** correct cursor when full name shown, requires nvim 0.12.2+ ([#3316](https://github.com/nvim-tree/nvim-tree.lua/issues/3316)) ([d277467](https://github.com/nvim-tree/nvim-tree.lua/commit/d277467fc0d1d0e2bca88165a1de6b526f9f6fe8))
|
||||
* **#3324:** deprecated BufModifiedSet event replaced by OptionSet event for Nvim 0.13+ ([#3325](https://github.com/nvim-tree/nvim-tree.lua/issues/3325)) ([f9bfc00](https://github.com/nvim-tree/nvim-tree.lua/commit/f9bfc0059eca24546b69a7006110463da4808f8f))
|
||||
* **#3327:** pass nvim_tree.api.node.open.Opts to all applicable nvim_tree.api.node.open function ([#3329](https://github.com/nvim-tree/nvim-tree.lua/issues/3329)) ([07f541f](https://github.com/nvim-tree/nvim-tree.lua/commit/07f541fcaa4a5ae019598240362449ab7e9812b3))
|
||||
* **full-name:** lower `zindex` to get consistent cursor shape ([d277467](https://github.com/nvim-tree/nvim-tree.lua/commit/d277467fc0d1d0e2bca88165a1de6b526f9f6fe8))
|
||||
|
||||
## [1.17.0](https://github.com/nvim-tree/nvim-tree.lua/compare/nvim-tree-v1.16.0...nvim-tree-v1.17.0) (2026-04-07)
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
|
||||
(Live) filtering
|
||||
|
||||
Cut, copy, paste, rename, delete, create
|
||||
Rename, delete, create
|
||||
|
||||
Cut, copy, paste locally and between instances
|
||||
|
||||
Highly customisable
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -142,7 +143,7 @@ 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()|
|
||||
`gy` nx Copy Absolute Path |nvim_tree.api.fs.copy.absolute_path()|
|
||||
`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()|
|
||||
@@ -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()|
|
||||
`gp` n Move |nvim_tree.api.fs.move()|
|
||||
`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()|
|
||||
@@ -435,7 +437,7 @@ You are encouraged to copy these to your {on_attach} function. >lua
|
||||
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", "x" }, "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"))
|
||||
@@ -447,6 +449,7 @@ You are encouraged to copy these to your {on_attach} function. >lua
|
||||
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.move, opts("Move"))
|
||||
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"))
|
||||
@@ -1908,6 +1911,11 @@ Config: experimental *nvim-tree-config-experimental*
|
||||
In the event of a problem please disable the experiment and raise an
|
||||
issue.
|
||||
|
||||
Fields: ~
|
||||
• {session_restore_nvim}? (`boolean`, default: `false`) Restore
|
||||
nvim-tree buffers when restoring vim sessions
|
||||
(requires 0.13+).
|
||||
|
||||
==============================================================================
|
||||
Config: log *nvim-tree-config-log*
|
||||
|
||||
@@ -2213,6 +2221,7 @@ Following is the default configuration, see |nvim_tree.config| for details. >lua
|
||||
persist = false,
|
||||
},
|
||||
experimental = {
|
||||
session_restore_nvim = false
|
||||
},
|
||||
log = {
|
||||
enable = false,
|
||||
@@ -2459,8 +2468,20 @@ cut({node}) *nvim_tree.api.fs.cut()*
|
||||
Parameters: ~
|
||||
• {node} (`nvim_tree.api.Node?`)
|
||||
|
||||
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?`)
|
||||
|
||||
paste({node}) *nvim_tree.api.fs.paste()*
|
||||
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.
|
||||
|
||||
|
||||
@@ -59,13 +59,25 @@ 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.
|
||||
---
|
||||
---@param node? nvim_tree.api.Node
|
||||
function nvim_tree.api.fs.paste(node) end
|
||||
|
||||
---
|
||||
---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.
|
||||
---
|
||||
---@param node? nvim_tree.api.Node
|
||||
function nvim_tree.api.fs.move(node) end
|
||||
|
||||
---
|
||||
---Print the contents of the nvim-tree clipboard.
|
||||
---
|
||||
|
||||
@@ -9,6 +9,9 @@ error("Cannot require a meta file")
|
||||
---
|
||||
---@class nvim_tree.config.experimental
|
||||
---
|
||||
---Restore nvim-tree buffers when restoring vim sessions (requires 0.13+).
|
||||
---(default: `false`)
|
||||
---@field session_restore_nvim? boolean
|
||||
--Example below for future reference:
|
||||
--
|
||||
--Buffers opened by nvim-tree will use with relative paths instead of absolute.
|
||||
|
||||
@@ -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"
|
||||
@@ -176,28 +177,40 @@ 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()
|
||||
else
|
||||
self:bulk_clipboard(utils.filter_descendant_nodes(node_or_nodes), self.data.cut, self.data.copy, "added to")
|
||||
end
|
||||
self:copy_absolute_path(self.data.copy, { notify = false })
|
||||
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()
|
||||
else
|
||||
self:bulk_clipboard(utils.filter_descendant_nodes(node_or_nodes), self.data.copy, self.data.cut, "cut to")
|
||||
end
|
||||
self:copy_absolute_path(self.data.cut, { notify = false })
|
||||
end
|
||||
|
||||
---Clear clipboard for action and reload to reflect filesystem changes from paste.
|
||||
@@ -304,6 +317,40 @@ function Clipboard:resolve_conflicts(conflict, destination, action, action_fn)
|
||||
end)
|
||||
end
|
||||
|
||||
--- Transforms the copied absolute paths on register to node
|
||||
---@private
|
||||
function Clipboard:get_nodes_from_reg()
|
||||
local content = vim.fn.getreg(self.reg)
|
||||
|
||||
if #content == 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local nodes = {}
|
||||
local absolute_paths = vim.split(content:sub(1, #content), "\n")
|
||||
|
||||
for _, absolute_path in ipairs(absolute_paths) do
|
||||
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
|
||||
end
|
||||
|
||||
---@param nodes Node[]
|
||||
---@private
|
||||
function Clipboard:destroy_nodes(nodes)
|
||||
for _, n in ipairs(nodes) do
|
||||
n:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
---Paste cut or copy with batch conflict resolution.
|
||||
---@private
|
||||
---@param node Node
|
||||
@@ -318,7 +365,9 @@ function Clipboard:do_paste(node, action, action_fn)
|
||||
node = dir:last_group_node()
|
||||
end
|
||||
end
|
||||
local clip = self.data[action]
|
||||
local is_local = #self.data[action] > 0
|
||||
local clip = is_local and self.data[action] or self:get_nodes_from_reg()
|
||||
|
||||
if #clip == 0 then
|
||||
return
|
||||
end
|
||||
@@ -328,6 +377,9 @@ function Clipboard:do_paste(node, action, action_fn)
|
||||
if not stats and err_name ~= "ENOENT" then
|
||||
log.line("copy_paste", "do_paste fs_stat '%s' failed '%s'", destination, err)
|
||||
notify.error("Could not " .. action .. " " .. notify.render_path(destination) .. " - " .. (err or "???"))
|
||||
if is_local == false then
|
||||
self:destroy_nodes(clip)
|
||||
end
|
||||
return
|
||||
end
|
||||
local is_dir = stats and stats.type == "directory"
|
||||
@@ -359,6 +411,10 @@ function Clipboard:do_paste(node, action, action_fn)
|
||||
else
|
||||
self:finish_paste(action)
|
||||
end
|
||||
|
||||
if is_local == false then
|
||||
self:destroy_nodes(clip)
|
||||
end
|
||||
end
|
||||
|
||||
---@param source string
|
||||
@@ -386,10 +442,12 @@ end
|
||||
|
||||
---Paste cut (if present) or copy (if present)
|
||||
---@param node Node
|
||||
function Clipboard:paste(node)
|
||||
if self.data.cut[1] ~= nil then
|
||||
---@param opts? { cut?: boolean }
|
||||
function Clipboard:paste(node, opts)
|
||||
opts = opts and opts or {}
|
||||
if self.data.cut[1] ~= nil or opts.cut == true then
|
||||
self:do_paste(node, "cut", do_cut)
|
||||
elseif self.data.copy[1] ~= nil then
|
||||
else
|
||||
self:do_paste(node, "copy", do_copy)
|
||||
end
|
||||
end
|
||||
@@ -413,17 +471,15 @@ function Clipboard:print_clipboard()
|
||||
end
|
||||
|
||||
---@param content string
|
||||
function Clipboard:copy_to_reg(content)
|
||||
-- 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)
|
||||
vim.api.nvim_buf_set_text(temp_buf, 0, 0, 0, 0, { content })
|
||||
vim.api.nvim_buf_call(temp_buf, function()
|
||||
vim.cmd(string.format('normal! "%sy$', self.reg))
|
||||
end)
|
||||
vim.api.nvim_buf_delete(temp_buf, {})
|
||||
---@param message? string
|
||||
---@param opts? { notify?: boolean }
|
||||
function Clipboard:copy_to_reg(content, message, opts)
|
||||
opts = opts and opts or {}
|
||||
vim.fn.setreg(self.reg, type(content) == "table" and content or { content }, "v")
|
||||
|
||||
notify.info(string.format("Copied %s to %s clipboard!", content, self.clipboard_name))
|
||||
if opts.notify ~= false then
|
||||
notify.info(message or string.format("Copied %s to %s clipboard!", content, self.clipboard_name))
|
||||
end
|
||||
end
|
||||
|
||||
---@param node Node
|
||||
@@ -437,18 +493,20 @@ function Clipboard:copy_filename(node)
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param node Node
|
||||
function Clipboard:copy_basename(node)
|
||||
---@return string
|
||||
function Clipboard:get_absolute_path(node)
|
||||
if node.name == ".." then
|
||||
-- root
|
||||
self:copy_to_reg(vim.fn.fnamemodify(self.explorer.absolute_path, ":t:r"))
|
||||
else
|
||||
-- node
|
||||
self:copy_to_reg(vim.fn.fnamemodify(node.name, ":r"))
|
||||
node = self.explorer
|
||||
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:copy_path(node)
|
||||
if node.name == ".." then
|
||||
-- root
|
||||
@@ -470,15 +528,44 @@ function Clipboard:copy_path(node)
|
||||
end
|
||||
end
|
||||
|
||||
---@param node Node
|
||||
function Clipboard:copy_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
|
||||
local content = node.nodes ~= nil and utils.path_add_trailing(absolute_path) or absolute_path
|
||||
self:copy_to_reg(content)
|
||||
|
||||
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
|
||||
function Clipboard:copy_basename(node)
|
||||
if node.name == ".." then
|
||||
-- root
|
||||
self:copy_to_reg(vim.fn.fnamemodify(node.explorer.absolute_path, ":t:r"))
|
||||
else
|
||||
-- node
|
||||
self:copy_to_reg(vim.fn.fnamemodify(node.name, ":r"))
|
||||
end
|
||||
end
|
||||
|
||||
---Node is cut. Will not be copied.
|
||||
|
||||
@@ -49,7 +49,7 @@ function M.fn(node)
|
||||
local containing_folder = utils.path_add_trailing(dir.absolute_path)
|
||||
|
||||
local input_opts = {
|
||||
prompt = "Create file ",
|
||||
prompt = "Create ",
|
||||
default = containing_folder,
|
||||
completion = "file",
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local view = require("nvim-tree.view")
|
||||
local view_state = require("nvim-tree.view-state")
|
||||
|
||||
local M = {}
|
||||
|
||||
@@ -7,7 +8,7 @@ local M = {}
|
||||
function M.fn(opts)
|
||||
if opts == nil then
|
||||
-- reset to config values
|
||||
view.configure_width()
|
||||
view_state.configure_width()
|
||||
view.resize()
|
||||
return
|
||||
end
|
||||
@@ -16,7 +17,7 @@ function M.fn(opts)
|
||||
local width_cfg = options.width
|
||||
|
||||
if width_cfg ~= nil then
|
||||
view.configure_width(width_cfg)
|
||||
view_state.configure_width(width_cfg)
|
||||
view.resize()
|
||||
return
|
||||
end
|
||||
|
||||
@@ -155,14 +155,15 @@ 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.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.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)
|
||||
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)
|
||||
api.fs.paste = en(function(e, n) e.clipboard:paste(n) end)
|
||||
api.fs.move = en(function(e, n) e.clipboard:paste(n, { cut = 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)
|
||||
|
||||
@@ -17,6 +17,28 @@ function M.global()
|
||||
end,
|
||||
})
|
||||
|
||||
if vim.fn.has("nvim-0.13") == 1 and config.g.experimental.session_restore_nvim then
|
||||
vim.api.nvim_create_autocmd("SessionWritePre", { ---@diagnostic disable-line: param-type-mismatch
|
||||
group = augroup_id,
|
||||
callback = function()
|
||||
-- We must schedule to wait until `vim.v.this_session` is properly updated
|
||||
-- This prevents overwriting the data if a new session is created with a new `:mksession`
|
||||
vim.schedule(require("nvim-tree.session").save)
|
||||
end,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd("SessionLoadPost", {
|
||||
group = augroup_id,
|
||||
-- Workaround: this event fires multiple times (report upstream),
|
||||
-- failure notifications could show up many times.
|
||||
once = true,
|
||||
callback = function()
|
||||
require("nvim-tree.session").restore()
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
if config.g.tab.sync.open then
|
||||
vim.api.nvim_create_autocmd("TabEnter", {
|
||||
group = augroup_id,
|
||||
|
||||
@@ -297,6 +297,7 @@ M.d = { -- config-default-start
|
||||
persist = false,
|
||||
},
|
||||
experimental = {
|
||||
session_restore_nvim = false
|
||||
},
|
||||
log = {
|
||||
enable = false,
|
||||
|
||||
@@ -90,7 +90,7 @@ function M.on_attach_default(bufnr)
|
||||
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", "x" }, "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"))
|
||||
@@ -102,6 +102,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.move, opts("Move"))
|
||||
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"))
|
||||
|
||||
103
lua/nvim-tree/session.lua
Normal file
103
lua/nvim-tree/session.lua
Normal file
@@ -0,0 +1,103 @@
|
||||
local notify = require("nvim-tree.notify")
|
||||
|
||||
local M = {}
|
||||
|
||||
local storepath = vim.fn.stdpath("data") .. "/nvim-tree-session.json"
|
||||
|
||||
local function decode_session_file()
|
||||
local file = io.open(storepath, "r")
|
||||
|
||||
if file then
|
||||
local content = file:read("*all")
|
||||
file:close()
|
||||
if content and content ~= "" then
|
||||
return vim.json.decode(content)
|
||||
end
|
||||
end
|
||||
-- Notifying on failure could be noisy, as it'd happen if the file simply did not exist
|
||||
end
|
||||
|
||||
local function write_session_file(session_file_content)
|
||||
local file, errmsg = io.open(storepath, "w")
|
||||
|
||||
if file then
|
||||
file:write(vim.json.encode(session_file_content))
|
||||
file:close()
|
||||
else
|
||||
notify.warn(string.format("Invalid session file (%s): %s", storepath, errmsg))
|
||||
end
|
||||
end
|
||||
|
||||
function M.save()
|
||||
-- We either always save the session data, which ends up populating the storepath with empty data
|
||||
-- Or we gate by the tree's visibility, which could create "out of sync" scenario:
|
||||
-- if the tree is initially open and the session is saved, it won't be overridden later,
|
||||
-- if the tree is no longer visible. However, when restoring, this is harmless.
|
||||
if require("nvim-tree.api").tree.is_visible({ any_tabpage = true }) then
|
||||
local ok, session_file_content = pcall(decode_session_file)
|
||||
|
||||
if not ok then
|
||||
notify.warn(string.format("Failed to decode session file (%s): %s", storepath, session_file_content))
|
||||
return
|
||||
end
|
||||
|
||||
-- might be nil at this point
|
||||
session_file_content = session_file_content or {}
|
||||
|
||||
local cwd = require("nvim-tree.core").get_cwd()
|
||||
|
||||
session_file_content[vim.v.this_session] = { cwd = cwd }
|
||||
|
||||
local ok2, err = pcall(write_session_file, session_file_content)
|
||||
|
||||
if not ok2 then
|
||||
notify.warn(string.format("Failed to write session file (%s): %s", storepath, err))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.restore()
|
||||
local api = require("nvim-tree.api").tree
|
||||
|
||||
---@type table<integer,boolean>
|
||||
local tabs = {}
|
||||
|
||||
local ok, session_file_content = pcall(decode_session_file)
|
||||
|
||||
-- Failing to restore cwd is not fatal, we can continue
|
||||
if not ok then
|
||||
notify.warn(string.format("Failed to decode session file (%s): %s", storepath, session_file_content))
|
||||
end
|
||||
|
||||
local path = session_file_content and session_file_content[vim.v.this_session] and session_file_content[vim.v.this_session].cwd or nil
|
||||
|
||||
-- Save tabs with leftover nvim-tree buffers
|
||||
for _, tab in ipairs(vim.api.nvim_list_tabpages()) do
|
||||
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tab)) do
|
||||
local buf = vim.api.nvim_win_get_buf(win)
|
||||
if api.is_tree_buf(buf) then
|
||||
tabs[tab] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- The new window may inherit options from the current one if we don't schedule
|
||||
vim.schedule(function()
|
||||
api.close_in_all_tabs()
|
||||
|
||||
for tab, _ in pairs(tabs) do
|
||||
if vim.api.nvim_tabpage_is_valid(tab) then
|
||||
local win = vim.api.nvim_tabpage_get_win(tab)
|
||||
|
||||
-- Invoke `open` from each tab's current window to prevent having to switch tabs
|
||||
if vim.api.nvim_win_is_valid(win) then
|
||||
vim.api.nvim_win_call(win, function()
|
||||
api.open({ path = path })
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -71,7 +71,7 @@ end
|
||||
|
||||
---Configure width-related config
|
||||
---@param width string|function|number|table|nil
|
||||
local function configure_width(width)
|
||||
function M.configure_width(width)
|
||||
if type(width) == "table" then
|
||||
M.Active.adaptive_size = true
|
||||
M.Active.width = width.min or DEFAULT_MIN_WIDTH
|
||||
@@ -101,7 +101,7 @@ function M.initialize()
|
||||
M.Active.winopts.relativenumber = config.g.view.relativenumber
|
||||
M.Active.winopts.signcolumn = config.g.view.signcolumn
|
||||
|
||||
configure_width(config.g.view.width)
|
||||
M.configure_width(config.g.view.width)
|
||||
|
||||
M.Active.initial_width = M.get_width()
|
||||
end
|
||||
|
||||
@@ -298,7 +298,7 @@ function M.resize(size)
|
||||
local new_size = view_state.get_width()
|
||||
|
||||
if new_size ~= vim.api.nvim_win_get_width(winnr) then
|
||||
vim.api.nvim_win_set_width(winnr, new_size)
|
||||
vim.api.nvim_win_set_width(winnr, new_size) ---@diagnostic disable-line: deprecated see #3344
|
||||
if not config.g.view.preserve_window_proportions then
|
||||
vim.cmd(":wincmd =")
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user