Skip to content

feat(#2225): add renderer.hidden_display to show a summary of hidden files below the tree #2856

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 18 commits into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
d27bcb8
feat(icon_placement): Allow right_align icon_placemente for decorator…
evertonse Jul 14, 2024
6d336de
feat(icon_placement): Allow right_align icon_placemente for decorator…
evertonse Jul 14, 2024
6b7b4f2
feat(icon_placement): consolidate doc
alex-courtis Jul 21, 2024
a8873b8
Merge remote-tracking branch 'nvim-tree/master' into feat/icon_placem…
evertonse Jul 21, 2024
cb56c0d
fix: extra namespace added to avoid colision between right_align and …
evertonse Jul 22, 2024
c41c752
feat(hidden_display): Allow fine grained rendering of hidden files in
evertonse Jul 22, 2024
9053a6d
feat(hidden_display): update defaults in Builder to allow rendering
evertonse Jul 24, 2024
31ba53a
Merge with nvim-tree/master
evertonse Jul 28, 2024
6bbc2ec
feat(hidden_display): Rename opts function name for the feature
evertonse Jul 28, 2024
7021848
feat(#2349): add "right_align" option for renderer.icons.*_placement …
evertonse Jul 28, 2024
d53ca8e
Merge remote-tracking branch 'nvim-tree/master' into feat/hidden_display
evertonse Jul 28, 2024
8ef7e48
docs: update docs
evertonse Jul 28, 2024
36954ff
feat(hidden_display): Simplification and better performance by not so…
evertonse Jul 28, 2024
8ef8f06
Update doc/nvim-tree-lua.txt
evertonse Aug 5, 2024
6dbbf9d
style: hidden_stats is better
evertonse Aug 5, 2024
a005a7f
docs: change to hidden_stats
evertonse Aug 5, 2024
70159e2
add separate namespace for virtual lines
evertonse Aug 7, 2024
9c4ed7b
help: add highlight group
alex-courtis Aug 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions doc/nvim-tree-lua.txt
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ Following is the default configuration. See |nvim-tree-opts| for details.
root_folder_label = ":~:s?$?/..?",
indent_width = 2,
special_files = { "Cargo.toml", "Makefile", "README.md", "readme.md" },
hidden_display = "none",
symlink_destination = true,
highlight_git = "none",
highlight_diagnostics = "none",
Expand Down Expand Up @@ -878,6 +879,49 @@ Number of spaces for an each tree nesting level. Minimum 1.
A list of filenames that gets highlighted with `NvimTreeSpecialFile`.
Type: `table`, Default: `{ "Cargo.toml", "Makefile", "README.md", "readme.md", }`

*nvim-tree.renderer.hidden_display*
Show a summary of hidden files below the tree using `NvimTreeHiddenDisplay
Type: `function | string`, Default: `"none"`

Possible string values are:
- `"none"`: Doesn't inform anything about hidden files.
- `"simple"`: Shows how many hidden files are in a folder.
- `"all"`: Shows how many files are hidden and the number of hidden
files per reason why they're hidden.

Example `"all"`:
If a folder has 14 hidden items for various reasons, the display might
show: >
(14 total git: 5, dotfile: 9)
<
If a function is provided, it receives a table `hidden_stats` where keys are
reasons and values are the count of hidden files for that reason.

The `hidden_stats` argument is structured as follows, where <num> is the
number of hidden files related to the field: >
hidden_stats = {
bookmark = <num>,
buf = <num>,
custom = <num>,
dotfile = <num>,
git = <num>,
live_filter = <num>,
}
<
Example of function that can be passed: >
function(hidden_stats)
local total_count = 0
for reason, count in pairs(hidden_stats) do
total_count = total_count + count
end

if total_count > 0 then
return "(" .. tostring(total_count) .. " hidden)"
end
return nil
end
<

*nvim-tree.renderer.symlink_destination*
Whether to show the destination of the symlink.
Type: `boolean`, Default: `true`
Expand Down Expand Up @@ -2461,6 +2505,9 @@ Hidden: >
NvimTreeModifiedFileHL NvimTreeHiddenIcon
NvimTreeModifiedFolderHL NvimTreeHiddenFileHL
<
Hidden Display: >
NvimTreeHiddenDisplay Conceal
<
Opened: >
NvimTreeOpenedHL Special
<
Expand Down Expand Up @@ -2872,6 +2919,7 @@ highlight group is not, hard linking as follows: >
|nvim-tree.renderer.add_trailing|
|nvim-tree.renderer.full_name|
|nvim-tree.renderer.group_empty|
|nvim-tree.renderer.hidden_display|
|nvim-tree.renderer.highlight_bookmarks|
|nvim-tree.renderer.highlight_clipboard|
|nvim-tree.renderer.highlight_diagnostics|
Expand Down
3 changes: 3 additions & 0 deletions lua/nvim-tree.lua
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
root_folder_label = ":~:s?$?/..?",
indent_width = 2,
special_files = { "Cargo.toml", "Makefile", "README.md", "readme.md" },
hidden_display = "none",
symlink_destination = true,
highlight_git = "none",
highlight_diagnostics = "none",
Expand Down Expand Up @@ -647,6 +648,7 @@ local ACCEPTED_TYPES = {
},
},
renderer = {
hidden_display = { "function", "string" },
group_empty = { "boolean", "function" },
root_folder_label = { "function", "string", "boolean" },
},
Expand Down Expand Up @@ -680,6 +682,7 @@ local ACCEPTED_STRINGS = {
signcolumn = { "yes", "no", "auto" },
},
renderer = {
hidden_display = { "none", "simple", "all" },
highlight_git = { "none", "icon", "name", "all" },
highlight_opened_files = { "none", "icon", "name", "all" },
highlight_modified = { "none", "icon", "name", "all" },
Expand Down
4 changes: 4 additions & 0 deletions lua/nvim-tree/appearance/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ M.HIGHLIGHT_GROUPS = {
-- Standard
{ group = "NvimTreeNormal", link = "Normal" },
{ group = "NvimTreeNormalFloat", link = "NormalFloat" },
{ group = "NvimTreeNormalFloatBorder", link = "FloatBorder" },
{ group = "NvimTreeNormalNC", link = "NvimTreeNormal" },

{ group = "NvimTreeLineNr", link = "LineNr" },
Expand Down Expand Up @@ -81,6 +82,9 @@ M.HIGHLIGHT_GROUPS = {
{ group = "NvimTreeHiddenFileHL", link = "NvimTreeHiddenIcon" },
{ group = "NvimTreeHiddenFolderHL", link = "NvimTreeHiddenFileHL" },

-- Hidden Display
{ group = "NvimTreeHiddenDisplay", link = "Conceal" },

-- Opened
{ group = "NvimTreeOpenedHL", link = "Special" },

Expand Down
11 changes: 11 additions & 0 deletions lua/nvim-tree/enum.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,15 @@ M.ICON_PLACEMENT = {
right_align = 4,
}

---Reason for filter in filter.lua
---@enum FILTER_REASON
M.FILTER_REASON = {
none = 0, -- It's not filtered
git = 1,
buf = 2,
dotfile = 4,
custom = 8,
bookmark = 16,
}

return M
21 changes: 19 additions & 2 deletions lua/nvim-tree/explorer/explore.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ local git = require "nvim-tree.git"
local live_filter = require "nvim-tree.live-filter"
local log = require "nvim-tree.log"

local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON
local Watcher = require "nvim-tree.watcher"

local M = {}
Expand All @@ -17,7 +18,17 @@ local M = {}
local function populate_children(handle, cwd, node, git_status, parent)
local node_ignored = explorer_node.is_git_ignored(node)
local nodes_by_path = utils.bool_record(node.nodes, "absolute_path")

local filter_status = parent.filters:prepare(git_status)

node.hidden_stats = vim.tbl_deep_extend("force", node.hidden_stats or {}, {
git = 0,
buf = 0,
dotfile = 0,
custom = 0,
bookmark = 0,
})

while true do
local name, t = vim.loop.fs_scandir_next(handle)
if not name then
Expand All @@ -29,8 +40,8 @@ local function populate_children(handle, cwd, node, git_status, parent)

---@type uv.fs_stat.result|nil
local stat = vim.loop.fs_stat(abs)

if not parent.filters:should_filter(abs, stat, filter_status) and not nodes_by_path[abs] and Watcher.is_fs_event_capable(abs) then
local filter_reason = parent.filters:should_filter_as_reason(abs, stat, filter_status)
if filter_reason == FILTER_REASON.none and not nodes_by_path[abs] and Watcher.is_fs_event_capable(abs) then
local child = nil
if t == "directory" and vim.loop.fs_access(abs, "R") then
child = builders.folder(node, abs, name, stat)
Expand All @@ -47,6 +58,12 @@ local function populate_children(handle, cwd, node, git_status, parent)
nodes_by_path[child.absolute_path] = true
explorer_node.update_git_status(child, node_ignored, git_status)
end
else
for reason, value in pairs(FILTER_REASON) do
if filter_reason == value then
node.hidden_stats[reason] = node.hidden_stats[reason] + 1
end
end
end

log.profile_end(profile)
Expand Down
30 changes: 30 additions & 0 deletions lua/nvim-tree/explorer/filters.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local utils = require "nvim-tree.utils"
local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON

---@class Filters to handle all opts.filters and related API
---@field config table hydrated user opts.filters
Expand Down Expand Up @@ -223,4 +224,33 @@ function Filters:should_filter(path, fs_stat, status)
or bookmark(self, path, fs_stat and fs_stat.type, status.bookmarks)
end

--- Check if the given path should be filtered, and provide the reason why it was
---@param path string Absolute path
---@param fs_stat uv.fs_stat.result|nil fs_stat of file
---@param status table from prepare
---@return FILTER_REASON
function Filters:should_filter_as_reason(path, fs_stat, status)
if not self.config.enable then
return FILTER_REASON.none
end

if is_excluded(self, path) then
return FILTER_REASON.none
end

if git(self, path, status.git_status) then
return FILTER_REASON.git
elseif buf(self, path, status.bufinfo) then
return FILTER_REASON.buf
elseif dotfile(self, path) then
return FILTER_REASON.dotfile
elseif custom(self, path) then
return FILTER_REASON.custom
elseif bookmark(self, path, fs_stat and fs_stat.type, status.bookmarks) then
return FILTER_REASON.bookmark
else
return FILTER_REASON.none
end
end

return Filters
20 changes: 19 additions & 1 deletion lua/nvim-tree/explorer/reload.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ local live_filter = require "nvim-tree.live-filter"
local git = require "nvim-tree.git"
local log = require "nvim-tree.log"

local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON
local NodeIterator = require "nvim-tree.iterators.node-iterator"
local Watcher = require "nvim-tree.watcher"

Expand Down Expand Up @@ -92,6 +93,16 @@ function M.reload(node, git_status)
local node_ignored = explorer_node.is_git_ignored(node)
---@type table<string, Node>
local nodes_by_path = utils.key_by(node.nodes, "absolute_path")

-- To reset we must 'zero' everything that we use
node.hidden_stats = vim.tbl_deep_extend("force", node.hidden_stats or {}, {
git = 0,
buf = 0,
dotfile = 0,
custom = 0,
bookmark = 0,
})

while true do
local name, t = vim.loop.fs_scandir_next(handle)
if not name then
Expand All @@ -102,7 +113,8 @@ function M.reload(node, git_status)
---@type uv.fs_stat.result|nil
local stat = vim.loop.fs_stat(abs)

if not explorer.filters:should_filter(abs, stat, filter_status) then
local filter_reason = explorer.filters:should_filter_as_reason(abs, stat, filter_status)
if filter_reason == FILTER_REASON.none then
remain_childs[abs] = true

-- Recreate node if type changes.
Expand Down Expand Up @@ -139,6 +151,12 @@ function M.reload(node, git_status)
n.fs_stat = stat
end
end
else
for reason, value in pairs(FILTER_REASON) do
if filter_reason == value then
node.hidden_stats[reason] = node.hidden_stats[reason] + 1
end
end
end
end

Expand Down
13 changes: 13 additions & 0 deletions lua/nvim-tree/live-filter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,17 @@ local function reset_filter(node_)
return
end

node_.hidden_stats = vim.tbl_deep_extend("force", node_.hidden_stats or {}, {
live_filter = 0,
})

Iterator.builder(node_.nodes)
:hidden()
:applier(function(node)
node.hidden = false
node.hidden_stats = vim.tbl_deep_extend("force", node.hidden_stats or {}, {
live_filter = 0,
})
end)
:iterate()
end
Expand Down Expand Up @@ -79,6 +86,10 @@ function M.apply_filter(node_)
local filtered_nodes = 0
local nodes = node.group_next and { node.group_next } or node.nodes

node.hidden_stats = vim.tbl_deep_extend("force", node.hidden_stats or {}, {
live_filter = 0,
})

if nodes then
for _, n in pairs(nodes) do
iterate(n)
Expand All @@ -88,6 +99,8 @@ function M.apply_filter(node_)
end
end

node.hidden_stats.live_filter = filtered_nodes

local has_nodes = nodes and (M.always_show_folders or #nodes > filtered_nodes)
local ok, is_match = pcall(matches, node)
node.hidden = not (has_nodes or (ok and is_match))
Expand Down
1 change: 1 addition & 0 deletions lua/nvim-tree/node.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
---@field group_next Node|nil
---@field nodes Node[]
---@field open boolean
---@field hidden_stats table -- Each field of this table is a key for source and value for count

---@class FileNode: BaseNode
---@field extension string
Expand Down
Loading
Loading