From d036b069b315dc56704bd9420cea19f84cb902af Mon Sep 17 00:00:00 2001 From: juefei yan Date: Mon, 29 Jan 2024 22:32:31 -0800 Subject: [PATCH] add a new api to toggle empty folders --- doc/nvim-tree-lua.txt | 5 +++++ lua/nvim-tree/api.lua | 5 +++-- lua/nvim-tree/keymap.lua | 1 + lua/nvim-tree/lib.lua | 39 +++++++++++++++++++++++++++++---------- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 32696f10999..11e032c3059 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -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` Group or Ungroup Folders |nvim-tree-api.node.tree.toggle_grouped_folders()| `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()| @@ -1848,6 +1849,9 @@ 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. +node.open.toggle_grouped_folders() *nvim-tree-api.node.open.toggle_grouped_folders()* + |nvim-tree-api.node.edit()|, empty folders would be grouped or ungrouped. + node.open.drop() *nvim-tree-api.node.open.drop()* Switch to window with selected file if it exists. Open file otherwise. @@ -2196,6 +2200,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_grouped_folders,opts('Toggle Grouped Folders')) 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')) diff --git a/lua/nvim-tree/api.lua b/lua/nvim-tree/api.lua index 3c85071e899..25f4d5208d6 100644 --- a/lua/nvim-tree/api.lua +++ b/lua/nvim-tree/api.lua @@ -175,12 +175,12 @@ 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) + lib.expand_or_collapse(node, toggle_group) else edit(mode, node) end @@ -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_grouped_folders = wrap_node(open_or_expand_or_dir_up("toggle_grouped_folders", 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") diff --git a/lua/nvim-tree/keymap.lua b/lua/nvim-tree/keymap.lua index 700a479461e..ec769551325 100644 --- a/lua/nvim-tree/keymap.lua +++ b/lua/nvim-tree/keymap.lua @@ -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_grouped_folders,opts('Toggle Grouped Folders')) 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')) diff --git a/lua/nvim-tree/lib.lua b/lua/nvim-tree/lib.lua index f040f2e3cbe..16d37580d3b 100644 --- a/lua/nvim-tree/lib.lua +++ b/lua/nvim-tree/lib.lua @@ -88,6 +88,7 @@ function M.get_last_group_node(node) end ---Group empty folders +-- Recursively group nodes ---@param node Node ---@return Node[] function M.group_empty_folders(node) @@ -102,7 +103,8 @@ function M.group_empty_folders(node) return node.nodes end ----Group empty folders +---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 @@ -125,8 +127,26 @@ function M.get_all_nodes_in_group(node) return nodes end +-- If a folder is grouped and closed -> group folder and open +-- If a folder is grouped and opened -> ungroup folder and open +-- If a folder is ungrouped and opened -> group folder and close +---@param head_node Node +---@param open boolean +---@return boolean +local function toggle_group_folders(head_node, open) + local is_grouped = head_node.group_next ~= nil + + if open and is_grouped then + M.ungroup_empty_folders(head_node) + elseif open then + M.group_empty_folders(head_node) + end + return is_grouped or not open +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 @@ -135,17 +155,16 @@ function M.expand_or_collapse(node) core.get_explorer():expand(node) end - local open = M.get_last_group_node(node).open local head_node = utils.get_parent_of_group(node) - local is_grouped = head_node.group_next ~= nil - - if open and is_grouped then - M.ungroup_empty_folders(head_node) - elseif open then - M.group_empty_folders(head_node) + local open = M.get_last_group_node(node).open + if toggle_group then + open = toggle_group_folders(head_node, open) + else + open = not open end + for _, n in ipairs(M.get_all_nodes_in_group(head_node)) do - n.open = is_grouped or not open + n.open = open end renderer.draw()