feat: add node.open.toggle_group_empty, default mapping L (#2647)
* feat: ungrouping empty directories * add a new api to toggle empty folders * solve comments * solve comments * update help --------- Co-authored-by: juefei yan <juefeiyan@juefeis-MacBook-Air.local> Co-authored-by: Alexander Courtis <alex@courtis.org>
This commit is contained in:
parent
f39f7b6fcd
commit
8cbb1db8e9
@ -181,6 +181,7 @@ Show the mappings: `g?`
|
|||||||
`I` Toggle Filter: Git Ignore |nvim-tree-api.tree.toggle_gitignore_filter()|
|
`I` Toggle Filter: Git Ignore |nvim-tree-api.tree.toggle_gitignore_filter()|
|
||||||
`J` Last Sibling |nvim-tree-api.node.navigate.sibling.last()|
|
`J` Last Sibling |nvim-tree-api.node.navigate.sibling.last()|
|
||||||
`K` First Sibling |nvim-tree-api.node.navigate.sibling.first()|
|
`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 Filter: No Bookmark |nvim-tree-api.tree.toggle_no_bookmark_filter()|
|
||||||
`m` Toggle Bookmark |nvim-tree-api.marks.toggle()|
|
`m` Toggle Bookmark |nvim-tree-api.marks.toggle()|
|
||||||
`o` Open |nvim-tree-api.node.open.edit()|
|
`o` Open |nvim-tree-api.node.open.edit()|
|
||||||
@ -1848,6 +1849,12 @@ node.open.vertical() *nvim-tree-api.node.open.vertical()*
|
|||||||
node.open.horizontal() *nvim-tree-api.node.open.horizontal()*
|
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.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()*
|
node.open.drop() *nvim-tree-api.node.open.drop()*
|
||||||
Switch to window with selected file if it exists.
|
Switch to window with selected file if it exists.
|
||||||
Open file otherwise.
|
Open file otherwise.
|
||||||
@ -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', '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', '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', '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.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', 'm', api.marks.toggle, opts('Toggle Bookmark'))
|
||||||
vim.keymap.set('n', 'o', api.node.open.edit, opts('Open'))
|
vim.keymap.set('n', 'o', api.node.open.edit, opts('Open'))
|
||||||
|
|||||||
@ -175,13 +175,13 @@ end
|
|||||||
|
|
||||||
---@param mode string
|
---@param mode string
|
||||||
---@return fun(node: table)
|
---@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)
|
return function(node)
|
||||||
if node.name == ".." then
|
if node.name == ".." then
|
||||||
actions.root.change_dir.fn ".."
|
actions.root.change_dir.fn ".."
|
||||||
elseif node.nodes then
|
elseif node.nodes then
|
||||||
lib.expand_or_collapse(node)
|
lib.expand_or_collapse(node, toggle_group)
|
||||||
else
|
elseif not toggle_group then
|
||||||
edit(mode, node)
|
edit(mode, node)
|
||||||
end
|
end
|
||||||
end
|
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.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.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.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 = 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")
|
Api.node.open.preview_no_picker = wrap_node(open_or_expand_or_dir_up "preview_no_picker")
|
||||||
|
|
||||||
|
|||||||
@ -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', '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', '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', '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.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', 'm', api.marks.toggle, opts('Toggle Bookmark'))
|
||||||
vim.keymap.set('n', 'o', api.node.open.edit, opts('Open'))
|
vim.keymap.set('n', 'o', api.node.open.edit, opts('Open'))
|
||||||
|
|||||||
@ -3,6 +3,7 @@ local view = require "nvim-tree.view"
|
|||||||
local core = require "nvim-tree.core"
|
local core = require "nvim-tree.core"
|
||||||
local utils = require "nvim-tree.utils"
|
local utils = require "nvim-tree.utils"
|
||||||
local events = require "nvim-tree.events"
|
local events = require "nvim-tree.events"
|
||||||
|
local explorer_node = require "nvim-tree.explorer.node"
|
||||||
|
|
||||||
---@class LibOpenOpts
|
---@class LibOpenOpts
|
||||||
---@field path string|nil path
|
---@field path string|nil path
|
||||||
@ -86,6 +87,34 @@ function M.get_last_group_node(node)
|
|||||||
return node
|
return node
|
||||||
end
|
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
|
---@param node Node
|
||||||
---@return Node[]
|
---@return Node[]
|
||||||
function M.get_all_nodes_in_group(node)
|
function M.get_all_nodes_in_group(node)
|
||||||
@ -98,8 +127,21 @@ function M.get_all_nodes_in_group(node)
|
|||||||
return nodes
|
return nodes
|
||||||
end
|
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
|
---@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
|
if node.has_children then
|
||||||
node.has_children = false
|
node.has_children = false
|
||||||
end
|
end
|
||||||
@ -108,9 +150,20 @@ function M.expand_or_collapse(node)
|
|||||||
core.get_explorer():expand(node)
|
core.get_explorer():expand(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
local open = not M.get_last_group_node(node).open
|
local head_node = utils.get_parent_of_group(node)
|
||||||
for _, n in ipairs(M.get_all_nodes_in_group(node)) do
|
if toggle_group then
|
||||||
n.open = open
|
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
|
end
|
||||||
|
|
||||||
renderer.draw()
|
renderer.draw()
|
||||||
@ -213,6 +266,7 @@ function M.setup(opts)
|
|||||||
M.hijack_directories = opts.hijack_directories
|
M.hijack_directories = opts.hijack_directories
|
||||||
M.respect_buf_cwd = opts.respect_buf_cwd
|
M.respect_buf_cwd = opts.respect_buf_cwd
|
||||||
M.select_prompts = opts.select_prompts
|
M.select_prompts = opts.select_prompts
|
||||||
|
M.group_empty = opts.renderer.group_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user