mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
backport: feat(vim.fs): vim.fs.root() can control priority #34413
feat(vim.fs): vim.fs.root() can control priority
Adds the capability of controlling the priority of searched markers in
vim.fs.root() by nesting lists.
(cherry picked from commit 0f0b96dd0f
)
This commit is contained in:
@@ -3165,6 +3165,10 @@ vim.fs.root({source}, {marker}) *vim.fs.root()*
|
|||||||
vim.fs.root(0, function(name, path)
|
vim.fs.root(0, function(name, path)
|
||||||
return name:match('%.csproj$') ~= nil
|
return name:match('%.csproj$') ~= nil
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Find the first ancestor directory containing EITHER "stylua.toml" or ".luarc.json"; if
|
||||||
|
-- not found, find the first ancestor containing ".git":
|
||||||
|
vim.fs.root(0, { { 'stylua.toml', '.luarc.json' }, '.git' })
|
||||||
<
|
<
|
||||||
|
|
||||||
Attributes: ~
|
Attributes: ~
|
||||||
@@ -3174,10 +3178,22 @@ vim.fs.root({source}, {marker}) *vim.fs.root()*
|
|||||||
• {source} (`integer|string`) Buffer number (0 for current buffer) or
|
• {source} (`integer|string`) Buffer number (0 for current buffer) or
|
||||||
file path (absolute or relative to the |current-directory|)
|
file path (absolute or relative to the |current-directory|)
|
||||||
to begin the search from.
|
to begin the search from.
|
||||||
• {marker} (`string|string[]|fun(name: string, path: string): boolean`)
|
• {marker} (`(string|string[]|fun(name: string, path: string): boolean)[]|string|fun(name: string, path: string): boolean`)
|
||||||
A marker, or list of markers, to search for. If a function,
|
A marker or a list of markers. A marker has one of three
|
||||||
the function is called for each evaluated item and should
|
types: string, a list of strings or a function. The
|
||||||
return true if {name} and {path} are a match.
|
parameter also accepts a list of markers, each of which is
|
||||||
|
any of those three types. If a marker is a function, it is
|
||||||
|
called for each evaluated item and should return true if
|
||||||
|
{name} and {path} are a match. If a list of markers is
|
||||||
|
passed, each marker in the list is evaluated in order and
|
||||||
|
the first marker which is matched returns the parent
|
||||||
|
directory that it found. This allows listing markers with
|
||||||
|
priority. E.g. - in the following list, a parent directory
|
||||||
|
containing either 'a' or 'b' is searched for. If neither is
|
||||||
|
found, then 'c' is searched for. So, 'c' has lower priority
|
||||||
|
than 'a' and 'b' which have equal priority. >lua
|
||||||
|
marker = { { 'a', 'b' }, 'c' }
|
||||||
|
<
|
||||||
|
|
||||||
Return: ~
|
Return: ~
|
||||||
(`string?`) Directory path containing one of the given markers, or nil
|
(`string?`) Directory path containing one of the given markers, or nil
|
||||||
|
@@ -305,6 +305,7 @@ LUA
|
|||||||
• |vim.hl.range()| now has a optional `timeout` field which allows for multiple
|
• |vim.hl.range()| now has a optional `timeout` field which allows for multiple
|
||||||
timed highlights.
|
timed highlights.
|
||||||
• |vim.text.indent()| indents/dedents text.
|
• |vim.text.indent()| indents/dedents text.
|
||||||
|
• |vim.fs.root()| can define "equal priority" via nested lists.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
|
|
||||||
|
@@ -388,14 +388,29 @@ end
|
|||||||
--- vim.fs.root(0, function(name, path)
|
--- vim.fs.root(0, function(name, path)
|
||||||
--- return name:match('%.csproj$') ~= nil
|
--- return name:match('%.csproj$') ~= nil
|
||||||
--- end)
|
--- end)
|
||||||
|
---
|
||||||
|
--- -- Find the first ancestor directory containing EITHER "stylua.toml" or ".luarc.json"; if
|
||||||
|
--- -- not found, find the first ancestor containing ".git":
|
||||||
|
--- vim.fs.root(0, { { 'stylua.toml', '.luarc.json' }, '.git' })
|
||||||
--- ```
|
--- ```
|
||||||
---
|
---
|
||||||
--- @since 12
|
--- @since 12
|
||||||
--- @param source integer|string Buffer number (0 for current buffer) or file path (absolute or
|
--- @param source integer|string Buffer number (0 for current buffer) or file path (absolute or
|
||||||
--- relative to the |current-directory|) to begin the search from.
|
--- relative to the |current-directory|) to begin the search from.
|
||||||
--- @param marker (string|string[]|fun(name: string, path: string): boolean) A marker, or list
|
--- @param marker (string|string[]|fun(name: string, path: string): boolean)[]|string|fun(name: string, path: string): boolean A marker or a list of markers.
|
||||||
--- of markers, to search for. If a function, the function is called for each
|
--- A marker has one of three types: string, a list of strings or a function. The
|
||||||
--- evaluated item and should return true if {name} and {path} are a match.
|
--- parameter also accepts a list of markers, each of which is any of those three
|
||||||
|
--- types. If a marker is a function, it is called for each evaluated item and
|
||||||
|
--- should return true if {name} and {path} are a match. If a list of markers is
|
||||||
|
--- passed, each marker in the list is evaluated in order and the first marker
|
||||||
|
--- which is matched returns the parent directory that it found. This allows
|
||||||
|
--- listing markers with priority. E.g. - in the following list, a parent directory
|
||||||
|
--- containing either 'a' or 'b' is searched for. If neither is found, then 'c' is
|
||||||
|
--- searched for. So, 'c' has lower priority than 'a' and 'b' which have equal
|
||||||
|
--- priority.
|
||||||
|
--- ```lua
|
||||||
|
--- marker = { { 'a', 'b' }, 'c' }
|
||||||
|
--- ```
|
||||||
--- @return string? # Directory path containing one of the given markers, or nil if no directory was
|
--- @return string? # Directory path containing one of the given markers, or nil if no directory was
|
||||||
--- found.
|
--- found.
|
||||||
function M.root(source, marker)
|
function M.root(source, marker)
|
||||||
@@ -415,16 +430,19 @@ function M.root(source, marker)
|
|||||||
error('invalid type for argument "source": expected string or buffer number')
|
error('invalid type for argument "source": expected string or buffer number')
|
||||||
end
|
end
|
||||||
|
|
||||||
local paths = M.find(marker, {
|
local markers = type(marker) == 'table' and marker or { marker }
|
||||||
upward = true,
|
for _, mark in ipairs(markers) do
|
||||||
path = vim.fn.fnamemodify(path, ':p:h'),
|
local paths = M.find(mark, {
|
||||||
})
|
upward = true,
|
||||||
|
path = vim.fn.fnamemodify(path, ':p:h'),
|
||||||
|
})
|
||||||
|
|
||||||
if #paths == 0 then
|
if #paths ~= 0 then
|
||||||
return nil
|
return vim.fs.dirname(paths[1])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return vim.fs.dirname(paths[1])
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Split a Windows path into a prefix and a body, such that the body can be processed like a POSIX
|
--- Split a Windows path into a prefix and a body, such that the body can be processed like a POSIX
|
||||||
|
@@ -708,13 +708,7 @@ function lsp.start(config, opts)
|
|||||||
validate('root_markers', opts._root_markers, 'table')
|
validate('root_markers', opts._root_markers, 'table')
|
||||||
config = vim.deepcopy(config)
|
config = vim.deepcopy(config)
|
||||||
|
|
||||||
for _, marker in ipairs(opts._root_markers) do
|
config.root_dir = vim.fs.root(bufnr, opts._root_markers)
|
||||||
local root = vim.fs.root(bufnr, marker)
|
|
||||||
if root ~= nil then
|
|
||||||
config.root_dir = root
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if
|
if
|
||||||
|
@@ -357,6 +357,36 @@ describe('vim.fs', function()
|
|||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('nested markers have equal priority', function()
|
||||||
|
local bufnr = api.nvim_get_current_buf()
|
||||||
|
eq(
|
||||||
|
vim.fs.joinpath(test_source_path, 'test/functional'),
|
||||||
|
exec_lua(
|
||||||
|
[[return vim.fs.root(..., { 'example_spec.lua', {'CMakeLists.txt', 'CMakePresets.json'}, '.luarc.json'})]],
|
||||||
|
bufnr
|
||||||
|
)
|
||||||
|
)
|
||||||
|
eq(
|
||||||
|
vim.fs.joinpath(test_source_path, 'test/functional/fixtures'),
|
||||||
|
exec_lua(
|
||||||
|
[[return vim.fs.root(..., { {'CMakeLists.txt', 'CMakePresets.json'}, 'example_spec.lua', '.luarc.json'})]],
|
||||||
|
bufnr
|
||||||
|
)
|
||||||
|
)
|
||||||
|
eq(
|
||||||
|
vim.fs.joinpath(test_source_path, 'test/functional/fixtures'),
|
||||||
|
exec_lua(
|
||||||
|
[[return vim.fs.root(..., {
|
||||||
|
function(name, _)
|
||||||
|
return name:match('%.txt$')
|
||||||
|
end,
|
||||||
|
'example_spec.lua',
|
||||||
|
'.luarc.json' })]],
|
||||||
|
bufnr
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
|
||||||
it('works with a function', function()
|
it('works with a function', function()
|
||||||
---@type string
|
---@type string
|
||||||
local result = exec_lua(function()
|
local result = exec_lua(function()
|
||||||
|
Reference in New Issue
Block a user