commit 4eebc46930008d7cf47491121556ee201e1f4860
parent e91224bfaa043bb85cdfa6394f417e400522ff53
Author: Lewis Russell <lewis6991@gmail.com>
Date: Wed, 2 Jul 2025 12:08:48 +0100
fix(vim.system): env=nil passes env=nil to uv.spawn
731e616a79 made it so passing `{env = nil, clear_env = true }` would
pass `{env = {}}` to `vim.uv.spawn`.
However this is not what `clear_env` is (arguably) supposed to do.
If `env=nil` then that implies the uses wants `vim.uv.spawn()` to use
the default environment. Adding `clear_env = true` simply prevents
`NVIM` (the base environment) from being added.
Fixes #34730
Diffstat:
4 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
@@ -1785,7 +1785,9 @@ vim.system({cmd}, {opts}, {on_exit}) *vim.system()*
the new process. Inherits the current environment with
`NVIM` set to |v:servername|.
• clear_env: (boolean) `env` defines the job environment
- exactly, instead of merging current environment.
+ exactly, instead of merging current environment. Note: if
+ `env` is `nil`, the current environment is used but
+ without `NVIM` set.
• stdin: (string|string[]|boolean) If `true`, then a pipe
to stdin is opened and can be written to via the
`write()` method to SystemObj. If string or string[] then
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
@@ -106,7 +106,7 @@ local utfs = {
--- - env: table<string,string> Set environment variables for the new process. Inherits the
--- current environment with `NVIM` set to |v:servername|.
--- - clear_env: (boolean) `env` defines the job environment exactly, instead of merging current
---- environment.
+--- environment. Note: if `env` is `nil`, the current environment is used but without `NVIM` set.
--- - stdin: (string|string[]|boolean) If `true`, then a pipe to stdin is opened and can be written
--- to via the `write()` method to SystemObj. If string or string[] then will be written to stdin
--- and closed. Defaults to `false`.
diff --git a/runtime/lua/vim/_system.lua b/runtime/lua/vim/_system.lua
@@ -208,13 +208,18 @@ end
--- @param clear_env? boolean
--- @return string[]?
local function setup_env(env, clear_env)
+ if not env and clear_env then
+ return
+ end
+
+ env = env or {}
if not clear_env then
--- @type table<string,string|number>
- env = vim.tbl_extend('force', base_env(), env or {})
+ env = vim.tbl_extend('force', base_env(), env)
end
local renv = {} --- @type string[]
- for k, v in pairs(env or {}) do
+ for k, v in pairs(env) do
renv[#renv + 1] = string.format('%s=%s', k, tostring(v))
end
diff --git a/test/functional/lua/system_spec.lua b/test/functional/lua/system_spec.lua
@@ -93,6 +93,27 @@ describe('vim.system', function()
)
end)
+ it('can set environment with clear_env = true and env = nil', function()
+ exec_lua(function()
+ vim.env.TEST = 'TESTVAL'
+ end)
+
+ -- Not passing env with clear_env should not clear the environment
+ eq(
+ 'TESTVAL',
+ system({ n.testprg('printenv-test'), 'TEST' }, { clear_env = true, text = true }).stdout
+ )
+
+ -- Passing env = {} with clear_env should clear the environment
+ eq(
+ '',
+ system(
+ { n.testprg('printenv-test'), 'TEST' },
+ { env = {}, clear_env = true, text = true }
+ ).stdout
+ )
+ end)
+
it('supports timeout', function()
eq({
code = 124,