Skip to content

Commit

Permalink
feat: add node.open.toggle_group_empty, default mapping L (#2647)
Browse files Browse the repository at this point in the history
* feat: ungrouping empty directories

* add a new api to toggle empty folders

* solve comments

* solve comments

* update help

---------

Co-authored-by: juefei yan <[email protected]>
Co-authored-by: Alexander Courtis <[email protected]>
  • Loading branch information
3 people authored Feb 4, 2024
1 parent f39f7b6 commit 8cbb1db
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 7 deletions.
8 changes: 8 additions & 0 deletions doc/nvim-tree-lua.txt
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ Show the mappings: `g?`
`I` Toggle Filter: Git Ignore |nvim-tree-api.tree.toggle_gitignore_filter()|
`J` Last Sibling |nvim-tree-api.node.navigate.sibling.last()|
`K` First Sibling |nvim-tree-api.node.navigate.sibling.first()|
`L` Toggle Group Empty |nvim-tree-api.node.open.toggle_group_empty()|
`M` Toggle Filter: No Bookmark |nvim-tree-api.tree.toggle_no_bookmark_filter()|
`m` Toggle Bookmark |nvim-tree-api.marks.toggle()|
`o` Open |nvim-tree-api.node.open.edit()|
Expand Down Expand Up @@ -1848,6 +1849,12 @@ node.open.vertical() *nvim-tree-api.node.open.vertical()*
node.open.horizontal() *nvim-tree-api.node.open.horizontal()*
|nvim-tree-api.node.edit()|, file will be opened in a new horizontal split.

*nvim-tree-api.node.open.toggle_group_empty()*
node.open.toggle_group_empty()
Toggle |nvim-tree.renderer.group_empty| for a specific folder.
Does nothing on files.
Needs |nvim-tree.renderer.group_empty| set.

node.open.drop() *nvim-tree-api.node.open.drop()*
Switch to window with selected file if it exists.
Open file otherwise.
Expand Down Expand Up @@ -2196,6 +2203,7 @@ You are encouraged to copy these to your own |nvim-tree.on_attach| function.
vim.keymap.set('n', 'I', api.tree.toggle_gitignore_filter, opts('Toggle Filter: Git Ignore'))
vim.keymap.set('n', 'J', api.node.navigate.sibling.last, opts('Last Sibling'))
vim.keymap.set('n', 'K', api.node.navigate.sibling.first, opts('First Sibling'))
vim.keymap.set('n', 'L', api.node.open.toggle_group_empty, opts('Toggle Group Empty'))
vim.keymap.set('n', 'M', api.tree.toggle_no_bookmark_filter, opts('Toggle Filter: No Bookmark'))
vim.keymap.set('n', 'm', api.marks.toggle, opts('Toggle Bookmark'))
vim.keymap.set('n', 'o', api.node.open.edit, opts('Open'))
Expand Down
7 changes: 4 additions & 3 deletions lua/nvim-tree/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,13 @@ end

---@param mode string
---@return fun(node: table)
local function open_or_expand_or_dir_up(mode)
local function open_or_expand_or_dir_up(mode, toggle_group)
return function(node)
if node.name == ".." then
actions.root.change_dir.fn ".."
elseif node.nodes then
lib.expand_or_collapse(node)
else
lib.expand_or_collapse(node, toggle_group)
elseif not toggle_group then
edit(mode, node)
end
end
Expand All @@ -195,6 +195,7 @@ Api.node.open.no_window_picker = wrap_node(open_or_expand_or_dir_up "edit_no_pic
Api.node.open.vertical = wrap_node(open_or_expand_or_dir_up "vsplit")
Api.node.open.horizontal = wrap_node(open_or_expand_or_dir_up "split")
Api.node.open.tab = wrap_node(open_or_expand_or_dir_up "tabnew")
Api.node.open.toggle_group_empty = wrap_node(open_or_expand_or_dir_up("toggle_group_empty", true))
Api.node.open.preview = wrap_node(open_or_expand_or_dir_up "preview")
Api.node.open.preview_no_picker = wrap_node(open_or_expand_or_dir_up "preview_no_picker")

Expand Down
1 change: 1 addition & 0 deletions lua/nvim-tree/keymap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ function M.default_on_attach(bufnr)
vim.keymap.set('n', 'I', api.tree.toggle_gitignore_filter, opts('Toggle Filter: Git Ignore'))
vim.keymap.set('n', 'J', api.node.navigate.sibling.last, opts('Last Sibling'))
vim.keymap.set('n', 'K', api.node.navigate.sibling.first, opts('First Sibling'))
vim.keymap.set('n', 'L', api.node.open.toggle_group_empty, opts('Toggle Group Empty'))
vim.keymap.set('n', 'M', api.tree.toggle_no_bookmark_filter, opts('Toggle Filter: No Bookmark'))
vim.keymap.set('n', 'm', api.marks.toggle, opts('Toggle Bookmark'))
vim.keymap.set('n', 'o', api.node.open.edit, opts('Open'))
Expand Down
62 changes: 58 additions & 4 deletions lua/nvim-tree/lib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local view = require "nvim-tree.view"
local core = require "nvim-tree.core"
local utils = require "nvim-tree.utils"
local events = require "nvim-tree.events"
local explorer_node = require "nvim-tree.explorer.node"

---@class LibOpenOpts
---@field path string|nil path
Expand Down Expand Up @@ -86,6 +87,34 @@ function M.get_last_group_node(node)
return node
end

---Group empty folders
-- Recursively group nodes
---@param node Node
---@return Node[]
function M.group_empty_folders(node)
local is_root = not node.parent
local child_folder_only = explorer_node.has_one_child_folder(node) and node.nodes[1]
if M.group_empty and not is_root and child_folder_only then
node.group_next = child_folder_only
local ns = M.group_empty_folders(child_folder_only)
node.nodes = ns or {}
return ns
end
return node.nodes
end

---Ungroup empty folders
-- If a node is grouped, ungroup it: put node.group_next to the node.nodes and set node.group_next to nil
---@param node Node
function M.ungroup_empty_folders(node)
local cur = node
while cur and cur.group_next do
cur.nodes = { cur.group_next }
cur.group_next = nil
cur = cur.nodes[1]
end
end

---@param node Node
---@return Node[]
function M.get_all_nodes_in_group(node)
Expand All @@ -98,8 +127,21 @@ function M.get_all_nodes_in_group(node)
return nodes
end

-- Toggle group empty folders
---@param head_node Node
local function toggle_group_folders(head_node)
local is_grouped = head_node.group_next ~= nil

if is_grouped then
M.ungroup_empty_folders(head_node)
else
M.group_empty_folders(head_node)
end
end

---@param node Node
function M.expand_or_collapse(node)
function M.expand_or_collapse(node, toggle_group)
toggle_group = toggle_group or false
if node.has_children then
node.has_children = false
end
Expand All @@ -108,9 +150,20 @@ function M.expand_or_collapse(node)
core.get_explorer():expand(node)
end

local open = not M.get_last_group_node(node).open
for _, n in ipairs(M.get_all_nodes_in_group(node)) do
n.open = open
local head_node = utils.get_parent_of_group(node)
if toggle_group then
toggle_group_folders(head_node)
end

local open = M.get_last_group_node(node).open
local next_open
if toggle_group then
next_open = open
else
next_open = not open
end
for _, n in ipairs(M.get_all_nodes_in_group(head_node)) do
n.open = next_open
end

renderer.draw()
Expand Down Expand Up @@ -213,6 +266,7 @@ function M.setup(opts)
M.hijack_directories = opts.hijack_directories
M.respect_buf_cwd = opts.respect_buf_cwd
M.select_prompts = opts.select_prompts
M.group_empty = opts.renderer.group_empty
end

return M

0 comments on commit 8cbb1db

Please sign in to comment.