Skip to content

feat(view): add filters.git_clean, filters.no_buffer #1784

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 11 commits into from
Dec 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
115 changes: 68 additions & 47 deletions doc/nvim-tree-lua.txt
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ Subsequent calls to setup will replace the previous configuration.
debounce_delay = 50,
severity = {
min = vim.diagnostic.severity.HINT,
max = vim.diagnostic.severity.ERROR
max = vim.diagnostic.severity.ERROR,
},
icons = {
hint = "",
Expand All @@ -307,6 +307,8 @@ Subsequent calls to setup will replace the previous configuration.
},
filters = {
dotfiles = false,
git_clean = false,
no_buffer = false,
custom = {},
exclude = {},
},
Expand Down Expand Up @@ -903,6 +905,19 @@ Filtering options.
Toggle via the `toggle_dotfiles` action, default mapping `H`.
Type: `boolean`, Default: `false`

*nvim-tree.filters.git_clean*
Do not show files with no git status. This will show ignored files when
|nvim-tree.git.ignore| is set, as they are effectively dirty.
Toggle via the `toggle_git_clean` action, default mapping `C`.
Type: `boolean`, Default: `false`

*nvim-tree.filters.no_buffer*
Do not show files that have no listed buffer.
Toggle via the `toggle_no_buffer` action, default mapping `B`.
For performance reasons this may not immediately update on buffer
delete/wipe. A reload or filesystem event will result in an update.
Type: `boolean`, Default: `false`

*nvim-tree.filters.custom*
Custom list of vim regex for file/directory names that will not be shown.
Backslashes must be escaped e.g. "^\\.git". See |string-match|.
Expand Down Expand Up @@ -1188,6 +1203,8 @@ exists.
- collapse_all `(keep_buffers?: bool)`
- expand_all
- toggle_gitignore_filter
- toggle_git_clean_filter
- toggle_no_buffer_filter
- toggle_custom_filter
- toggle_hidden_filter
- toggle_help
Expand Down Expand Up @@ -1302,55 +1319,57 @@ Single right / middle mouse mappings will requre changes to |mousemodel| or |mou

DEFAULT MAPPINGS *nvim-tree-default-mappings*

`<CR>` edit open a file or folder; root will cd to the above directory
`<CR>` edit open a file or folder; root will cd to the above directory
`o`
`<2-LeftMouse>`
`<C-e>` edit_in_place edit the file in place, effectively replacing the tree explorer
`O` edit_no_picker same as (edit) with no window picker
`<C-]>` cd cd in the directory under the cursor
`<C-e>` edit_in_place edit the file in place, effectively replacing the tree explorer
`O` edit_no_picker same as (edit) with no window picker
`<C-]>` cd cd in the directory under the cursor
`<2-RightMouse>`
`<C-v>` vsplit open the file in a vertical split
`<C-x>` split open the file in a horizontal split
`<C-t>` tabnew open the file in a new tab
`<` prev_sibling navigate to the previous sibling of current file/directory
`>` next_sibling navigate to the next sibling of current file/directory
`P` parent_node move cursor to the parent directory
`<BS>` close_node close current opened directory or parent
`<Tab>` preview open the file as a preview (keeps the cursor in the tree)
`K` first_sibling navigate to the first sibling of current file/directory
`J` last_sibling navigate to the last sibling of current file/directory
`I` toggle_git_ignored toggle visibility of files/folders hidden via |git.ignore| option
`H` toggle_dotfiles toggle visibility of dotfiles via |filters.dotfiles| option
`U` toggle_custom toggle visibility of files/folders hidden via |filters.custom| option
`R` refresh refresh the tree
`a` create add a file; leaving a trailing `/` will add a directory
`d` remove delete a file (will prompt for confirmation)
`D` trash trash a file via |trash| option
`r` rename rename a file
`<C-r>` full_rename rename a file and omit the filename on input
`x` cut add/remove file/directory to cut clipboard
`c` copy add/remove file/directory to copy clipboard
`p` paste paste from clipboard; cut clipboard has precedence over copy; will prompt for confirmation
`y` copy_name copy name to system clipboard
`Y` copy_path copy relative path to system clipboard
`gy` copy_absolute_path copy absolute path to system clipboard
`[e` prev_diag_item go to next diagnostic item
`[c` prev_git_item go to next git item
`]e` next_diag_item go to prev diagnostic item
`]c` next_git_item go to prev git item
`-` dir_up navigate up to the parent directory of the current file/directory
`s` system_open open a file with default system application or a folder with default file manager, using |system_open| option
`f` live_filter live filter nodes dynamically based on regex matching.
`F` clear_live_filter clear live filter
`q` close close tree window
`W` collapse_all collapse the whole tree
`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
`S` search_node prompt the user to enter a path and then expands the tree to match the path
`.` run_file_command enter vim command mode with the file the cursor is on
`<C-k>` toggle_file_info toggle a popup with file infos about the file under the cursor
`g?` toggle_help toggle help
`m` toggle_mark Toggle node in bookmarks
`bmv` bulk_move Move all bookmarked nodes into specified location
`<C-v>` vsplit open the file in a vertical split
`<C-x>` split open the file in a horizontal split
`<C-t>` tabnew open the file in a new tab
`<` prev_sibling navigate to the previous sibling of current file/directory
`>` next_sibling navigate to the next sibling of current file/directory
`P` parent_node move cursor to the parent directory
`<BS>` close_node close current opened directory or parent
`<Tab>` preview open the file as a preview (keeps the cursor in the tree)
`K` first_sibling navigate to the first sibling of current file/directory
`J` last_sibling navigate to the last sibling of current file/directory
`C` toggle_git_clean toggle visibility of git clean via |filters.git_clean| option
`I` toggle_git_ignored toggle visibility of files/folders hidden via |git.ignore| option
`H` toggle_dotfiles toggle visibility of dotfiles via |filters.dotfiles| option
`B` toggle_no_buffer toggle visibility of files/folders hidden via |filters.no_buffer| option
`U` toggle_custom toggle visibility of files/folders hidden via |filters.custom| option
`R` refresh refresh the tree
`a` create add a file; leaving a trailing `/` will add a directory
`d` remove delete a file (will prompt for confirmation)
`D` trash trash a file via |trash| option
`r` rename rename a file
`<C-r>` full_rename rename a file and omit the filename on input
`x` cut add/remove file/directory to cut clipboard
`c` copy add/remove file/directory to copy clipboard
`p` paste paste from clipboard; cut clipboard has precedence over copy; will prompt for confirmation
`y` copy_name copy name to system clipboard
`Y` copy_path copy relative path to system clipboard
`gy` copy_absolute_path copy absolute path to system clipboard
`[e` prev_diag_item go to next diagnostic item
`[c` prev_git_item go to next git item
`]e` next_diag_item go to prev diagnostic item
`]c` next_git_item go to prev git item
`-` dir_up navigate up to the parent directory of the current file/directory
`s` system_open open a file with default system application or a folder with default file manager, using |system_open| option
`f` live_filter live filter nodes dynamically based on regex matching.
`F` clear_live_filter clear live filter
`q` close close tree window
`W` collapse_all collapse the whole tree
`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
`S` search_node prompt the user to enter a path and then expands the tree to match the path
`.` run_file_command enter vim command mode with the file the cursor is on
`<C-k>` toggle_file_info toggle a popup with file infos about the file under the cursor
`g?` toggle_help toggle help
`m` toggle_mark Toggle node in bookmarks
`bmv` bulk_move Move all bookmarked nodes into specified location

>
view.mappings.list = { -- BEGIN_DEFAULT_MAPPINGS
Expand All @@ -1368,8 +1387,10 @@ DEFAULT MAPPINGS *nvim-tree-default-mappings
{ key = "<Tab>", action = "preview" },
{ key = "K", action = "first_sibling" },
{ key = "J", action = "last_sibling" },
{ key = "C", action = "toggle_git_clean" },
{ key = "I", action = "toggle_git_ignored" },
{ key = "H", action = "toggle_dotfiles" },
{ key = "B", action = "toggle_no_buffer" },
{ key = "U", action = "toggle_custom" },
{ key = "R", action = "refresh" },
{ key = "a", action = "create" },
Expand Down
19 changes: 19 additions & 0 deletions lua/nvim-tree.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ local reloaders = require "nvim-tree.actions.reloaders.reloaders"
local copy_paste = require "nvim-tree.actions.fs.copy-paste"
local collapse_all = require "nvim-tree.actions.tree-modifiers.collapse-all"
local git = require "nvim-tree.git"
local filters = require "nvim-tree.explorer.filters"

local _config = {}

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

create_nvim_tree_autocmd("BufReadPost", {
callback = function()
if filters.config.filter_no_buffer then
reloaders.reload_explorer()
end
end,
})

create_nvim_tree_autocmd("BufUnload", {
callback = function(data)
if filters.config.filter_no_buffer then
reloaders.reload_explorer(nil, data.buf)
end
end,
})

if not has_watchers and opts.git.enable then
create_nvim_tree_autocmd("User", {
pattern = { "FugitiveChanged", "NeogitStatusRefreshed" },
Expand Down Expand Up @@ -583,6 +600,8 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
},
filters = {
dotfiles = false,
git_clean = false,
no_buffer = false,
custom = {},
exclude = {},
},
Expand Down
2 changes: 2 additions & 0 deletions lua/nvim-tree/actions/dispatch.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ local Actions = {
toggle_dotfiles = require("nvim-tree.actions.tree-modifiers.toggles").dotfiles,
toggle_custom = require("nvim-tree.actions.tree-modifiers.toggles").custom,
toggle_git_ignored = require("nvim-tree.actions.tree-modifiers.toggles").git_ignored,
toggle_git_clean = require("nvim-tree.actions.tree-modifiers.toggles").git_clean,
toggle_no_buffer = require("nvim-tree.actions.tree-modifiers.toggles").no_buffer,

-- Filesystem operations
copy_absolute_path = require("nvim-tree.actions.fs.copy-paste").copy_absolute_path,
Expand Down
4 changes: 3 additions & 1 deletion lua/nvim-tree/actions/finders/search-node.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ local function search(search_dir, input_path)
local function iter(dir)
local realpath, path, name, stat, handle, _

local filter_status = filters.prepare()

handle, _ = vim.loop.fs_scandir(dir)
if not handle then
return
Expand All @@ -34,7 +36,7 @@ local function search(search_dir, input_path)
break
end

if not filters.should_ignore(path) then
if not filters.should_filter(path, filter_status) then
if string.find(path, "/" .. input_path .. "$") then
return path
end
Expand Down
10 changes: 10 additions & 0 deletions lua/nvim-tree/actions/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ local DEFAULT_MAPPINGS = {
action = "last_sibling",
desc = "navigate to the last sibling of current file/directory",
},
{
key = "C",
action = "toggle_git_clean",
desc = "toggle visibility of git clean via |filters.git_clean| option",
},
{
key = "I",
action = "toggle_git_ignored",
Expand All @@ -86,6 +91,11 @@ local DEFAULT_MAPPINGS = {
action = "toggle_dotfiles",
desc = "toggle visibility of dotfiles via |filters.dotfiles| option",
},
{
key = "B",
action = "toggle_no_buffer",
desc = "toggle visibility of files/folders hidden via |filters.no_buffer| option",
},
{
key = "U",
action = "toggle_custom",
Expand Down
12 changes: 7 additions & 5 deletions lua/nvim-tree/actions/reloaders/reloaders.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ local core = require "nvim-tree.core"

local M = {}

local function refresh_nodes(node, projects)
local function refresh_nodes(node, projects, unloaded_bufnr)
local cwd = node.cwd or node.link_to or node.absolute_path
local project_root = git.get_project_root(cwd)
explorer_module.reload(node, projects[project_root] or {})
explorer_module.reload(node, projects[project_root] or {}, unloaded_bufnr)
for _, _node in ipairs(node.nodes) do
if _node.nodes and _node.open then
refresh_nodes(_node, projects)
refresh_nodes(_node, projects, unloaded_bufnr)
end
end
end
Expand All @@ -33,14 +33,16 @@ function M.reload_node_status(parent_node, projects)
end

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

local projects = git.reload()
refresh_nodes(core.get_explorer(), projects)
refresh_nodes(core.get_explorer(), projects, unloaded_bufnr)
if view.is_visible() then
renderer.draw()
end
Expand Down
10 changes: 10 additions & 0 deletions lua/nvim-tree/actions/tree-modifiers/toggles.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ function M.git_ignored()
return reloaders.reload_explorer()
end

function M.git_clean()
filters.config.filter_git_clean = not filters.config.filter_git_clean
return reloaders.reload_explorer()
end

function M.no_buffer()
filters.config.filter_no_buffer = not filters.config.filter_no_buffer
return reloaders.reload_explorer()
end

function M.dotfiles()
filters.config.filter_dotfiles = not filters.config.filter_dotfiles
return reloaders.reload_explorer()
Expand Down
2 changes: 2 additions & 0 deletions lua/nvim-tree/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ Api.tree.search_node = require("nvim-tree.actions.finders.search-node").fn
Api.tree.collapse_all = require("nvim-tree.actions.tree-modifiers.collapse-all").fn
Api.tree.expand_all = inject_node(require("nvim-tree.actions.tree-modifiers.expand-all").fn)
Api.tree.toggle_gitignore_filter = require("nvim-tree.actions.tree-modifiers.toggles").git_ignored
Api.tree.toggle_git_clean_filter = require("nvim-tree.actions.tree-modifiers.toggles").git_clean
Api.tree.toggle_no_buffer_filter = require("nvim-tree.actions.tree-modifiers.toggles").no_buffer
Api.tree.toggle_custom_filter = require("nvim-tree.actions.tree-modifiers.toggles").custom
Api.tree.toggle_hidden_filter = require("nvim-tree.actions.tree-modifiers.toggles").dotfiles
Api.tree.toggle_help = require("nvim-tree.actions.tree-modifiers.toggles").help
Expand Down
11 changes: 4 additions & 7 deletions lua/nvim-tree/explorer/explore.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ local function get_type_from(type_, cwd)
return type_ or (vim.loop.fs_stat(cwd) or {}).type
end

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

local abs = utils.path_join { cwd, name }
t = get_type_from(t, abs)
if
not filters.should_ignore(abs)
and not filters.should_ignore_git(abs, status.files)
and not nodes_by_path[abs]
then
if not filters.should_filter(abs, filter_status) and not nodes_by_path[abs] then
local child = nil
if t == "directory" and vim.loop.fs_access(abs, "R") then
child = builders.folder(node, abs, name)
Expand All @@ -42,7 +39,7 @@ local function populate_children(handle, cwd, node, status)
if child then
table.insert(node.nodes, child)
nodes_by_path[child.absolute_path] = true
common.update_git_status(child, node_ignored, status)
common.update_git_status(child, node_ignored, git_status)
end
end
end
Expand Down
Loading