Skip to content
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

feat(fs.lua): pass path to vim.fs.find function predicate and lazy evaluate the predicate #22378

Merged
merged 7 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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
34 changes: 29 additions & 5 deletions runtime/doc/lua.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2359,12 +2359,36 @@ 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 the C++ source and header files inside lib/
dundargoc marked this conversation as resolved.
Show resolved Hide resolved
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 will be called once for
each file or directory within the traversed directory with
the base name of the file and directory and the path of the
directory being traversed. 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.
Expand Down
35 changes: 29 additions & 6 deletions runtime/lua/vim/fs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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 the C++ source and header files 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
justinmk marked this conversation as resolved.
Show resolved Hide resolved
--- 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 will be called once for each file or directory
--- within the traversed directory with the base name of the
--- file and directory and the path of the directory being traversed.
mike325 marked this conversation as resolved.
Show resolved Hide resolved
--- The function should return `true` if the given file or directory is considered a match.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess a blank line is needed here to work around the docs rendering issue (it joins this line).

Suggested change
--- The function should return `true` if the given file or directory is considered a match.
---
--- The function should return `true` if the given file or directory is considered a match.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not seem to work, gen_vimdoc.py sends everything after the new line to the general description, just below the code examples, it renders like

...
     -- 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'})
<

    The function should return `true` if the given file or directory is considered a match.

    Parameters: ~{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
...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I'll try to fix it later.

Don't want to block this PR meanwhile.

---
---@param opts (table) Optional keyword arguments:
--- - path (string): Path to begin searching from. If
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down