Skip to content

Commit 0489f9d

Browse files
committed
make pwsh path default beahvior
1 parent aad112f commit 0489f9d

File tree

1 file changed

+46
-36
lines changed

1 file changed

+46
-36
lines changed

bin/package-manager-completion.ts

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { RootCommand } from '../src/t.js';
88
const noop = () => {};
99

1010
const isTabDebug = Boolean(process.env.TAB_DEBUG);
11+
const isPowerShellEnv =
12+
process.platform === 'win32' && Boolean(process.env.PSModulePath);
1113

1214
function tabDebugLog(...args: unknown[]) {
1315
if (isTabDebug) {
@@ -38,6 +40,11 @@ function runCompletionCommand(
3840
const args = [...leadingArgs, 'complete', '--', ...safeCompletionArgs];
3941
tabDebugLog('spawn completion:', command, args);
4042

43+
// PowerShell: prefer invoking via powershell.exe so .ps1 shims are resolved.
44+
if (isPowerShellEnv && path.extname(command) === '') {
45+
return runCompletionViaPowerShell(command, args);
46+
}
47+
4148
const result = spawnSync(command, args, completionSpawnOptions);
4249

4350
tabDebugLog('spawn result:', {
@@ -46,46 +53,13 @@ function runCompletionCommand(
4653
stdout: result.stdout,
4754
});
4855

49-
// Windows: npm may only produce a .ps1 shim; spawnSync won't resolve .ps1 via PATHEXT.
50-
// Fallback: invoke through powershell so .ps1 shims (e.g. nuxt.ps1) are discoverable.
56+
// If the direct spawn fails on Windows, retry via PowerShell as a safety net.
5157
if (
5258
getErrnoCode(result.error) === 'ENOENT' &&
53-
process.platform === 'win32' &&
59+
isPowerShellEnv &&
5460
path.extname(command) === ''
5561
) {
56-
const psArgs = args.map(powerShellQuote);
57-
const psCommand = `& ${command} ${psArgs.join(' ')}`.trimEnd();
58-
59-
tabDebugLog('powershell fallback:', psCommand);
60-
61-
const psResult = spawnSync(
62-
'powershell.exe',
63-
[
64-
'-NoLogo',
65-
'-NoProfile',
66-
'-ExecutionPolicy',
67-
'Bypass',
68-
'-Command',
69-
psCommand,
70-
],
71-
completionSpawnOptions
72-
);
73-
74-
tabDebugLog('powershell fallback result:', {
75-
status: psResult.status,
76-
error: psResult.error?.message,
77-
stdout: psResult.stdout,
78-
});
79-
80-
if (psResult.error) {
81-
throw psResult.error;
82-
}
83-
if (typeof psResult.status === 'number' && psResult.status !== 0) {
84-
throw new Error(
85-
`Completion command "${command}" (PowerShell fallback) exited with code ${psResult.status}`
86-
);
87-
}
88-
return (psResult.stdout ?? '').trim();
62+
return runCompletionViaPowerShell(command, args);
8963
}
9064

9165
if (result.error) {
@@ -106,6 +80,42 @@ function powerShellQuote(value: string): string {
10680
return `'${value.replace(/'/g, "''")}'`;
10781
}
10882

83+
function runCompletionViaPowerShell(command: string, args: string[]): string {
84+
const psArgs = args.map(powerShellQuote);
85+
const psCommand = `& ${command} ${psArgs.join(' ')}`.trimEnd();
86+
87+
tabDebugLog('powershell exec:', psCommand);
88+
89+
const psResult = spawnSync(
90+
'powershell.exe',
91+
[
92+
'-NoLogo',
93+
'-NoProfile',
94+
'-ExecutionPolicy',
95+
'Bypass',
96+
'-Command',
97+
psCommand,
98+
],
99+
completionSpawnOptions
100+
);
101+
102+
tabDebugLog('powershell exec result:', {
103+
status: psResult.status,
104+
error: psResult.error?.message,
105+
stdout: psResult.stdout,
106+
});
107+
108+
if (psResult.error) {
109+
throw psResult.error;
110+
}
111+
if (typeof psResult.status === 'number' && psResult.status !== 0) {
112+
throw new Error(
113+
`Completion command "${command}" (PowerShell) exited with code ${psResult.status}`
114+
);
115+
}
116+
return (psResult.stdout ?? '').trim();
117+
}
118+
109119
function getErrnoCode(error: unknown): string | undefined {
110120
if (error && typeof error === 'object' && 'code' in error) {
111121
const candidate = (error as { code?: unknown }).code;

0 commit comments

Comments
 (0)