feat(vim.fs): pass path to find() predicate, lazy evaluate #22378

Problem:
No easy way to find files under certain directories (ex: grab all files under
`test/`) or exclude the content of certain paths (ex. `build/`, `.git/`)

Solution:
Pass the full `path` as an arg to the predicate.
This commit is contained in:
Mike
2023-03-01 10:51:22 -06:00
committed by GitHub
parent 014981c900
commit bc15b075d1
3 changed files with 70 additions and 11 deletions

View File

@@ -144,11 +144,34 @@ end
--- The search can be narrowed to find only files or only directories by
--- specifying {type} to be "file" or "directory", respectively.
---
---@param names (string|table|fun(name: string): boolean) Names of the files
--- Examples:
--- <pre>lua
--- -- location of Cargo.toml from the current buffer's path
--- local cargo = vim.fs.find('Cargo.toml', {
--- upward = true,
--- stop = vim.loop.os_homedir(),
--- path = vim.fs.dirname(vim.api.nvim_buf_get_name(0)),
--- })
---
--- -- list all test directories under the runtime directory
--- local test_dirs = vim.fs.find(
--- {'test', 'tst', 'testdir'},
--- {limit = math.huge, type = 'directory', path = './runtime/'}
--- )
---
--- -- get all files ending with .cpp or .hpp inside lib/
--- local cpp_hpp = vim.fs.find(function(name, path)
--- return name:match('.*%.[ch]pp$') and path:match('[/\\\\]lib$')
--- end, {limit = math.huge, type = 'file'})
--- </pre>
---
---@param names (string|table|fun(name: string, path: string): boolean) Names of the files
--- and directories to find.
--- Must be base names, paths and globs are not supported.
--- The function is called per file and directory within the
--- traversed directories to test if they match {names}.
--- Must be base names, paths and globs are not supported when {names} is a string or a table.
--- If {names} is a function, it is called for each traversed file and directory with args:
--- - name: base name of the current item
--- - path: full path of the current item
--- The function should return `true` if the given file or directory is considered a match.
---
---@param opts (table) Optional keyword arguments:
--- - path (string): Path to begin searching from. If
@@ -201,7 +224,7 @@ function M.find(names, opts)
test = function(p)
local t = {}
for name, type in M.dir(p) do
if names(name) and (not opts.type or opts.type == type) then
if (not opts.type or opts.type == type) and names(name, p) then
table.insert(t, join_paths(p, name))
end
end
@@ -250,7 +273,7 @@ function M.find(names, opts)
for other, type_ in M.dir(dir) do
local f = join_paths(dir, other)
if type(names) == 'function' then
if names(other) and (not opts.type or opts.type == type_) then
if (not opts.type or opts.type == type_) and names(other, dir) then
if add(f) then
return matches
end