Merge pull request #34090 from yochem/exrc-search-parent

feat(exrc): unset 'exrc' to stop searching parent directories
This commit is contained in:
Gregory Anders
2025-05-20 12:06:08 -05:00
committed by GitHub
6 changed files with 47 additions and 26 deletions

View File

@@ -123,6 +123,7 @@ DEFAULTS
• 'statusline' default is exposed as a statusline expression (previously it • 'statusline' default is exposed as a statusline expression (previously it
was implemented as an internal C routine). was implemented as an internal C routine).
• Project-local configuration ('exrc') is also loaded from parent directories. • Project-local configuration ('exrc') is also loaded from parent directories.
Unset 'exrc' to stop further search.
DIAGNOSTICS DIAGNOSTICS

View File

@@ -2416,6 +2416,9 @@ A jump table for the options with a short description can be found at |Q_op|.
directories (ordered upwards), if the files are in the |trust| list. directories (ordered upwards), if the files are in the |trust| list.
Use |:trust| to manage trusted files. See also |vim.secure.read()|. Use |:trust| to manage trusted files. See also |vim.secure.read()|.
Unset 'exrc' to stop further searching of 'exrc' files in parent
directories, similar to |editorconfig.root|.
Compare 'exrc' to |editorconfig|: Compare 'exrc' to |editorconfig|:
- 'exrc' can execute any code; editorconfig only specifies settings. - 'exrc' can execute any code; editorconfig only specifies settings.
- 'exrc' is Nvim-specific; editorconfig works in other editors. - 'exrc' is Nvim-specific; editorconfig works in other editors.

View File

@@ -928,13 +928,18 @@ do
vim.api.nvim_create_autocmd('VimEnter', { vim.api.nvim_create_autocmd('VimEnter', {
group = vim.api.nvim_create_augroup('nvim.find_exrc', {}), group = vim.api.nvim_create_augroup('nvim.find_exrc', {}),
desc = 'Find project-local configuration', desc = 'Find exrc files in parent directories',
callback = function() callback = function()
if vim.o.exrc then if not vim.o.exrc then
local files = vim.fs.find( return
{ '.nvim.lua', '.nvimrc', '.exrc' }, end
{ type = 'file', upward = true, limit = math.huge } local files = vim.fs.find({ '.nvim.lua', '.nvimrc', '.exrc' }, {
) type = 'file',
upward = true,
limit = math.huge,
-- exrc in cwd already handled from C, thus start in parent directory.
path = vim.fs.dirname(vim.uv.cwd()),
})
for _, file in ipairs(files) do for _, file in ipairs(files) do
local trusted = vim.secure.read(file) --[[@as string|nil]] local trusted = vim.secure.read(file) --[[@as string|nil]]
if trusted then if trusted then
@@ -944,6 +949,9 @@ do
vim.api.nvim_exec2(trusted, {}) vim.api.nvim_exec2(trusted, {})
end end
end end
-- If the user unset 'exrc' in the current exrc then stop searching
if not vim.o.exrc then
return
end end
end end
end, end,

View File

@@ -2080,6 +2080,9 @@ vim.bo.et = vim.bo.expandtab
--- directories (ordered upwards), if the files are in the `trust` list. --- directories (ordered upwards), if the files are in the `trust` list.
--- Use `:trust` to manage trusted files. See also `vim.secure.read()`. --- Use `:trust` to manage trusted files. See also `vim.secure.read()`.
--- ---
--- Unset 'exrc' to stop further searching of 'exrc' files in parent
--- directories, similar to `editorconfig.root`.
---
--- Compare 'exrc' to `editorconfig`: --- Compare 'exrc' to `editorconfig`:
--- - 'exrc' can execute any code; editorconfig only specifies settings. --- - 'exrc' can execute any code; editorconfig only specifies settings.
--- - 'exrc' is Nvim-specific; editorconfig works in other editors. --- - 'exrc' is Nvim-specific; editorconfig works in other editors.

View File

@@ -2749,6 +2749,9 @@ local options = {
directories (ordered upwards), if the files are in the |trust| list. directories (ordered upwards), if the files are in the |trust| list.
Use |:trust| to manage trusted files. See also |vim.secure.read()|. Use |:trust| to manage trusted files. See also |vim.secure.read()|.
Unset 'exrc' to stop further searching of 'exrc' files in parent
directories, similar to |editorconfig.root|.
Compare 'exrc' to |editorconfig|: Compare 'exrc' to |editorconfig|:
- 'exrc' can execute any code; editorconfig only specifies settings. - 'exrc' can execute any code; editorconfig only specifies settings.
- 'exrc' is Nvim-specific; editorconfig works in other editors. - 'exrc' is Nvim-specific; editorconfig works in other editors.

View File

@@ -1128,6 +1128,10 @@ describe('user config init', function()
end end
before_each(function() before_each(function()
for _, file in ipairs({ '.exrc', '.nvimrc', '.nvim.lua' }) do
os.remove('../' .. file)
os.remove(file)
end
write_file( write_file(
init_lua_path, init_lua_path,
[[ [[
@@ -1139,7 +1143,10 @@ describe('user config init', function()
end) end)
after_each(function() after_each(function()
os.remove(exrc_path) for _, file in ipairs({ '.exrc', '.nvimrc', '.nvim.lua' }) do
os.remove('../' .. file)
os.remove(file)
end
rmdir(xstate) rmdir(xstate)
end) end)
@@ -1188,13 +1195,9 @@ describe('user config init', function()
end) end)
end end
it('exrc from all parent directories', function() it('exrc from parent directories', function()
-- make sure that there are not any exrc files left from previous tests
for _, file in ipairs({ '.exrc', '.nvimrc', '.nvim.lua', '../.nvim.lua', '../.nvimrc' }) do
os.remove(file)
end
setup_exrc_file('../.exrc')
setup_exrc_file('.nvim.lua') setup_exrc_file('.nvim.lua')
setup_exrc_file('../.exrc')
clear { args_rm = { '-u' }, env = xstateenv } clear { args_rm = { '-u' }, env = xstateenv }
local screen = Screen.new(50, 8) local screen = Screen.new(50, 8)
screen._default_attr_ids = nil screen._default_attr_ids = nil
@@ -1206,16 +1209,16 @@ describe('user config init', function()
}) })
-- current directory exrc is found first -- current directory exrc is found first
screen:expect({ any = '.nvim.lua' }) screen:expect({ any = '.nvim.lua' })
screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny, (a)llow:') }) screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny, (a)llow:'), unchanged = true })
feed('ia') feed('ia')
-- after that the exrc in the parent directory -- after that the exrc in the parent directory
screen:expect({ any = '.exrc' }) screen:expect({ any = '.exrc' })
screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny, (a)llow:') }) screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny, (a)llow:'), unchanged = true })
feed('ia') feed('a')
clear { args_rm = { '-u' }, env = xstateenv }
-- a total of 2 exrc files are executed -- a total of 2 exrc files are executed
eq(2, eval('g:exrc_count')) feed(':echo g:exrc_count<CR>')
screen:expect({ any = '2' })
end) end)
end) end)