Skip to content

Commit c0c39e7

Browse files
committed
feat(files): add option to use "git check-ignore" for gitignore checks, fixes #147
1 parent d69601f commit c0c39e7

File tree

4 files changed

+60
-6
lines changed

4 files changed

+60
-6
lines changed

lua/neo-tree/defaults.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ local config = {
153153
filters = {
154154
show_hidden = false,
155155
respect_gitignore = true,
156-
gitignore_source = "git", -- or "plenary", which may be faster in a slow repo but less accurate
156+
gitignore_source = "git status", -- or "git check-ignored", which may be faster in some repos
157157
},
158158
bind_to_cwd = true, -- true creates a 2-way binding between vim's cwd and neo-tree's root
159159
-- The renderer section provides the renderers that will be used to render the tree.

lua/neo-tree/git/init.lua

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
local Path = require("plenary.path")
22
local utils = require("neo-tree.utils")
3+
local log = require("neo-tree.log")
34

45
local os_sep = Path.path.sep
56

@@ -124,6 +125,24 @@ M.status = function(exclude_directories)
124125
return git_status, git_root
125126
end
126127

128+
M.load_ignored_per_directory = function(path)
129+
if type(path) ~= "string" then
130+
log.error("load_ignored_per_directory: path must be a string")
131+
return {}
132+
end
133+
path = utils.path_join(path, "*")
134+
local cmd = 'git check-ignore "' .. path .. '"'
135+
local result = vim.fn.systemlist(cmd)
136+
if vim.v.shell_error == 128 then
137+
if utils.truthy(result) and vim.startswith(result[1], "fatal: not a git repository") then
138+
return {}
139+
end
140+
log.error("Failed to load ignored files for ", path, ": ", result)
141+
return {}
142+
end
143+
return result
144+
end
145+
127146
M.load_ignored = function(path)
128147
local git_root = M.get_repository_root(path)
129148
if not git_root then

lua/neo-tree/sources/filesystem/lib/fs_scan.lua

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ local function do_scan(context, path_to_scan)
1818
local paths_to_load = context.paths_to_load
1919
local folders = context.folders
2020
local filters = state.filters or {}
21-
local use_gitignore_table = filters.respect_gitignore and filters.gitignore_source == "git"
21+
local use_gitignore_table = filters.respect_gitignore and utils.truthy(state.git_ignored)
2222

2323
scan.scan_dir_async(path_to_scan, {
2424
hidden = filters.show_hidden or false,
@@ -150,11 +150,18 @@ M.get_items_async = function(state, parent_id, path_to_reveal, callback)
150150
context.paths_to_load = utils.unique(context.paths_to_load)
151151
end
152152

153-
if state.filters.respect_gitignore and state.filters.gitignore_source == "git" then
154-
state.git_ignored = git.load_ignored(state.path) or {}
155-
else
156-
state.git_ignored = {}
153+
local ignored = {}
154+
if state.filters.respect_gitignore then
155+
if state.filters.gitignore_source == "git status" then
156+
ignored = git.load_ignored(state.path)
157+
elseif state.filters.gitignore_source == "git check-ignore" then
158+
ignored = git.load_ignored_per_directory(state.path)
159+
for _, p in ipairs(context.paths_to_load) do
160+
vim.list_extend(ignored, git.load_ignored_per_directory(p))
161+
end
162+
end
157163
end
164+
state.git_ignored = ignored
158165
end
159166
do_scan(context, parent_id or state.path)
160167
end

lua/neo-tree/utils.lua

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,13 @@ M.is_subpath = function(base, path)
329329
return string.sub(path, 1, string.len(base)) == base
330330
end
331331

332+
---The file system path separator for the current platform.
333+
M.path_separator = "/"
334+
M.is_windows = vim.fn.has("win32") == 1 or vim.fn.has("win32unix") == 1
335+
if M.is_windows == true then
336+
M.path_separator = "\\"
337+
end
338+
332339
---Split string into a table of strings using a separator.
333340
---@param inputString string The string to split.
334341
---@param sep string The separator to use.
@@ -363,6 +370,27 @@ M.split_path = function(path)
363370
return parentPath, name
364371
end
365372

373+
---Joins arbitrary number of paths together.
374+
---@param ... string The paths to join.
375+
---@return string
376+
M.path_join = function(...)
377+
local args = { ... }
378+
if #args == 0 then
379+
return ""
380+
end
381+
382+
local all_parts = {}
383+
if type(args[1]) == "string" and args[1]:sub(1, 1) == M.path_separator then
384+
all_parts[1] = ""
385+
end
386+
387+
for _, arg in ipairs(args) do
388+
arg_parts = M.split(arg, M.path_separator)
389+
vim.list_extend(all_parts, arg_parts)
390+
end
391+
return table.concat(all_parts, M.path_separator)
392+
end
393+
366394
local table_merge_internal
367395
---Merges overrideTable into baseTable. This mutates baseTable.
368396
---@param base_table table The base table that provides default values.

0 commit comments

Comments
 (0)