Skip to content

Commit cadd271

Browse files
committed
fix(shared): hydrate PATH with Nushell login shells
1 parent 11f0513 commit cadd271

2 files changed

Lines changed: 34 additions & 3 deletions

File tree

‎packages/shared/src/shell.test.ts‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,26 @@ describe("readPathFromLaunchctl", () => {
122122
});
123123

124124
describe("readEnvironmentFromLoginShell", () => {
125+
it("uses Nushell-compatible syntax for a nu login shell", () => {
126+
const execFile = vi.fn<
127+
(
128+
file: string,
129+
args: ReadonlyArray<string>,
130+
options: { encoding: "utf8"; timeout: number },
131+
) => string
132+
>(() => "__T3CODE_ENV_PATH_START__\n/a:/b\n__T3CODE_ENV_PATH_END__\n");
133+
134+
expect(readEnvironmentFromLoginShell("/opt/homebrew/bin/nu", ["PATH"], execFile)).toEqual({
135+
PATH: "/a:/b",
136+
});
137+
138+
const command = execFile.mock.calls[0]?.[1][1];
139+
expect(command).toContain("do --ignore-errors { printenv PATH }");
140+
expect(command).not.toContain("|| true");
141+
expect(command).toContain("__T3CODE_ENV_PATH_START__");
142+
expect(command).toContain("__T3CODE_ENV_PATH_END__");
143+
});
144+
125145
it("extracts multiple environment variables from a login shell command", () => {
126146
const execFile = vi.fn<
127147
(

‎packages/shared/src/shell.ts‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,16 +245,27 @@ function envCaptureEnd(name: string): string {
245245
return `__T3CODE_ENV_${name}_END__`;
246246
}
247247

248-
function buildEnvironmentCaptureCommand(names: ReadonlyArray<string>): string {
248+
function isNushellExecutable(shell: string): boolean {
249+
const executableName = NodePath.basename(shell).toLowerCase();
250+
return executableName === "nu" || executableName === "nu.exe";
251+
}
252+
253+
function buildEnvironmentCaptureCommand(shell: string, names: ReadonlyArray<string>): string {
254+
const isNushell = isNushellExecutable(shell);
255+
249256
return names
250257
.map((name) => {
251258
if (!SHELL_ENV_NAME_PATTERN.test(name)) {
252259
throw new Error(`Unsupported environment variable name: ${name}`);
253260
}
254261

262+
const readVariable = isNushell
263+
? `do --ignore-errors { printenv ${name} }`
264+
: `printenv ${name} || true`;
265+
255266
return [
256267
`printf '%s\\n' '${envCaptureStart(name)}'`,
257-
`printenv ${name} || true`,
268+
readVariable,
258269
`printf '%s\\n' '${envCaptureEnd(name)}'`,
259270
].join("; ");
260271
})
@@ -312,7 +323,7 @@ export const readEnvironmentFromLoginShell: ShellEnvironmentReader = (
312323
return {};
313324
}
314325

315-
const output = execFile(shell, ["-ilc", buildEnvironmentCaptureCommand(names)], {
326+
const output = execFile(shell, ["-ilc", buildEnvironmentCaptureCommand(shell, names)], {
316327
encoding: "utf8",
317328
timeout: 5000,
318329
});

0 commit comments

Comments
 (0)