Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6b1f5b8
chore: moving root action dir-up to explorer class
Uanela Dec 9, 2025
41585a8
chore(explorer): moving requires to top level
Uanela Dec 19, 2025
a12890c
wip(explorer): moved all change-dir functions to explorer class
Uanela Dec 27, 2025
fd5ee1d
wip(explorer): rename M.current_tab to self.current_tab
Uanela Dec 27, 2025
85b621b
chore(explorer): move change_dir root action to explorer and replace …
Uanela Dec 27, 2025
896e629
refactor(explorer): changing _foldername to folder_name
Uanela Dec 27, 2025
2ea9992
merge with master
Uanela Dec 27, 2025
5084dd4
wip(explorer): rename expand method to expand_dir_node and all places…
Uanela Dec 27, 2025
d5b8ead
wip(explorer): mark private methods and remove add_profiling_to method
Uanela Dec 28, 2025
0d6eefd
fix: allow changing root to file`s parent directory and fix restrict_…
Uanela Dec 28, 2025
db36b04
refactor(api): moving change_root_to_node to Explorer:change_dir_to_node
Uanela Dec 28, 2025
189c036
Merge branch 'master' of https://github.com/uanela/nvim-tree.lua into…
Uanela Jan 22, 2026
195f924
fix(explorer): get new explorer before redrawing on <C-]>
Uanela Jan 22, 2026
fd300ed
docs(explorer): adding link to PR discussion for more context
Uanela Jan 22, 2026
4995699
fix(explorer): correctly check config.actions.change_dir for change_d…
Uanela Jan 22, 2026
986c79a
fix: correctly pass explorer as first arg when calling explorer metho…
Uanela Jan 22, 2026
e4f7cc5
fix: correctly pass args to change_dir
Uanela Jan 22, 2026
0933b46
fix: check for explorer before force_dirchange in open_on_directory
Uanela Jan 23, 2026
47c8a7e
Merge branch 'master' into moving-change-dir-to-explorer
Uanela Jan 23, 2026
b97299e
fix: check if force_dirchange should call core.init
Uanela Jan 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions lua/nvim-tree.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ local M = {
init_root = "",
}

--- Helper function to execute some explorer method safely
---@param fn string # key of explorer
---@return function|nil
local function explorer_fn(fn)
local explorer = core.get_explorer()
if explorer then
return explorer[fn]
end
end
Comment thread
alex-courtis marked this conversation as resolved.

--- Update the tree root to a directory or the directory containing
---@param path string relative or absolute
---@param bufnr number|nil
Expand Down Expand Up @@ -47,7 +57,7 @@ function M.change_root(path, bufnr)
-- test if in vim_cwd
if utils.path_relative(path, vim_cwd) ~= path then
if vim_cwd ~= cwd then
actions.root.change_dir.fn(vim_cwd)
explorer_fn("change_dir")(vim_cwd)
end
return
end
Expand All @@ -58,19 +68,19 @@ function M.change_root(path, bufnr)

-- otherwise test M.init_root
if _config.prefer_startup_root and utils.path_relative(path, M.init_root) ~= path then
actions.root.change_dir.fn(M.init_root)
explorer_fn("change_dir")(M.init_root)
return
end
-- otherwise root_dirs
for _, dir in pairs(_config.root_dirs) do
dir = vim.fn.fnamemodify(dir, ":p")
if utils.path_relative(path, dir) ~= path then
actions.root.change_dir.fn(dir)
explorer_fn("change_dir")(dir)
return
end
end
-- finally fall back to the folder containing the file
actions.root.change_dir.fn(vim.fn.fnamemodify(path, ":p:h"))
explorer_fn("change_dir")(vim.fn.fnamemodify(path, ":p:h"))
end

function M.tab_enter()
Expand Down Expand Up @@ -110,7 +120,7 @@ function M.open_on_directory()
return
end

actions.root.change_dir.force_dirchange(bufname, true)
explorer_fn("force_dirchange")(bufname, true)
end

---@return table
Expand All @@ -134,7 +144,7 @@ end
---@param name string|nil
function M.change_dir(name)
if name then
actions.root.change_dir.fn(name)
explorer_fn("change_dir")(name)
end

if _config.update_focused_file.update_root.enable then
Expand Down
2 changes: 0 additions & 2 deletions lua/nvim-tree/actions/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ M.finders = require("nvim-tree.actions.finders")
M.fs = require("nvim-tree.actions.fs")
M.moves = require("nvim-tree.actions.moves")
M.node = require("nvim-tree.actions.node")
M.root = require("nvim-tree.actions.root")
M.tree = require("nvim-tree.actions.tree")

function M.setup(opts)
M.fs.setup(opts)
M.node.setup(opts)
M.root.setup(opts)
M.tree.setup(opts)
end

Expand Down
105 changes: 0 additions & 105 deletions lua/nvim-tree/actions/root/change-dir.lua

This file was deleted.

9 changes: 0 additions & 9 deletions lua/nvim-tree/actions/root/init.lua

This file was deleted.

21 changes: 7 additions & 14 deletions lua/nvim-tree/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ local keymap = require("nvim-tree.keymap")
local notify = require("nvim-tree.notify")

local DirectoryNode = require("nvim-tree.node.directory")
local FileNode = require("nvim-tree.node.file")
local FileLinkNode = require("nvim-tree.node.file-link")
local RootNode = require("nvim-tree.node.root")
local UserDecorator = require("nvim-tree.renderer.decorator.user")
Expand Down Expand Up @@ -160,18 +159,12 @@ end)

Api.tree.change_root_to_node = wrap_node(function(node)
if node.name == ".." or node:is(RootNode) then
actions.root.change_dir.fn("..")
return
end

if node:is(FileNode) and node.parent ~= nil then
actions.root.change_dir.fn(node.parent:last_group_node().absolute_path)
Comment thread
alex-courtis marked this conversation as resolved.
return
end

if node:is(DirectoryNode) then
actions.root.change_dir.fn(node:last_group_node().absolute_path)
return
wrap_explorer("change_dir")("..")
else
node = node:as(DirectoryNode)
if node then
wrap_explorer("change_dir")(node:last_group_node().absolute_path)
end
end
end)

Expand Down Expand Up @@ -281,7 +274,7 @@ local function open_or_expand_or_dir_up(mode, toggle_group)
local dir = node:as(DirectoryNode)

if root or node.name == ".." then
actions.root.change_dir.fn("..")
wrap_explorer("change_dir")("..")
Comment thread
alex-courtis marked this conversation as resolved.
elseif dir then
dir:expand_or_collapse(toggle_group)
elseif not toggle_group then
Expand Down
117 changes: 108 additions & 9 deletions lua/nvim-tree/explorer/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ local Clipboard = require("nvim-tree.actions.fs.clipboard")
local Renderer = require("nvim-tree.renderer")

local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON
local change_dir = require("nvim-tree.actions.root.change-dir")
local find_file = require("nvim-tree.actions.finders.find-file")

local config
Expand All @@ -31,6 +30,7 @@ local config
---@field uid_explorer number vim.loop.hrtime() at construction time
---@field opts table user options
---@field augroup_id integer
---@field current_tab integer
---@field renderer Renderer
---@field filters Filters
---@field live_filter LiveFilter
Expand Down Expand Up @@ -60,12 +60,15 @@ function Explorer:new(args)
self.open = true
self.opts = config

self.sorters = Sorter({ explorer = self })
self.renderer = Renderer({ explorer = self })
self.filters = Filters({ explorer = self })
self.live_filter = LiveFilter({ explorer = self })
self.marks = Marks({ explorer = self })
self.clipboard = Clipboard({ explorer = self })

self.sorters = Sorter({ explorer = self })
self.renderer = Renderer({ explorer = self })
self.filters = Filters({ explorer = self })
self.live_filter = LiveFilter({ explorer = self })
self.marks = Marks({ explorer = self })
self.clipboard = Clipboard({ explorer = self })

self.current_tab = vim.api.nvim_get_current_tabpage()
Comment thread
alex-courtis marked this conversation as resolved.

self:create_autocmds()

Expand Down Expand Up @@ -664,15 +667,15 @@ end
---@param node Node
function Explorer:dir_up(node)
if not node or node.name == ".." then
change_dir.fn("..")
self:change_dir("..")
else
local cwd = core.get_cwd()
if cwd == nil then
return
end
Comment thread
alex-courtis marked this conversation as resolved.
Outdated

local newdir = vim.fn.fnamemodify(utils.path_remove_trailing(cwd), ":h")
change_dir.fn(newdir)
self:change_dir(newdir)
find_file.fn(node.absolute_path)
end
end
Expand All @@ -683,6 +686,102 @@ function Explorer:get_nodes()
return self:clone()
end

---@param new_tabpage integer
---@return boolean
function Explorer:is_window_event(new_tabpage)
local is_event_scope_window = vim.v.event.scope == "window" or vim.v.event.changed_window or false
return is_event_scope_window and new_tabpage == self.current_tab
end

---@param name string
---@return string|nil
function Explorer:clean_input_cwd(name)
Comment thread
alex-courtis marked this conversation as resolved.
name = vim.fn.fnameescape(name)
local cwd = core.get_cwd()
if cwd == nil then
return
end
local root_parent_cwd = vim.fn.fnamemodify(utils.path_remove_trailing(cwd), ":h")
if name == ".." and root_parent_cwd then
return vim.fn.expand(root_parent_cwd)
else
return vim.fn.expand(name)
end
end

---@param foldername string
---@return boolean
function Explorer:prevent_cwd_change(foldername)
local is_same_cwd = foldername == core.get_cwd()
local is_restricted_above = config.restrict_above_cwd and foldername < vim.fn.getcwd(-1, -1)
Comment thread
alex-courtis marked this conversation as resolved.
Outdated
return is_same_cwd or is_restricted_above
end

---@param f function
---@return fun(foldername: string, should_open_view: boolean|nil)
function Explorer:add_profiling_to(f)
Comment thread
alex-courtis marked this conversation as resolved.
Outdated
return function(foldername, should_open_view)
local profile = log.profile_start("change dir %s", foldername)
f(foldername, should_open_view)
log.profile_end(profile)
end
end

---@return boolean
function Explorer:should_change_dir()
return config.enable and vim.tbl_isempty(vim.v.event)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return config.enable and vim.tbl_isempty(vim.v.event)
return config.actions.change_dir.enable and vim.tbl_isempty(vim.v.event)

end

---@param global boolean
---@param path string
function Explorer:cd(global, path)
vim.cmd((global and "cd " or "lcd ") .. vim.fn.fnameescape(path))
end

function Explorer:force_dirchange(folder_name, with_open)
local fn = self:add_profiling_to(function(foldername, should_open_view)
local valid_dir = vim.fn.isdirectory(foldername) == 1 -- prevent problems on non existing dirs
if valid_dir then
if self:should_change_dir() then
self:cd(config.global, foldername)
end
core.init(foldername)
end

if should_open_view then
require("nvim-tree.lib").open()
else
local explorer = core.get_explorer()
if explorer then
explorer.renderer:draw()
end
Comment thread
alex-courtis marked this conversation as resolved.
Outdated
end
end)

fn(folder_name, with_open)
end

---@param input_cwd string
---@param with_open boolean|nil
function Explorer:change_dir(input_cwd, with_open)
if not core.get_explorer() then
return
end
Comment thread
alex-courtis marked this conversation as resolved.
Outdated

local new_tabpage = vim.api.nvim_get_current_tabpage()
if self:is_window_event(new_tabpage) then
return
end

local foldername = self:clean_input_cwd(input_cwd)
if foldername == nil or self:prevent_cwd_change(foldername) then
return
end

self.current_tab = new_tabpage
self:force_dirchange(foldername, with_open)
end

function Explorer:setup(opts)
config = opts
end
Expand Down
Loading
Loading