diff --git a/packages/shared/src/shell.test.ts b/packages/shared/src/shell.test.ts index 89ec055f599e..c6411fa4988f 100644 --- a/packages/shared/src/shell.test.ts +++ b/packages/shared/src/shell.test.ts @@ -122,6 +122,26 @@ describe("readPathFromLaunchctl", () => { }); describe("readEnvironmentFromLoginShell", () => { + it("uses Nushell-compatible syntax for a nu login shell", () => { + const execFile = vi.fn< + ( + file: string, + args: ReadonlyArray, + options: { encoding: "utf8"; timeout: number }, + ) => string + >(() => "__T3CODE_ENV_PATH_START__\n/a:/b\n__T3CODE_ENV_PATH_END__\n"); + + expect(readEnvironmentFromLoginShell("/opt/homebrew/bin/nu", ["PATH"], execFile)).toEqual({ + PATH: "/a:/b", + }); + + const command = execFile.mock.calls[0]?.[1][1]; + expect(command).toBe( + "print '__T3CODE_ENV_PATH_START__'; try { printenv PATH } catch { print '' }; print '__T3CODE_ENV_PATH_END__'", + ); + expect(command).not.toContain("|| true"); + }); + it("extracts multiple environment variables from a login shell command", () => { const execFile = vi.fn< ( diff --git a/packages/shared/src/shell.ts b/packages/shared/src/shell.ts index da6db2166765..e5ca01f0fa58 100644 --- a/packages/shared/src/shell.ts +++ b/packages/shared/src/shell.ts @@ -245,13 +245,28 @@ function envCaptureEnd(name: string): string { return `__T3CODE_ENV_${name}_END__`; } -function buildEnvironmentCaptureCommand(names: ReadonlyArray): string { +function isNushellExecutable(shell: string): boolean { + const executableName = NodePath.basename(shell).toLowerCase(); + return executableName === "nu" || executableName === "nu.exe"; +} + +function buildEnvironmentCaptureCommand(shell: string, names: ReadonlyArray): string { + const isNushell = isNushellExecutable(shell); + return names .map((name) => { if (!SHELL_ENV_NAME_PATTERN.test(name)) { throw new Error(`Unsupported environment variable name: ${name}`); } + if (isNushell) { + return [ + `print '${envCaptureStart(name)}'`, + `try { printenv ${name} } catch { print '' }`, + `print '${envCaptureEnd(name)}'`, + ].join("; "); + } + return [ `printf '%s\\n' '${envCaptureStart(name)}'`, `printenv ${name} || true`, @@ -312,7 +327,7 @@ export const readEnvironmentFromLoginShell: ShellEnvironmentReader = ( return {}; } - const output = execFile(shell, ["-ilc", buildEnvironmentCaptureCommand(names)], { + const output = execFile(shell, ["-ilc", buildEnvironmentCaptureCommand(shell, names)], { encoding: "utf8", timeout: 5000, });