Skip to content

feat(#2789): add optional function expand_until to api.tree.expand_all and api.node.expand #3166

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Aug 11, 2025

Conversation

ghostbuster91
Copy link
Contributor

@ghostbuster91 ghostbuster91 commented Jul 20, 2025

This closes #2789

It took me a while but here I am :) I decided to create a fresh one as it was easier then resolving conflicts on the old one.

For now bare minimum of the changes that makes it work. Once we agree how the api will look like I will add docs following what we did in #2790

Api.tree.expand_all = wrap_node(actions.tree.modifiers.expand.all)

Api.tree.toggle_descend_until = wrap_node(function(node, descend_until)
Copy link
Contributor Author

@ghostbuster91 ghostbuster91 Jul 20, 2025

Choose a reason for hiding this comment

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

note: this is actually what I would like to achieve in the end. The edit part is wrong as nodes are not getting collapsed after hitting enter for the second time. Can you advise? fixed

question: how should the end user api look like?

Copy link
Member

Choose a reason for hiding this comment

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

This will be very useful, however it needs a bit of thought.

Can we please do this in a future PR? The functionality for the API expands is working and we can merge that now.

What should it look like? This isn't something the user should have to do; it should be core functionality.

It could go into node.open.edit, as a new member of NodeEditOpts

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doing it in a separate PR makes perfect sense 👍

@alex-courtis
Copy link
Member

Thanks for getting back to this one @ghostbuster91

My time is limited, however I will get to reviewing next weekend.

FYI the nightly CI failure has been resolved on master: #3167

@alex-courtis
Copy link
Member

The descend filter functionality working beautifully for api.tree.expand_all and api.node.expand

Small issue: When the nodes are grouped, the arrow indicates open for a directory that is not traversed e.g.

20250728_105539
#!/bin/sh

rm -rfv foo

mkdir -pv foo/bar foo/baz foo/stop foo/baz/stop

touch foo/bar/1
touch foo/bar/2

touch foo/stop/3
touch foo/stop/4

touch foo/baz/stop/5
touch foo/baz/stop/6
---@type ApiTreeExpandAllOpts
local expand_all_opts = {
  descend_until = function(i, node)
    print(i .. " " .. node.name)
    return node.name ~= "stop" and node.name ~= ".git" and node.name ~= "7"
  end
}

  vim.keymap.set("n", "A", function()
    api.tree.expand_all(nil, expand_all_opts)
  end, opts("expand"))

  vim.keymap.set("n", "N", function()
    api.node.expand(nil, expand_all_opts)
  end, opts("expand"))

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.

Looking good, let's merge the expand functionality now.

Please:

Api.tree.expand_all = wrap_node(actions.tree.modifiers.expand.all)

Api.tree.toggle_descend_until = wrap_node(function(node, descend_until)
Copy link
Member

Choose a reason for hiding this comment

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

This will be very useful, however it needs a bit of thought.

Can we please do this in a future PR? The functionality for the API expands is working and we can merge that now.

What should it look like? This isn't something the user should have to do; it should be core functionality.

It could go into node.open.edit, as a new member of NodeEditOpts

@ghostbuster91
Copy link
Contributor Author

All comments have been addressed. Ready for the final review

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.

We're getting really close.

  • Expand all does not expand grouped nodes
  • expand.lua expects descend_until from the user, not expand_until
  • Help needs to document expand_until; I'll do that one
  • max_folder_discovery is not obeyed when using expand_until

api.tree.expand_all with no expand_until

20250804_103435

api.tree.expand on node with no expand_until

20250804_103606

This doesn't apply:

---@type ApiTreeExpandOpts
local expand_all_opts = {
  expand_until = function(i, node)
    print(i .. " " .. node.name)
    return node.name ~= "stop" and node.name ~= ".git" and node.name ~= "7"
  end
}

@alex-courtis
Copy link
Member

alex-courtis commented Aug 4, 2025

tree.expand_all({node}, {opts})              *nvim-tree-api.tree.expand_all()*
    Recursively expand all nodes under the tree root or specified folder.

    Parameters: ~{node} (Node|nil) folder
      • {opts} (ApiTreeExpandOpts) optional parameters

    Options: ~
      • {expand_until} ((fun(expansion_count: integer, node: Node?): boolean)?)
            Return true if {node} should be expanded.
            {expansion_count} is the total number of folders expanded.
node.expand({node}, {opts})                      *nvim-tree-api.node.expand()*
    Recursively expand all nodes under a directory or a file's parent
    directory.

    Parameters: ~{node} (Node|nil) file or folder
      • {opts} (ApiTreeExpandOpts) optional parameters

    Options: ~
      • {expand_until} ((fun(expansion_count: integer, node: Node?): boolean)?)
            Return true if {node} should be expanded.
            {expansion_count} is the total number of folders expanded.

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.

Many thanks for all your work on this one @ghostbuster91 , it's not been easy.

In the interest of speed, I'm applying the nits and merging.

@@ -72,12 +129,13 @@ local function gen_iterator()
end
Copy link
Member

Choose a reason for hiding this comment

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

The max folder discovery test above does not appear to be necessary as limit_folder_discovery does the job.

Commenting this out results in the correct number of folders being expanded, just no message.

Having the same test twice in two locations is fragile and unclear.

Proposal: limit_folder_discovery prints the warning and gen_iterator's function returns nothing.

@alex-courtis alex-courtis changed the title feat: Allow to expand nodes until certain condition is met feat: add optional function expand_until to api.tree.expand_all and api.node.expand Aug 11, 2025
@alex-courtis alex-courtis changed the title feat: add optional function expand_until to api.tree.expand_all and api.node.expand feat(#2789): add optional function expand_until to api.tree.expand_all and api.node.expand Aug 11, 2025
@alex-courtis alex-courtis merged commit 1b876db into nvim-tree:master Aug 11, 2025
4 checks passed
@ghostbuster91 ghostbuster91 deleted the expand-until-2 branch August 11, 2025 07:44
@ghostbuster91
Copy link
Contributor Author

thanks @alex-courtis for the reviews and tests. I appreciate the effort.

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.

Allow nodes to expand until a certain condition is met.
2 participants