mirror of
https://github.com/neovim/neovim.git
synced 2025-12-15 19:05:40 +00:00
feat(fs): add vim.fs.root (#28477)
vim.fs.root() is a function for finding a project root relative to a buffer using one or more "root markers". This is useful for LSP and could be useful for other "projects" designs, as well as for any plugins which work with a "projects" concept.
This commit is contained in:
@@ -197,13 +197,6 @@ end
|
||||
--- Examples:
|
||||
---
|
||||
--- ```lua
|
||||
--- -- location of Cargo.toml from the current buffer's path
|
||||
--- local cargo = vim.fs.find('Cargo.toml', {
|
||||
--- upward = true,
|
||||
--- stop = vim.uv.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'},
|
||||
@@ -334,6 +327,56 @@ function M.find(names, opts)
|
||||
return matches
|
||||
end
|
||||
|
||||
--- Find the first parent directory containing a specific "marker", relative to a buffer's
|
||||
--- directory.
|
||||
---
|
||||
--- Example:
|
||||
---
|
||||
--- ```lua
|
||||
--- -- Find the root of a Python project, starting from file 'main.py'
|
||||
--- vim.fs.root(vim.fs.joinpath(vim.env.PWD, 'main.py'), {'pyproject.toml', 'setup.py' })
|
||||
---
|
||||
--- -- Find the root of a git repository
|
||||
--- vim.fs.root(0, '.git')
|
||||
---
|
||||
--- -- Find the parent directory containing any file with a .csproj extension
|
||||
--- vim.fs.root(0, function(name, path)
|
||||
--- return name:match('%.csproj$') ~= nil
|
||||
--- end)
|
||||
--- ```
|
||||
---
|
||||
--- @param source integer|string Buffer number (0 for current buffer) or file path to begin the
|
||||
--- search from.
|
||||
--- @param marker (string|string[]|fun(name: string, path: string): boolean) A marker, or list
|
||||
--- of markers, to search for. If a function, the function is called for each
|
||||
--- evaluated item and should return true if {name} and {path} are a match.
|
||||
--- @return string? # Directory path containing one of the given markers, or nil if no directory was
|
||||
--- found.
|
||||
function M.root(source, marker)
|
||||
assert(source, 'missing required argument: source')
|
||||
assert(marker, 'missing required argument: marker')
|
||||
|
||||
local path ---@type string
|
||||
if type(source) == 'string' then
|
||||
path = source
|
||||
elseif type(source) == 'number' then
|
||||
path = vim.api.nvim_buf_get_name(source)
|
||||
else
|
||||
error('invalid type for argument "source": expected string or buffer number')
|
||||
end
|
||||
|
||||
local paths = M.find(marker, {
|
||||
upward = true,
|
||||
path = path,
|
||||
})
|
||||
|
||||
if #paths == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
return vim.fs.dirname(paths[1])
|
||||
end
|
||||
|
||||
--- Split a Windows path into a prefix and a body, such that the body can be processed like a POSIX
|
||||
--- path. The path must use forward slashes as path separator.
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user