aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Anders <8965202+gpanders@users.noreply.github.com>2024-05-24 10:48:32 -0500
committerGitHub <noreply@github.com>2024-05-24 10:48:32 -0500
commit206f8f24a2470f961cfe7e7c177443c0f199231c (patch)
treefa4f59e706ba64b511a105135be5312bd21e37b0
parente71713ba2b5cb4e3b725d162b2dd43e35975eead (diff)
downloadrneovim-206f8f24a2470f961cfe7e7c177443c0f199231c.tar.gz
rneovim-206f8f24a2470f961cfe7e7c177443c0f199231c.tar.bz2
rneovim-206f8f24a2470f961cfe7e7c177443c0f199231c.zip
fix(fs): make vim.fs.root work for relative paths and unnamed buffers (#28964)
If a buffer does not have a backing file then fall back to the current working directory.
-rw-r--r--runtime/doc/lua.txt8
-rw-r--r--runtime/lua/vim/fs.lua21
-rw-r--r--test/functional/lua/fs_spec.lua19
3 files changed, 39 insertions, 9 deletions
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index fccda177d2..3d8453c5a2 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -3012,7 +3012,10 @@ vim.fs.parents({start}) *vim.fs.parents()*
vim.fs.root({source}, {marker}) *vim.fs.root()*
Find the first parent directory containing a specific "marker", relative
- to a buffer's directory.
+ to a file path or buffer.
+
+ If the buffer is unnamed (has no backing file) or has a non-empty
+ 'buftype' then the search begins from Nvim's |current-directory|.
Example: >lua
-- Find the root of a Python project, starting from file 'main.py'
@@ -3029,7 +3032,8 @@ vim.fs.root({source}, {marker}) *vim.fs.root()*
Parameters: ~
• {source} (`integer|string`) Buffer number (0 for current buffer) or
- file path to begin the search from.
+ file path (absolute or relative to the |current-directory|)
+ to begin the search from.
• {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
diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua
index ce533ad0a9..b05220ee2c 100644
--- a/runtime/lua/vim/fs.lua
+++ b/runtime/lua/vim/fs.lua
@@ -328,8 +328,11 @@ function M.find(names, opts)
return matches
end
---- Find the first parent directory containing a specific "marker", relative to a buffer's
---- directory.
+--- Find the first parent directory containing a specific "marker", relative to a file path or
+--- buffer.
+---
+--- If the buffer is unnamed (has no backing file) or has a non-empty 'buftype' then the search
+--- begins from Nvim's |current-directory|.
---
--- Example:
---
@@ -346,13 +349,13 @@ end
--- end)
--- ```
---
---- @param source integer|string Buffer number (0 for current buffer) or file path to begin the
---- search from.
+--- @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.
--- @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.
+--- found.
function M.root(source, marker)
assert(source, 'missing required argument: source')
assert(marker, 'missing required argument: marker')
@@ -361,14 +364,18 @@ function M.root(source, marker)
if type(source) == 'string' then
path = source
elseif type(source) == 'number' then
- path = vim.api.nvim_buf_get_name(source)
+ if vim.bo[source].buftype ~= '' then
+ path = assert(vim.uv.cwd())
+ else
+ path = vim.api.nvim_buf_get_name(source)
+ end
else
error('invalid type for argument "source": expected string or buffer number')
end
local paths = M.find(marker, {
upward = true,
- path = path,
+ path = vim.fn.fnamemodify(path, ':p:h'),
})
if #paths == 0 then
diff --git a/test/functional/lua/fs_spec.lua b/test/functional/lua/fs_spec.lua
index b651297db3..aba02ab01b 100644
--- a/test/functional/lua/fs_spec.lua
+++ b/test/functional/lua/fs_spec.lua
@@ -310,6 +310,25 @@ describe('vim.fs', function()
it('works with a filename argument', function()
eq(test_source_path, exec_lua([[return vim.fs.root(..., '.git')]], nvim_prog))
end)
+
+ it('works with a relative path', function()
+ eq(
+ test_source_path,
+ exec_lua([[return vim.fs.root(..., '.git')]], vim.fs.basename(nvim_prog))
+ )
+ end)
+
+ it('uses cwd for unnamed buffers', function()
+ command('new')
+ eq(test_source_path, exec_lua([[return vim.fs.root(0, '.git')]]))
+ end)
+
+ it("uses cwd for buffers with non-empty 'buftype'", function()
+ command('new')
+ command('set buftype=nofile')
+ command('file lua://')
+ eq(test_source_path, exec_lua([[return vim.fs.root(0, '.git')]]))
+ end)
end)
describe('joinpath()', function()