* feat(icon_placement): Allow right_align icon_placemente for decorator using ext_marks nvim api * feat(icon_placement): Allow right_align icon_placemente for decorator using ext_marks nvim api feat(icon_placement): Allow right_align icon_placemente for decorator using ext_marks nvim api * feat(icon_placement): consolidate doc * fix: extra namespace added to avoid colision between right_align and full_name features * feat(hidden_display): Allow fine grained rendering of hidden files in a folder * feat(hidden_display): update defaults in Builder to allow rendering * feat(hidden_display): Rename opts function name for the feature * feat(#2349): add "right_align" option for renderer.icons.*_placement (#2846) * feat(icon_placement): Allow right_align icon_placemente for decorator using ext_marks nvim api * feat(icon_placement): Allow right_align icon_placemente for decorator using ext_marks nvim api feat(icon_placement): Allow right_align icon_placemente for decorator using ext_marks nvim api * feat(icon_placement): consolidate doc * fix: extra namespace added to avoid colision between right_align and full_name features * style: rename namespace_id --------- Co-authored-by: Alexander Courtis <alex@courtis.org> * docs: update docs * feat(hidden_display): Simplification and better performance by not sorting and grouping virtual lines * Update doc/nvim-tree-lua.txt Co-authored-by: Alexander Courtis <alex@courtis.org> * style: hidden_stats is better * docs: change to hidden_stats * add separate namespace for virtual lines * help: add highlight group --------- Co-authored-by: Alexander Courtis <alex@courtis.org>
This commit is contained in:
parent
48d0e82f94
commit
e25eb7fa83
@ -423,6 +423,7 @@ Following is the default configuration. See |nvim-tree-opts| for details.
|
|||||||
root_folder_label = ":~:s?$?/..?",
|
root_folder_label = ":~:s?$?/..?",
|
||||||
indent_width = 2,
|
indent_width = 2,
|
||||||
special_files = { "Cargo.toml", "Makefile", "README.md", "readme.md" },
|
special_files = { "Cargo.toml", "Makefile", "README.md", "readme.md" },
|
||||||
|
hidden_display = "none",
|
||||||
symlink_destination = true,
|
symlink_destination = true,
|
||||||
highlight_git = "none",
|
highlight_git = "none",
|
||||||
highlight_diagnostics = "none",
|
highlight_diagnostics = "none",
|
||||||
@ -878,6 +879,49 @@ Number of spaces for an each tree nesting level. Minimum 1.
|
|||||||
A list of filenames that gets highlighted with `NvimTreeSpecialFile`.
|
A list of filenames that gets highlighted with `NvimTreeSpecialFile`.
|
||||||
Type: `table`, Default: `{ "Cargo.toml", "Makefile", "README.md", "readme.md", }`
|
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*
|
*nvim-tree.renderer.symlink_destination*
|
||||||
Whether to show the destination of the symlink.
|
Whether to show the destination of the symlink.
|
||||||
Type: `boolean`, Default: `true`
|
Type: `boolean`, Default: `true`
|
||||||
@ -2461,6 +2505,9 @@ Hidden: >
|
|||||||
NvimTreeModifiedFileHL NvimTreeHiddenIcon
|
NvimTreeModifiedFileHL NvimTreeHiddenIcon
|
||||||
NvimTreeModifiedFolderHL NvimTreeHiddenFileHL
|
NvimTreeModifiedFolderHL NvimTreeHiddenFileHL
|
||||||
<
|
<
|
||||||
|
Hidden Display: >
|
||||||
|
NvimTreeHiddenDisplay Conceal
|
||||||
|
<
|
||||||
Opened: >
|
Opened: >
|
||||||
NvimTreeOpenedHL Special
|
NvimTreeOpenedHL Special
|
||||||
<
|
<
|
||||||
@ -2872,6 +2919,7 @@ highlight group is not, hard linking as follows: >
|
|||||||
|nvim-tree.renderer.add_trailing|
|
|nvim-tree.renderer.add_trailing|
|
||||||
|nvim-tree.renderer.full_name|
|
|nvim-tree.renderer.full_name|
|
||||||
|nvim-tree.renderer.group_empty|
|
|nvim-tree.renderer.group_empty|
|
||||||
|
|nvim-tree.renderer.hidden_display|
|
||||||
|nvim-tree.renderer.highlight_bookmarks|
|
|nvim-tree.renderer.highlight_bookmarks|
|
||||||
|nvim-tree.renderer.highlight_clipboard|
|
|nvim-tree.renderer.highlight_clipboard|
|
||||||
|nvim-tree.renderer.highlight_diagnostics|
|
|nvim-tree.renderer.highlight_diagnostics|
|
||||||
|
|||||||
@ -398,6 +398,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
|
|||||||
root_folder_label = ":~:s?$?/..?",
|
root_folder_label = ":~:s?$?/..?",
|
||||||
indent_width = 2,
|
indent_width = 2,
|
||||||
special_files = { "Cargo.toml", "Makefile", "README.md", "readme.md" },
|
special_files = { "Cargo.toml", "Makefile", "README.md", "readme.md" },
|
||||||
|
hidden_display = "none",
|
||||||
symlink_destination = true,
|
symlink_destination = true,
|
||||||
highlight_git = "none",
|
highlight_git = "none",
|
||||||
highlight_diagnostics = "none",
|
highlight_diagnostics = "none",
|
||||||
@ -647,6 +648,7 @@ local ACCEPTED_TYPES = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
renderer = {
|
renderer = {
|
||||||
|
hidden_display = { "function", "string" },
|
||||||
group_empty = { "boolean", "function" },
|
group_empty = { "boolean", "function" },
|
||||||
root_folder_label = { "function", "string", "boolean" },
|
root_folder_label = { "function", "string", "boolean" },
|
||||||
},
|
},
|
||||||
@ -680,6 +682,7 @@ local ACCEPTED_STRINGS = {
|
|||||||
signcolumn = { "yes", "no", "auto" },
|
signcolumn = { "yes", "no", "auto" },
|
||||||
},
|
},
|
||||||
renderer = {
|
renderer = {
|
||||||
|
hidden_display = { "none", "simple", "all" },
|
||||||
highlight_git = { "none", "icon", "name", "all" },
|
highlight_git = { "none", "icon", "name", "all" },
|
||||||
highlight_opened_files = { "none", "icon", "name", "all" },
|
highlight_opened_files = { "none", "icon", "name", "all" },
|
||||||
highlight_modified = { "none", "icon", "name", "all" },
|
highlight_modified = { "none", "icon", "name", "all" },
|
||||||
|
|||||||
@ -14,6 +14,7 @@ M.HIGHLIGHT_GROUPS = {
|
|||||||
-- Standard
|
-- Standard
|
||||||
{ group = "NvimTreeNormal", link = "Normal" },
|
{ group = "NvimTreeNormal", link = "Normal" },
|
||||||
{ group = "NvimTreeNormalFloat", link = "NormalFloat" },
|
{ group = "NvimTreeNormalFloat", link = "NormalFloat" },
|
||||||
|
{ group = "NvimTreeNormalFloatBorder", link = "FloatBorder" },
|
||||||
{ group = "NvimTreeNormalNC", link = "NvimTreeNormal" },
|
{ group = "NvimTreeNormalNC", link = "NvimTreeNormal" },
|
||||||
|
|
||||||
{ group = "NvimTreeLineNr", link = "LineNr" },
|
{ group = "NvimTreeLineNr", link = "LineNr" },
|
||||||
@ -81,6 +82,9 @@ M.HIGHLIGHT_GROUPS = {
|
|||||||
{ group = "NvimTreeHiddenFileHL", link = "NvimTreeHiddenIcon" },
|
{ group = "NvimTreeHiddenFileHL", link = "NvimTreeHiddenIcon" },
|
||||||
{ group = "NvimTreeHiddenFolderHL", link = "NvimTreeHiddenFileHL" },
|
{ group = "NvimTreeHiddenFolderHL", link = "NvimTreeHiddenFileHL" },
|
||||||
|
|
||||||
|
-- Hidden Display
|
||||||
|
{ group = "NvimTreeHiddenDisplay", link = "Conceal" },
|
||||||
|
|
||||||
-- Opened
|
-- Opened
|
||||||
{ group = "NvimTreeOpenedHL", link = "Special" },
|
{ group = "NvimTreeOpenedHL", link = "Special" },
|
||||||
|
|
||||||
|
|||||||
@ -19,4 +19,15 @@ M.ICON_PLACEMENT = {
|
|||||||
right_align = 4,
|
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
|
return M
|
||||||
|
|||||||
@ -5,6 +5,7 @@ local git = require "nvim-tree.git"
|
|||||||
local live_filter = require "nvim-tree.live-filter"
|
local live_filter = require "nvim-tree.live-filter"
|
||||||
local log = require "nvim-tree.log"
|
local log = require "nvim-tree.log"
|
||||||
|
|
||||||
|
local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON
|
||||||
local Watcher = require "nvim-tree.watcher"
|
local Watcher = require "nvim-tree.watcher"
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
@ -17,7 +18,17 @@ local M = {}
|
|||||||
local function populate_children(handle, cwd, node, git_status, parent)
|
local function populate_children(handle, cwd, node, git_status, parent)
|
||||||
local node_ignored = explorer_node.is_git_ignored(node)
|
local node_ignored = explorer_node.is_git_ignored(node)
|
||||||
local nodes_by_path = utils.bool_record(node.nodes, "absolute_path")
|
local nodes_by_path = utils.bool_record(node.nodes, "absolute_path")
|
||||||
|
|
||||||
local filter_status = parent.filters:prepare(git_status)
|
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
|
while true do
|
||||||
local name, t = vim.loop.fs_scandir_next(handle)
|
local name, t = vim.loop.fs_scandir_next(handle)
|
||||||
if not name then
|
if not name then
|
||||||
@ -29,8 +40,8 @@ local function populate_children(handle, cwd, node, git_status, parent)
|
|||||||
|
|
||||||
---@type uv.fs_stat.result|nil
|
---@type uv.fs_stat.result|nil
|
||||||
local stat = vim.loop.fs_stat(abs)
|
local stat = vim.loop.fs_stat(abs)
|
||||||
|
local filter_reason = parent.filters:should_filter_as_reason(abs, stat, filter_status)
|
||||||
if not parent.filters:should_filter(abs, stat, filter_status) and not nodes_by_path[abs] and Watcher.is_fs_event_capable(abs) then
|
if filter_reason == FILTER_REASON.none and not nodes_by_path[abs] and Watcher.is_fs_event_capable(abs) then
|
||||||
local child = nil
|
local child = nil
|
||||||
if t == "directory" and vim.loop.fs_access(abs, "R") then
|
if t == "directory" and vim.loop.fs_access(abs, "R") then
|
||||||
child = builders.folder(node, abs, name, stat)
|
child = builders.folder(node, abs, name, stat)
|
||||||
@ -47,6 +58,12 @@ local function populate_children(handle, cwd, node, git_status, parent)
|
|||||||
nodes_by_path[child.absolute_path] = true
|
nodes_by_path[child.absolute_path] = true
|
||||||
explorer_node.update_git_status(child, node_ignored, git_status)
|
explorer_node.update_git_status(child, node_ignored, git_status)
|
||||||
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
|
||||||
|
|
||||||
log.profile_end(profile)
|
log.profile_end(profile)
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
local utils = require "nvim-tree.utils"
|
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
|
---@class Filters to handle all opts.filters and related API
|
||||||
---@field config table hydrated user opts.filters
|
---@field config table hydrated user opts.filters
|
||||||
@ -223,4 +224,33 @@ function Filters:should_filter(path, fs_stat, status)
|
|||||||
or bookmark(self, path, fs_stat and fs_stat.type, status.bookmarks)
|
or bookmark(self, path, fs_stat and fs_stat.type, status.bookmarks)
|
||||||
end
|
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
|
return Filters
|
||||||
|
|||||||
@ -5,6 +5,7 @@ local live_filter = require "nvim-tree.live-filter"
|
|||||||
local git = require "nvim-tree.git"
|
local git = require "nvim-tree.git"
|
||||||
local log = require "nvim-tree.log"
|
local log = require "nvim-tree.log"
|
||||||
|
|
||||||
|
local FILTER_REASON = require("nvim-tree.enum").FILTER_REASON
|
||||||
local NodeIterator = require "nvim-tree.iterators.node-iterator"
|
local NodeIterator = require "nvim-tree.iterators.node-iterator"
|
||||||
local Watcher = require "nvim-tree.watcher"
|
local Watcher = require "nvim-tree.watcher"
|
||||||
|
|
||||||
@ -92,6 +93,16 @@ function M.reload(node, git_status)
|
|||||||
local node_ignored = explorer_node.is_git_ignored(node)
|
local node_ignored = explorer_node.is_git_ignored(node)
|
||||||
---@type table<string, Node>
|
---@type table<string, Node>
|
||||||
local nodes_by_path = utils.key_by(node.nodes, "absolute_path")
|
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
|
while true do
|
||||||
local name, t = vim.loop.fs_scandir_next(handle)
|
local name, t = vim.loop.fs_scandir_next(handle)
|
||||||
if not name then
|
if not name then
|
||||||
@ -102,7 +113,8 @@ function M.reload(node, git_status)
|
|||||||
---@type uv.fs_stat.result|nil
|
---@type uv.fs_stat.result|nil
|
||||||
local stat = vim.loop.fs_stat(abs)
|
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
|
remain_childs[abs] = true
|
||||||
|
|
||||||
-- Recreate node if type changes.
|
-- Recreate node if type changes.
|
||||||
@ -139,6 +151,12 @@ function M.reload(node, git_status)
|
|||||||
n.fs_stat = stat
|
n.fs_stat = stat
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -18,10 +18,17 @@ local function reset_filter(node_)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
node_.hidden_stats = vim.tbl_deep_extend("force", node_.hidden_stats or {}, {
|
||||||
|
live_filter = 0,
|
||||||
|
})
|
||||||
|
|
||||||
Iterator.builder(node_.nodes)
|
Iterator.builder(node_.nodes)
|
||||||
:hidden()
|
:hidden()
|
||||||
:applier(function(node)
|
:applier(function(node)
|
||||||
node.hidden = false
|
node.hidden = false
|
||||||
|
node.hidden_stats = vim.tbl_deep_extend("force", node.hidden_stats or {}, {
|
||||||
|
live_filter = 0,
|
||||||
|
})
|
||||||
end)
|
end)
|
||||||
:iterate()
|
:iterate()
|
||||||
end
|
end
|
||||||
@ -79,6 +86,10 @@ function M.apply_filter(node_)
|
|||||||
local filtered_nodes = 0
|
local filtered_nodes = 0
|
||||||
local nodes = node.group_next and { node.group_next } or node.nodes
|
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
|
if nodes then
|
||||||
for _, n in pairs(nodes) do
|
for _, n in pairs(nodes) do
|
||||||
iterate(n)
|
iterate(n)
|
||||||
@ -88,6 +99,8 @@ function M.apply_filter(node_)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
node.hidden_stats.live_filter = filtered_nodes
|
||||||
|
|
||||||
local has_nodes = nodes and (M.always_show_folders or #nodes > filtered_nodes)
|
local has_nodes = nodes and (M.always_show_folders or #nodes > filtered_nodes)
|
||||||
local ok, is_match = pcall(matches, node)
|
local ok, is_match = pcall(matches, node)
|
||||||
node.hidden = not (has_nodes or (ok and is_match))
|
node.hidden = not (has_nodes or (ok and is_match))
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
---@field group_next Node|nil
|
---@field group_next Node|nil
|
||||||
---@field nodes Node[]
|
---@field nodes Node[]
|
||||||
---@field open boolean
|
---@field open boolean
|
||||||
|
---@field hidden_stats table -- Each field of this table is a key for source and value for count
|
||||||
|
|
||||||
---@class FileNode: BaseNode
|
---@class FileNode: BaseNode
|
||||||
---@field extension string
|
---@field extension string
|
||||||
|
|||||||
@ -43,6 +43,8 @@ local M = {
|
|||||||
---@field lines string[] includes icons etc.
|
---@field lines string[] includes icons etc.
|
||||||
---@field hl_args AddHighlightArgs[] line highlights
|
---@field hl_args AddHighlightArgs[] line highlights
|
||||||
---@field signs string[] line signs
|
---@field signs string[] line signs
|
||||||
|
---@field extmarks table[] extra marks for right icon placement
|
||||||
|
---@field virtual_lines table[] virtual lines for hidden count display
|
||||||
---@field private root_cwd string absolute path
|
---@field private root_cwd string absolute path
|
||||||
---@field private index number
|
---@field private index number
|
||||||
---@field private depth number
|
---@field private depth number
|
||||||
@ -62,6 +64,7 @@ function Builder:new()
|
|||||||
markers = {},
|
markers = {},
|
||||||
signs = {},
|
signs = {},
|
||||||
extmarks = {},
|
extmarks = {},
|
||||||
|
virtual_lines = {},
|
||||||
}
|
}
|
||||||
setmetatable(o, self)
|
setmetatable(o, self)
|
||||||
self.__index = self
|
self.__index = self
|
||||||
@ -351,7 +354,6 @@ function Builder:build_line(node, idx, num_children)
|
|||||||
self.index = self.index + 1
|
self.index = self.index + 1
|
||||||
|
|
||||||
node = require("nvim-tree.lib").get_last_group_node(node)
|
node = require("nvim-tree.lib").get_last_group_node(node)
|
||||||
|
|
||||||
if node.open then
|
if node.open then
|
||||||
self.depth = self.depth + 1
|
self.depth = self.depth + 1
|
||||||
self:build_lines(node)
|
self:build_lines(node)
|
||||||
@ -359,6 +361,32 @@ function Builder:build_line(node, idx, num_children)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Add virtual lines for rendering hidden count information per node
|
||||||
|
---@private
|
||||||
|
function Builder:add_hidden_count_string(node, idx, num_children)
|
||||||
|
if not node.open then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local hidden_count_string = M.opts.renderer.hidden_display(node.hidden_stats)
|
||||||
|
if hidden_count_string and hidden_count_string ~= "" then
|
||||||
|
local indent_markers = pad.get_indent_markers(self.depth, idx or 0, num_children or 0, node, self.markers, 1)
|
||||||
|
local indent_width = M.opts.renderer.indent_width
|
||||||
|
|
||||||
|
local indent_padding = string.rep(" ", indent_width)
|
||||||
|
local indent_string = indent_padding .. indent_markers.str
|
||||||
|
local line_nr = #self.lines - 1
|
||||||
|
self.virtual_lines[line_nr] = self.virtual_lines[line_nr] or {}
|
||||||
|
|
||||||
|
-- NOTE: We are inserting in depth order because of current traversal
|
||||||
|
-- if we change the traversal, we might need to sort by depth before rendering `self.virtual_lines`
|
||||||
|
-- to maintain proper ordering of parent and child folder hidden count info.
|
||||||
|
table.insert(self.virtual_lines[line_nr], {
|
||||||
|
{ indent_string, indent_markers.hl },
|
||||||
|
{ string.rep(indent_padding, (node.parent == nil and 0 or 1)) .. hidden_count_string, "NvimTreeHiddenDisplay" },
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
function Builder:get_nodes_number(nodes)
|
function Builder:get_nodes_number(nodes)
|
||||||
if not live_filter.filter then
|
if not live_filter.filter then
|
||||||
@ -388,6 +416,7 @@ function Builder:build_lines(node)
|
|||||||
idx = idx + 1
|
idx = idx + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
self:add_hidden_count_string(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
@ -442,7 +471,50 @@ function Builder:build()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param opts table
|
||||||
|
local setup_hidden_display_function = function(opts)
|
||||||
|
local hidden_display = opts.renderer.hidden_display
|
||||||
|
-- options are already validated, so ´hidden_display´ can ONLY be `string` or `function` if type(hidden_display) == "string" then
|
||||||
|
if type(hidden_display) == "string" then
|
||||||
|
if hidden_display == "none" then
|
||||||
|
opts.renderer.hidden_display = function()
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
elseif hidden_display == "simple" then
|
||||||
|
opts.renderer.hidden_display = function(hidden_stats)
|
||||||
|
return utils.default_format_hidden_count(hidden_stats, true)
|
||||||
|
end
|
||||||
|
elseif hidden_display == "all" then
|
||||||
|
opts.renderer.hidden_display = function(hidden_stats)
|
||||||
|
return utils.default_format_hidden_count(hidden_stats, false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif type(hidden_display) == "function" then
|
||||||
|
local safe_render = function(hidden_stats)
|
||||||
|
-- In case of missing field such as live_filter we zero it, otherwise keep field as is
|
||||||
|
hidden_stats = vim.tbl_deep_extend("force", {
|
||||||
|
live_filter = 0,
|
||||||
|
git = 0,
|
||||||
|
buf = 0,
|
||||||
|
dotfile = 0,
|
||||||
|
custom = 0,
|
||||||
|
bookmark = 0,
|
||||||
|
}, hidden_stats or {})
|
||||||
|
|
||||||
|
local ok, result = pcall(hidden_display, hidden_stats)
|
||||||
|
if not ok then
|
||||||
|
notify.warn "Problem occurred in the function ``opts.renderer.hidden_display`` see nvim-tree.renderer.hidden_display on :h nvim-tree"
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
opts.renderer.hidden_display = safe_render
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function Builder.setup(opts)
|
function Builder.setup(opts)
|
||||||
|
setup_hidden_display_function(opts)
|
||||||
M.opts = opts
|
M.opts = opts
|
||||||
|
|
||||||
-- priority order
|
-- priority order
|
||||||
|
|||||||
@ -19,7 +19,7 @@ local function check_siblings_for_folder(node, with_arrows)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_padding_indent_markers(depth, idx, nodes_number, markers, with_arrows, inline_arrows, node)
|
local function get_padding_indent_markers(depth, idx, nodes_number, markers, with_arrows, inline_arrows, node, early_stop)
|
||||||
local base_padding = with_arrows and (not node.nodes or depth > 0) and " " or ""
|
local base_padding = with_arrows and (not node.nodes or depth > 0) and " " or ""
|
||||||
local padding = (inline_arrows or depth == 0) and base_padding or ""
|
local padding = (inline_arrows or depth == 0) and base_padding or ""
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ local function get_padding_indent_markers(depth, idx, nodes_number, markers, wit
|
|||||||
local has_folder_sibling = check_siblings_for_folder(node, with_arrows)
|
local has_folder_sibling = check_siblings_for_folder(node, with_arrows)
|
||||||
local indent = string.rep(" ", M.config.indent_width - 1)
|
local indent = string.rep(" ", M.config.indent_width - 1)
|
||||||
markers[depth] = idx ~= nodes_number
|
markers[depth] = idx ~= nodes_number
|
||||||
for i = 1, depth do
|
for i = 1, depth - early_stop do
|
||||||
local glyph
|
local glyph
|
||||||
if idx == nodes_number and i == depth then
|
if idx == nodes_number and i == depth then
|
||||||
local bottom_width = M.config.indent_width - 2 + (with_arrows and not inline_arrows and has_folder_sibling and 2 or 0)
|
local bottom_width = M.config.indent_width - 2 + (with_arrows and not inline_arrows and has_folder_sibling and 2 or 0)
|
||||||
@ -62,7 +62,7 @@ end
|
|||||||
---@param node table
|
---@param node table
|
||||||
---@param markers table
|
---@param markers table
|
||||||
---@return HighlightedString[]
|
---@return HighlightedString[]
|
||||||
function M.get_indent_markers(depth, idx, nodes_number, node, markers)
|
function M.get_indent_markers(depth, idx, nodes_number, node, markers, early_stop)
|
||||||
local str = ""
|
local str = ""
|
||||||
|
|
||||||
local show_arrows = M.config.icons.show.folder_arrow
|
local show_arrows = M.config.icons.show.folder_arrow
|
||||||
@ -71,7 +71,7 @@ function M.get_indent_markers(depth, idx, nodes_number, node, markers)
|
|||||||
local indent_width = M.config.indent_width
|
local indent_width = M.config.indent_width
|
||||||
|
|
||||||
if show_markers then
|
if show_markers then
|
||||||
str = str .. get_padding_indent_markers(depth, idx, nodes_number, markers, show_arrows, inline_arrows, node)
|
str = str .. get_padding_indent_markers(depth, idx, nodes_number, markers, show_arrows, inline_arrows, node, early_stop or 0)
|
||||||
else
|
else
|
||||||
str = str .. string.rep(" ", depth * indent_width)
|
str = str .. string.rep(" ", depth * indent_width)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -14,12 +14,13 @@ local SIGN_GROUP = "NvimTreeRendererSigns"
|
|||||||
|
|
||||||
local namespace_highlights_id = vim.api.nvim_create_namespace "NvimTreeHighlights"
|
local namespace_highlights_id = vim.api.nvim_create_namespace "NvimTreeHighlights"
|
||||||
local namespace_extmarks_id = vim.api.nvim_create_namespace "NvimTreeExtmarks"
|
local namespace_extmarks_id = vim.api.nvim_create_namespace "NvimTreeExtmarks"
|
||||||
|
local namespace_virtual_lines_id = vim.api.nvim_create_namespace "NvimTreeVirtualLines"
|
||||||
|
|
||||||
---@param bufnr number
|
---@param bufnr number
|
||||||
---@param lines string[]
|
---@param lines string[]
|
||||||
---@param hl_args AddHighlightArgs[]
|
---@param hl_args AddHighlightArgs[]
|
||||||
---@param signs string[]
|
---@param signs string[]
|
||||||
local function _draw(bufnr, lines, hl_args, signs, extmarks)
|
local function _draw(bufnr, lines, hl_args, signs, extmarks, virtual_lines)
|
||||||
if vim.fn.has "nvim-0.10" == 1 then
|
if vim.fn.has "nvim-0.10" == 1 then
|
||||||
vim.api.nvim_set_option_value("modifiable", true, { buf = bufnr })
|
vim.api.nvim_set_option_value("modifiable", true, { buf = bufnr })
|
||||||
else
|
else
|
||||||
@ -50,6 +51,15 @@ local function _draw(bufnr, lines, hl_args, signs, extmarks)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_buf_clear_namespace(bufnr, namespace_virtual_lines_id, 0, -1)
|
||||||
|
for line_nr, vlines in pairs(virtual_lines) do
|
||||||
|
vim.api.nvim_buf_set_extmark(bufnr, namespace_virtual_lines_id, line_nr, 0, {
|
||||||
|
virt_lines = vlines,
|
||||||
|
virt_lines_above = false,
|
||||||
|
virt_lines_leftcol = true,
|
||||||
|
})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.render_hl(bufnr, hl)
|
function M.render_hl(bufnr, hl)
|
||||||
@ -79,7 +89,7 @@ function M.draw()
|
|||||||
|
|
||||||
local builder = Builder:new():build()
|
local builder = Builder:new():build()
|
||||||
|
|
||||||
_draw(bufnr, builder.lines, builder.hl_args, builder.signs, builder.extmarks)
|
_draw(bufnr, builder.lines, builder.hl_args, builder.signs, builder.extmarks, builder.virtual_lines)
|
||||||
|
|
||||||
if cursor and #builder.lines >= cursor[1] then
|
if cursor and #builder.lines >= cursor[1] then
|
||||||
vim.api.nvim_win_set_cursor(view.get_winnr() or 0, cursor)
|
vim.api.nvim_win_set_cursor(view.get_winnr() or 0, cursor)
|
||||||
|
|||||||
@ -181,6 +181,26 @@ function M.get_parent_of_group(node)
|
|||||||
return node
|
return node
|
||||||
end
|
end
|
||||||
|
|
||||||
|
M.default_format_hidden_count = function(hidden_count, simple)
|
||||||
|
local parts = {}
|
||||||
|
local total_count = 0
|
||||||
|
for reason, count in pairs(hidden_count) do
|
||||||
|
total_count = total_count + count
|
||||||
|
if count > 0 then
|
||||||
|
table.insert(parts, reason .. ": " .. tostring(count))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local hidden_count_string = table.concat(parts, ", ") -- if empty then is "" (empty string)
|
||||||
|
if simple then
|
||||||
|
hidden_count_string = ""
|
||||||
|
end
|
||||||
|
if total_count > 0 then
|
||||||
|
return "(" .. tostring(total_count) .. (simple and " hidden" or " total ") .. hidden_count_string .. ")"
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Return visible nodes indexed by line
|
--- Return visible nodes indexed by line
|
||||||
---@param nodes_all Node[]
|
---@param nodes_all Node[]
|
||||||
---@param line_start number
|
---@param line_start number
|
||||||
|
|||||||
@ -50,6 +50,7 @@ M.View = {
|
|||||||
"Normal:NvimTreeNormal",
|
"Normal:NvimTreeNormal",
|
||||||
"NormalNC:NvimTreeNormalNC",
|
"NormalNC:NvimTreeNormalNC",
|
||||||
"NormalFloat:NvimTreeNormalFloat",
|
"NormalFloat:NvimTreeNormalFloat",
|
||||||
|
"FloatBorder:NvimTreeNormalFloatBorder",
|
||||||
}, ","),
|
}, ","),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user