Skip to content

Conversation

@Uanela
Copy link
Collaborator

@Uanela Uanela commented Dec 28, 2025

Description

Refactors the expand functionality by moving it from the actions layer into node methods, improving encapsulation and making the code more object-oriented.

Changes

  • Removed lua/nvim-tree/actions/tree/modifiers/expand.lua module
  • Moved expansion logic into DirectoryNode and Explorer classes as methods
  • Added DirectoryNode:expand() - public method for recursive directory expansion
  • Added DirectoryNode:expand_dir_node() - helper to open and load a single directory
  • Added Node:expand() - dispatcher that handles both file and directory nodes
  • Added Explorer:expand_all() and Explorer:expand_node() - wrapper methods for the API
  • Updated API endpoints to use new Explorer methods via wrap_explorer
  • Replaced core.get_explorer() calls with self.explorer references
  • Renamed Explorer:expand() to Explorer:expand_dir_node() to avoid naming conflicts
  • Removed modifiers.setup() as it's no longer needed

Benefits

  • Better encapsulation: expansion behavior lives with the node data structures
  • Reduced coupling between actions and core modules
  • More intuitive API: nodes know how to expand themselves
  • Easier to maintain and extend

Related Issues

Closes #3225

Move expansion logic from actions/tree/modifiers/expand.lua into
DirectoryNode and Explorer methods. Update API to use new methods
via wrap_explorer. Remove expand module and its setup calls.
@Uanela Uanela requested a review from alex-courtis December 28, 2025 17:46
@alex-courtis alex-courtis changed the title refactor(#2255): multi instance - move expand actions to nodes refactor(#3225): multi instance - move expand actions to nodes Jan 3, 2026
---@param should_descend fun(expansion_count: integer, node: Node): boolean
---@return fun(expansion_count: integer, node: Node): boolean
function DirectoryNode:limit_folder_discovery(should_descend)
local MAX_FOLDER_DISCOVERY = self.explorer.opts.actions.expand_all.max_folder_discovery
Copy link
Member

Choose a reason for hiding this comment

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

Nice one. Reading it here will allow us to dynamically change actions.expand_all.max_folder_discovery

---@param _ integer expansion_count
---@return boolean
function DirectoryNode:descend_until_empty(_)
local EXCLUDE = to_lookup_table(self.explorer.opts.actions.expand_all.exclude)
Copy link
Member

Choose a reason for hiding this comment

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

Again nice, allows dynamic changes to actions.expand_all.exclude

@alex-courtis
Copy link
Member

Base Test Cases

Setup

cd /tmp
git clone git@github.com:rvaiya/keyd.git

Startup Nvim - Fail

Start nvim in /tmp/keyd

Error detected while processing /tmp/nd/config/nvim/nd.lua:
E5113: Error while calling lua chunk: ...cker/start/nvim-tree.lua.dev/lua/nvim-tree/node/init.lua:2: loop or previous error loading module 'nvi
m-tree.node.directory'
stack traceback:
        [C]: in function 'require'
        ...cker/start/nvim-tree.lua.dev/lua/nvim-tree/node/init.lua:2: in main chunk
        [C]: in function 'require'
        ...start/nvim-tree.lua.dev/lua/nvim-tree/node/directory.lua:6: in main chunk
        [C]: in function 'require'
        ...tree.lua.dev/lua/nvim-tree/actions/finders/find-file.lua:6: in main chunk
        [C]: in function 'require'
        ...nvim-tree.lua.dev/lua/nvim-tree/actions/finders/init.lua:3: in main chunk
        [C]: in function 'require'
        ...r/start/nvim-tree.lua.dev/lua/nvim-tree/actions/init.lua:3: in main chunk
        [C]: in function 'require'
        ...ack/packer/start/nvim-tree.lua.dev/lua/nvim-tree/api.lua:4: in main chunk
        [C]: in function 'require'
        /tmp/nd/config/nvim/nd.lua:48: in main chunk

We have an unresovleable circular dependency, as DirectorNode etc. will always require Node.

Recommendation: remove unnecessary type testing.

---@param expand_opts ApiTreeExpandOpts?
function Node:expand(expand_opts)
  if self.parent then
    self.parent:expand(expand_opts)
  end
end

Good OO design directs that parent types should never be aware of child types.
We do not need to test for a DirectoryNode as this method will never be called on a DirectoryNode. The sub-class method DirectoryNode:expand will be always be called instead.
We do not need to test for a FileNode as the parent is a field of Node and should be used for all nodes except for DirectoryNodes which are handled above.

Expand Root - Fail

Start nvim in /tmp/keyd

E at root

Expected: root should expand until MAX_FOLDER_DISCOVERY

E5108: Error executing lua: ...start/nvim-tree.lua.dev/lua/nvim-tree/node/directory.lua:326: attempt to index local 'self' (a number value)
stack traceback:
        ...start/nvim-tree.lua.dev/lua/nvim-tree/node/directory.lua:326: in function 'should_descend'
        ...start/nvim-tree.lua.dev/lua/nvim-tree/node/directory.lua:342: in function 'should_expand'
        ...start/nvim-tree.lua.dev/lua/nvim-tree/node/directory.lua:375: in function '_apply_fn_on_node'
        ...m-tree.lua.dev/lua/nvim-tree/iterators/node-iterator.lua:63: in function 'iterate'
        ...start/nvim-tree.lua.dev/lua/nvim-tree/node/directory.lua:398: in function <...start/nvim-tree.lua.dev/lua/nvim-tree/node/directory.lua:366>
        ...start/nvim-tree.lua.dev/lua/nvim-tree/node/directory.lua:406: in function 'expand'
        .../start/nvim-tree.lua.dev/lua/nvim-tree/explorer/init.lua:691: in function <.../start/nvim-tree.lua.dev/lua/nvim-tree/explorer/init.lua:689>

My statement "Other functions above should be private methods" in the issue is incorrect and was not properly thought out and for that I apologise.

should_expand, descend_until_empty etc are passed as around as functions and invoked during Iterator. It is not practical to use methods for these functions as the self to use is unclear. The refactoring and rewriting required would be great.

Recommendation: revert should_expand etc. to local functions. This isn't ideal, however avoids the risky rewriting.

Copy link
Member

@alex-courtis alex-courtis left a comment

Choose a reason for hiding this comment

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

This is looking good, it is tidying up and encapsulating nicely.

We have a couple of test failures. Please

  • resolve the circular dependency
  • fix expand root

In the future please test startup, basic functionality and your changes before submitting a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multi Instance: Refactor: Move actions/tree/modifiers/expand.lua To Explorer, DirectoryNode and Node

2 participants