mirror of
https://github.com/nvim-tree/nvim-tree.lua.git
synced 2026-07-28 15:59:44 +05:30
Compare commits
10 Commits
feat/add-d
...
c97f42044d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c97f42044d | ||
|
|
4213bd6eab | ||
|
|
f2dd529e3f | ||
|
|
cf18a662cd | ||
|
|
a797d5e201 | ||
|
|
35d3511e7a | ||
|
|
7ff7040bf6 | ||
|
|
531b807b8f | ||
|
|
c760c92667 | ||
|
|
8f73cbb7d2 |
@@ -1,3 +1,3 @@
|
||||
{
|
||||
".": "1.17.0"
|
||||
".": "1.18.0"
|
||||
}
|
||||
|
||||
15
CHANGELOG.md
15
CHANGELOG.md
@@ -1,5 +1,20 @@
|
||||
# Changelog
|
||||
|
||||
## [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
|
||||
|
||||
|
||||
@@ -1911,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*
|
||||
|
||||
@@ -2216,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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -181,7 +181,10 @@ end
|
||||
---@param node_or_nodes Node|Node[]
|
||||
---@return boolean
|
||||
function Clipboard:is_nodes_array(node_or_nodes)
|
||||
return type(node_or_nodes) == "table" and node_or_nodes.is and node_or_nodes:is(Node)
|
||||
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
|
||||
@@ -374,7 +377,7 @@ 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 then
|
||||
if is_local == false then
|
||||
self:destroy_nodes(clip)
|
||||
end
|
||||
return
|
||||
@@ -399,18 +402,7 @@ function Clipboard:do_paste(node, action, action_fn)
|
||||
|
||||
-- Paste non-conflicting items immediately
|
||||
for _, item in ipairs(no_conflict) do
|
||||
local absolute_path = item.node.absolute_path
|
||||
if absolute_path:sub(1, #"http") == "http" then
|
||||
notify.info("Downloading " .. absolute_path .. " to " .. item.dest .. "...")
|
||||
local result = vim.fn.system({ "curl", "-sL", absolute_path, "-o", item.dest })
|
||||
if vim.v.shell_error == 0 then
|
||||
notify.info("Downloaded " .. absolute_path .. " successfully at " .. item.dest)
|
||||
else
|
||||
notify.error("Error downloading " .. absolute_path .. ": " .. result)
|
||||
end
|
||||
else
|
||||
do_paste_one(absolute_path, item.dest, action, action_fn)
|
||||
end
|
||||
do_paste_one(item.node.absolute_path, item.dest, action, action_fn)
|
||||
end
|
||||
|
||||
-- Resolve conflicts in batch
|
||||
@@ -420,7 +412,7 @@ function Clipboard:do_paste(node, action, action_fn)
|
||||
self:finish_paste(action)
|
||||
end
|
||||
|
||||
if ~is_local then
|
||||
if is_local == false then
|
||||
self:destroy_nodes(clip)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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,5 +1,6 @@
|
||||
-- Copyright 2019 Yazdani Kiyan under MIT License
|
||||
local lib = require("nvim-tree.lib")
|
||||
local log = require("nvim-tree.log")
|
||||
local notify = require("nvim-tree.notify")
|
||||
local utils = require("nvim-tree.utils")
|
||||
local full_name = require("nvim-tree.renderer.components.full-name")
|
||||
@@ -94,7 +95,12 @@ local function pick_win_id()
|
||||
return not vim.tbl_contains(selectable, id)
|
||||
end, win_ids)
|
||||
|
||||
if laststatus == 3 then
|
||||
-- experiment only for #3323
|
||||
local clear_not_selectable_statusline = false
|
||||
|
||||
log.line("dev", "clear_unselectable_statusline=%s", clear_not_selectable_statusline)
|
||||
|
||||
if clear_not_selectable_statusline then
|
||||
for _, win_id in ipairs(not_selectable) do
|
||||
local ok_status, statusline = pcall(vim.api.nvim_get_option_value, "statusline", { win = win_id })
|
||||
|
||||
@@ -144,7 +150,7 @@ local function pick_win_id()
|
||||
end
|
||||
end
|
||||
|
||||
if laststatus == 3 then
|
||||
if clear_not_selectable_statusline then
|
||||
for _, id in ipairs(not_selectable) do
|
||||
-- Ensure window still exists at this point
|
||||
if vim.api.nvim_win_is_valid(id) then
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
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