mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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:
parent
014981c900
commit
bc15b075d1
@ -2359,12 +2359,37 @@ find({names}, {opts}) *vim.fs.find()*
|
||||
The search can be narrowed to find only files or only directories by
|
||||
specifying {type} to be "file" or "directory", respectively.
|
||||
|
||||
Examples: >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'})
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {names} (string|table|fun(name: 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}.
|
||||
• {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 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.
|
||||
• {opts} (table) Optional keyword arguments:
|
||||
• path (string): Path to begin searching from. If omitted,
|
||||
the |current-directory| is used.
|
||||
|
@ -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
|
||||
|
@ -8,6 +8,7 @@ local mkdir_p = helpers.mkdir_p
|
||||
local rmdir = helpers.rmdir
|
||||
local nvim_dir = helpers.nvim_dir
|
||||
local test_build_dir = helpers.test_build_dir
|
||||
local test_source_path = helpers.test_source_path
|
||||
local nvim_prog = helpers.nvim_prog
|
||||
local is_os = helpers.is_os
|
||||
|
||||
@ -252,6 +253,16 @@ describe('vim.fs', function()
|
||||
local opts = { path = dir, upward = true, type = 'directory' }
|
||||
return vim.fs.find(function(x) return x == 'no-match' end, opts)
|
||||
]], nvim_dir))
|
||||
eq(
|
||||
exec_lua([[
|
||||
local dir = ...
|
||||
return vim.tbl_map(vim.fs.basename, vim.fn.glob(dir..'/contrib/*', false, true))
|
||||
]], test_source_path),
|
||||
exec_lua([[
|
||||
local dir = ...
|
||||
local opts = { path = dir, limit = math.huge }
|
||||
return vim.tbl_map(vim.fs.basename, vim.fs.find(function(_, d) return d:match('[\\/]contrib$') end, opts))
|
||||
]], test_source_path))
|
||||
end)
|
||||
end)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user