Skip to content

Commit c5dc80c

Browse files
authored
feat(view): add filters.git_clean, filters.no_buffer (#1784)
* feat(view): add filters.git_clean * feat(view): add filters.git_clean * feat(view): add filters.no_buffer * feat(view): filters.no_buffer misses unloaded, handles buffer in/out * feat(view): filters.no_buffer matches directories specifically * feat(view): filters.no_buffer clarify targets * feat: add placeholder filters.diagnostics_ok, refactor filters * feat(view): remove placeholder filters.diagnostics_ok
1 parent e49fa4e commit c5dc80c

File tree

12 files changed

+213
-76
lines changed

12 files changed

+213
-76
lines changed

doc/nvim-tree-lua.txt

+68-47
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ Subsequent calls to setup will replace the previous configuration.
296296
debounce_delay = 50,
297297
severity = {
298298
min = vim.diagnostic.severity.HINT,
299-
max = vim.diagnostic.severity.ERROR
299+
max = vim.diagnostic.severity.ERROR,
300300
},
301301
icons = {
302302
hint = "",
@@ -307,6 +307,8 @@ Subsequent calls to setup will replace the previous configuration.
307307
},
308308
filters = {
309309
dotfiles = false,
310+
git_clean = false,
311+
no_buffer = false,
310312
custom = {},
311313
exclude = {},
312314
},
@@ -903,6 +905,19 @@ Filtering options.
903905
Toggle via the `toggle_dotfiles` action, default mapping `H`.
904906
Type: `boolean`, Default: `false`
905907

908+
*nvim-tree.filters.git_clean*
909+
Do not show files with no git status. This will show ignored files when
910+
|nvim-tree.git.ignore| is set, as they are effectively dirty.
911+
Toggle via the `toggle_git_clean` action, default mapping `C`.
912+
Type: `boolean`, Default: `false`
913+
914+
*nvim-tree.filters.no_buffer*
915+
Do not show files that have no listed buffer.
916+
Toggle via the `toggle_no_buffer` action, default mapping `B`.
917+
For performance reasons this may not immediately update on buffer
918+
delete/wipe. A reload or filesystem event will result in an update.
919+
Type: `boolean`, Default: `false`
920+
906921
*nvim-tree.filters.custom*
907922
Custom list of vim regex for file/directory names that will not be shown.
908923
Backslashes must be escaped e.g. "^\\.git". See |string-match|.
@@ -1188,6 +1203,8 @@ exists.
11881203
- collapse_all `(keep_buffers?: bool)`
11891204
- expand_all
11901205
- toggle_gitignore_filter
1206+
- toggle_git_clean_filter
1207+
- toggle_no_buffer_filter
11911208
- toggle_custom_filter
11921209
- toggle_hidden_filter
11931210
- toggle_help
@@ -1302,55 +1319,57 @@ Single right / middle mouse mappings will requre changes to |mousemodel| or |mou
13021319

13031320
DEFAULT MAPPINGS *nvim-tree-default-mappings*
13041321

1305-
`<CR>` edit open a file or folder; root will cd to the above directory
1322+
`<CR>` edit open a file or folder; root will cd to the above directory
13061323
`o`
13071324
`<2-LeftMouse>`
1308-
`<C-e>` edit_in_place edit the file in place, effectively replacing the tree explorer
1309-
`O` edit_no_picker same as (edit) with no window picker
1310-
`<C-]>` cd cd in the directory under the cursor
1325+
`<C-e>` edit_in_place edit the file in place, effectively replacing the tree explorer
1326+
`O` edit_no_picker same as (edit) with no window picker
1327+
`<C-]>` cd cd in the directory under the cursor
13111328
`<2-RightMouse>`
1312-
`<C-v>` vsplit open the file in a vertical split
1313-
`<C-x>` split open the file in a horizontal split
1314-
`<C-t>` tabnew open the file in a new tab
1315-
`<` prev_sibling navigate to the previous sibling of current file/directory
1316-
`>` next_sibling navigate to the next sibling of current file/directory
1317-
`P` parent_node move cursor to the parent directory
1318-
`<BS>` close_node close current opened directory or parent
1319-
`<Tab>` preview open the file as a preview (keeps the cursor in the tree)
1320-
`K` first_sibling navigate to the first sibling of current file/directory
1321-
`J` last_sibling navigate to the last sibling of current file/directory
1322-
`I` toggle_git_ignored toggle visibility of files/folders hidden via |git.ignore| option
1323-
`H` toggle_dotfiles toggle visibility of dotfiles via |filters.dotfiles| option
1324-
`U` toggle_custom toggle visibility of files/folders hidden via |filters.custom| option
1325-
`R` refresh refresh the tree
1326-
`a` create add a file; leaving a trailing `/` will add a directory
1327-
`d` remove delete a file (will prompt for confirmation)
1328-
`D` trash trash a file via |trash| option
1329-
`r` rename rename a file
1330-
`<C-r>` full_rename rename a file and omit the filename on input
1331-
`x` cut add/remove file/directory to cut clipboard
1332-
`c` copy add/remove file/directory to copy clipboard
1333-
`p` paste paste from clipboard; cut clipboard has precedence over copy; will prompt for confirmation
1334-
`y` copy_name copy name to system clipboard
1335-
`Y` copy_path copy relative path to system clipboard
1336-
`gy` copy_absolute_path copy absolute path to system clipboard
1337-
`[e` prev_diag_item go to next diagnostic item
1338-
`[c` prev_git_item go to next git item
1339-
`]e` next_diag_item go to prev diagnostic item
1340-
`]c` next_git_item go to prev git item
1341-
`-` dir_up navigate up to the parent directory of the current file/directory
1342-
`s` system_open open a file with default system application or a folder with default file manager, using |system_open| option
1343-
`f` live_filter live filter nodes dynamically based on regex matching.
1344-
`F` clear_live_filter clear live filter
1345-
`q` close close tree window
1346-
`W` collapse_all collapse the whole tree
1347-
`E` expand_all expand the whole tree, stopping after expanding |actions.expand_all.max_folder_discovery| folders; this might hang neovim for a while if running on a big folder
1348-
`S` search_node prompt the user to enter a path and then expands the tree to match the path
1349-
`.` run_file_command enter vim command mode with the file the cursor is on
1350-
`<C-k>` toggle_file_info toggle a popup with file infos about the file under the cursor
1351-
`g?` toggle_help toggle help
1352-
`m` toggle_mark Toggle node in bookmarks
1353-
`bmv` bulk_move Move all bookmarked nodes into specified location
1329+
`<C-v>` vsplit open the file in a vertical split
1330+
`<C-x>` split open the file in a horizontal split
1331+
`<C-t>` tabnew open the file in a new tab
1332+
`<` prev_sibling navigate to the previous sibling of current file/directory
1333+
`>` next_sibling navigate to the next sibling of current file/directory
1334+
`P` parent_node move cursor to the parent directory
1335+
`<BS>` close_node close current opened directory or parent
1336+
`<Tab>` preview open the file as a preview (keeps the cursor in the tree)
1337+
`K` first_sibling navigate to the first sibling of current file/directory
1338+
`J` last_sibling navigate to the last sibling of current file/directory
1339+
`C` toggle_git_clean toggle visibility of git clean via |filters.git_clean| option
1340+
`I` toggle_git_ignored toggle visibility of files/folders hidden via |git.ignore| option
1341+
`H` toggle_dotfiles toggle visibility of dotfiles via |filters.dotfiles| option
1342+
`B` toggle_no_buffer toggle visibility of files/folders hidden via |filters.no_buffer| option
1343+
`U` toggle_custom toggle visibility of files/folders hidden via |filters.custom| option
1344+
`R` refresh refresh the tree
1345+
`a` create add a file; leaving a trailing `/` will add a directory
1346+
`d` remove delete a file (will prompt for confirmation)
1347+
`D` trash trash a file via |trash| option
1348+
`r` rename rename a file
1349+
`<C-r>` full_rename rename a file and omit the filename on input
1350+
`x` cut add/remove file/directory to cut clipboard
1351+
`c` copy add/remove file/directory to copy clipboard
1352+
`p` paste paste from clipboard; cut clipboard has precedence over copy; will prompt for confirmation
1353+
`y` copy_name copy name to system clipboard
1354+
`Y` copy_path copy relative path to system clipboard
1355+
`gy` copy_absolute_path copy absolute path to system clipboard
1356+
`[e` prev_diag_item go to next diagnostic item
1357+
`[c` prev_git_item go to next git item
1358+
`]e` next_diag_item go to prev diagnostic item
1359+
`]c` next_git_item go to prev git item
1360+
`-` dir_up navigate up to the parent directory of the current file/directory
1361+
`s` system_open open a file with default system application or a folder with default file manager, using |system_open| option
1362+
`f` live_filter live filter nodes dynamically based on regex matching.
1363+
`F` clear_live_filter clear live filter
1364+
`q` close close tree window
1365+
`W` collapse_all collapse the whole tree
1366+
`E` expand_all expand the whole tree, stopping after expanding |actions.expand_all.max_folder_discovery| folders; this might hang neovim for a while if running on a big folder
1367+
`S` search_node prompt the user to enter a path and then expands the tree to match the path
1368+
`.` run_file_command enter vim command mode with the file the cursor is on
1369+
`<C-k>` toggle_file_info toggle a popup with file infos about the file under the cursor
1370+
`g?` toggle_help toggle help
1371+
`m` toggle_mark Toggle node in bookmarks
1372+
`bmv` bulk_move Move all bookmarked nodes into specified location
13541373

13551374
>
13561375
view.mappings.list = { -- BEGIN_DEFAULT_MAPPINGS
@@ -1368,8 +1387,10 @@ DEFAULT MAPPINGS *nvim-tree-default-mappings
13681387
{ key = "<Tab>", action = "preview" },
13691388
{ key = "K", action = "first_sibling" },
13701389
{ key = "J", action = "last_sibling" },
1390+
{ key = "C", action = "toggle_git_clean" },
13711391
{ key = "I", action = "toggle_git_ignored" },
13721392
{ key = "H", action = "toggle_dotfiles" },
1393+
{ key = "B", action = "toggle_no_buffer" },
13731394
{ key = "U", action = "toggle_custom" },
13741395
{ key = "R", action = "refresh" },
13751396
{ key = "a", action = "create" },

lua/nvim-tree.lua

+19
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ local reloaders = require "nvim-tree.actions.reloaders.reloaders"
1111
local copy_paste = require "nvim-tree.actions.fs.copy-paste"
1212
local collapse_all = require "nvim-tree.actions.tree-modifiers.collapse-all"
1313
local git = require "nvim-tree.git"
14+
local filters = require "nvim-tree.explorer.filters"
1415

1516
local _config = {}
1617

@@ -353,6 +354,22 @@ local function setup_autocommands(opts)
353354
create_nvim_tree_autocmd("BufWritePost", { callback = reloaders.reload_explorer })
354355
end
355356

357+
create_nvim_tree_autocmd("BufReadPost", {
358+
callback = function()
359+
if filters.config.filter_no_buffer then
360+
reloaders.reload_explorer()
361+
end
362+
end,
363+
})
364+
365+
create_nvim_tree_autocmd("BufUnload", {
366+
callback = function(data)
367+
if filters.config.filter_no_buffer then
368+
reloaders.reload_explorer(nil, data.buf)
369+
end
370+
end,
371+
})
372+
356373
if not has_watchers and opts.git.enable then
357374
create_nvim_tree_autocmd("User", {
358375
pattern = { "FugitiveChanged", "NeogitStatusRefreshed" },
@@ -583,6 +600,8 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
583600
},
584601
filters = {
585602
dotfiles = false,
603+
git_clean = false,
604+
no_buffer = false,
586605
custom = {},
587606
exclude = {},
588607
},

lua/nvim-tree/actions/dispatch.lua

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ local Actions = {
1212
toggle_dotfiles = require("nvim-tree.actions.tree-modifiers.toggles").dotfiles,
1313
toggle_custom = require("nvim-tree.actions.tree-modifiers.toggles").custom,
1414
toggle_git_ignored = require("nvim-tree.actions.tree-modifiers.toggles").git_ignored,
15+
toggle_git_clean = require("nvim-tree.actions.tree-modifiers.toggles").git_clean,
16+
toggle_no_buffer = require("nvim-tree.actions.tree-modifiers.toggles").no_buffer,
1517

1618
-- Filesystem operations
1719
copy_absolute_path = require("nvim-tree.actions.fs.copy-paste").copy_absolute_path,

lua/nvim-tree/actions/finders/search-node.lua

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ local function search(search_dir, input_path)
1414
local function iter(dir)
1515
local realpath, path, name, stat, handle, _
1616

17+
local filter_status = filters.prepare()
18+
1719
handle, _ = vim.loop.fs_scandir(dir)
1820
if not handle then
1921
return
@@ -34,7 +36,7 @@ local function search(search_dir, input_path)
3436
break
3537
end
3638

37-
if not filters.should_ignore(path) then
39+
if not filters.should_filter(path, filter_status) then
3840
if string.find(path, "/" .. input_path .. "$") then
3941
return path
4042
end

lua/nvim-tree/actions/init.lua

+10
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ local DEFAULT_MAPPINGS = {
7676
action = "last_sibling",
7777
desc = "navigate to the last sibling of current file/directory",
7878
},
79+
{
80+
key = "C",
81+
action = "toggle_git_clean",
82+
desc = "toggle visibility of git clean via |filters.git_clean| option",
83+
},
7984
{
8085
key = "I",
8186
action = "toggle_git_ignored",
@@ -86,6 +91,11 @@ local DEFAULT_MAPPINGS = {
8691
action = "toggle_dotfiles",
8792
desc = "toggle visibility of dotfiles via |filters.dotfiles| option",
8893
},
94+
{
95+
key = "B",
96+
action = "toggle_no_buffer",
97+
desc = "toggle visibility of files/folders hidden via |filters.no_buffer| option",
98+
},
8999
{
90100
key = "U",
91101
action = "toggle_custom",

lua/nvim-tree/actions/reloaders/reloaders.lua

+7-5
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ local core = require "nvim-tree.core"
66

77
local M = {}
88

9-
local function refresh_nodes(node, projects)
9+
local function refresh_nodes(node, projects, unloaded_bufnr)
1010
local cwd = node.cwd or node.link_to or node.absolute_path
1111
local project_root = git.get_project_root(cwd)
12-
explorer_module.reload(node, projects[project_root] or {})
12+
explorer_module.reload(node, projects[project_root] or {}, unloaded_bufnr)
1313
for _, _node in ipairs(node.nodes) do
1414
if _node.nodes and _node.open then
15-
refresh_nodes(_node, projects)
15+
refresh_nodes(_node, projects, unloaded_bufnr)
1616
end
1717
end
1818
end
@@ -33,14 +33,16 @@ function M.reload_node_status(parent_node, projects)
3333
end
3434

3535
local event_running = false
36-
function M.reload_explorer()
36+
---@param _ table unused node passed by action
37+
---@param unloaded_bufnr number optional bufnr recently unloaded via BufUnload event
38+
function M.reload_explorer(_, unloaded_bufnr)
3739
if event_running or not core.get_explorer() or vim.v.exiting ~= vim.NIL then
3840
return
3941
end
4042
event_running = true
4143

4244
local projects = git.reload()
43-
refresh_nodes(core.get_explorer(), projects)
45+
refresh_nodes(core.get_explorer(), projects, unloaded_bufnr)
4446
if view.is_visible() then
4547
renderer.draw()
4648
end

lua/nvim-tree/actions/tree-modifiers/toggles.lua

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ function M.git_ignored()
1515
return reloaders.reload_explorer()
1616
end
1717

18+
function M.git_clean()
19+
filters.config.filter_git_clean = not filters.config.filter_git_clean
20+
return reloaders.reload_explorer()
21+
end
22+
23+
function M.no_buffer()
24+
filters.config.filter_no_buffer = not filters.config.filter_no_buffer
25+
return reloaders.reload_explorer()
26+
end
27+
1828
function M.dotfiles()
1929
filters.config.filter_dotfiles = not filters.config.filter_dotfiles
2030
return reloaders.reload_explorer()

lua/nvim-tree/api.lua

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ Api.tree.search_node = require("nvim-tree.actions.finders.search-node").fn
3838
Api.tree.collapse_all = require("nvim-tree.actions.tree-modifiers.collapse-all").fn
3939
Api.tree.expand_all = inject_node(require("nvim-tree.actions.tree-modifiers.expand-all").fn)
4040
Api.tree.toggle_gitignore_filter = require("nvim-tree.actions.tree-modifiers.toggles").git_ignored
41+
Api.tree.toggle_git_clean_filter = require("nvim-tree.actions.tree-modifiers.toggles").git_clean
42+
Api.tree.toggle_no_buffer_filter = require("nvim-tree.actions.tree-modifiers.toggles").no_buffer
4143
Api.tree.toggle_custom_filter = require("nvim-tree.actions.tree-modifiers.toggles").custom
4244
Api.tree.toggle_hidden_filter = require("nvim-tree.actions.tree-modifiers.toggles").dotfiles
4345
Api.tree.toggle_help = require("nvim-tree.actions.tree-modifiers.toggles").help

lua/nvim-tree/explorer/explore.lua

+4-7
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ local function get_type_from(type_, cwd)
1212
return type_ or (vim.loop.fs_stat(cwd) or {}).type
1313
end
1414

15-
local function populate_children(handle, cwd, node, status)
15+
local function populate_children(handle, cwd, node, git_status)
1616
local node_ignored = node.git_status == "!!"
1717
local nodes_by_path = utils.bool_record(node.nodes, "absolute_path")
18+
local filter_status = filters.prepare(git_status)
1819
while true do
1920
local name, t = vim.loop.fs_scandir_next(handle)
2021
if not name then
@@ -23,11 +24,7 @@ local function populate_children(handle, cwd, node, status)
2324

2425
local abs = utils.path_join { cwd, name }
2526
t = get_type_from(t, abs)
26-
if
27-
not filters.should_ignore(abs)
28-
and not filters.should_ignore_git(abs, status.files)
29-
and not nodes_by_path[abs]
30-
then
27+
if not filters.should_filter(abs, filter_status) and not nodes_by_path[abs] then
3128
local child = nil
3229
if t == "directory" and vim.loop.fs_access(abs, "R") then
3330
child = builders.folder(node, abs, name)
@@ -42,7 +39,7 @@ local function populate_children(handle, cwd, node, status)
4239
if child then
4340
table.insert(node.nodes, child)
4441
nodes_by_path[child.absolute_path] = true
45-
common.update_git_status(child, node_ignored, status)
42+
common.update_git_status(child, node_ignored, git_status)
4643
end
4744
end
4845
end

0 commit comments

Comments
 (0)