diff options
author | Mike <Mike325@users.noreply.github.com> | 2023-03-01 10:51:22 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-01 08:51:22 -0800 |
commit | bc15b075d14c85098d674a2466d2386e08b0005f (patch) | |
tree | 22eb1817988f98c7c55d5fc39e09d2287215c847 | |
parent | 014981c9006f9b96b8045e609dc27f4a84da5263 (diff) | |
download | rneovim-bc15b075d14c85098d674a2466d2386e08b0005f.tar.gz rneovim-bc15b075d14c85098d674a2466d2386e08b0005f.tar.bz2 rneovim-bc15b075d14c85098d674a2466d2386e08b0005f.zip |
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.
-rw-r--r-- | runtime/doc/lua.txt | 35 | ||||
-rw-r--r-- | runtime/lua/vim/fs.lua | 35 | ||||
-rw-r--r-- | test/functional/lua/fs_spec.lua | 11 |
3 files changed, 70 insertions, 11 deletions
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 8ae1c6dc40..e3e0665025 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -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. diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index a0d2c4c339..2c3fc64d57 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -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 diff --git a/test/functional/lua/fs_spec.lua b/test/functional/lua/fs_spec.lua index 642d36f63a..03de16c079 100644 --- a/test/functional/lua/fs_spec.lua +++ b/test/functional/lua/fs_spec.lua @@ -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) |