From b9d64021194e4773b4f90a74e7de414641276960 Mon Sep 17 00:00:00 2001 From: Abdelrahman AL MAROUK Date: Wed, 20 Aug 2025 13:53:01 +0200 Subject: [PATCH 1/2] Improve shell command formatting Consolidates shell command formatting logic into a shared utility function that is used for running in terminal and PET command execution, among other places --- src/extension.ts | 18 +++++++++++----- src/features/execution/execUtils.ts | 1 + src/features/terminal/runInTerminal.ts | 21 +++---------------- .../terminal/shells/common/shellUtils.ts | 3 ++- 4 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 22b2f658..eac758f5 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -19,6 +19,7 @@ import { } from './common/window.apis'; import { getConfiguration } from './common/workspace.apis'; import { createManagerReady } from './features/common/managerReady'; +import { identifyTerminalShell } from './features/common/shellDetector'; import { AutoFindProjects } from './features/creators/autoFindProjects'; import { ExistingProjects } from './features/creators/existingProjects'; import { NewPackageProject } from './features/creators/newPackageProject'; @@ -49,7 +50,7 @@ import { PythonProjectManagerImpl } from './features/projectManager'; import { getPythonApi, setPythonApi } from './features/pythonApi'; import { registerCompletionProvider } from './features/settings/settingCompletions'; import { setActivateMenuButtonContext } from './features/terminal/activateMenuButton'; -import { normalizeShellPath } from './features/terminal/shells/common/shellUtils'; +import { getShellCommandAsString, normalizeShellPath } from './features/terminal/shells/common/shellUtils'; import { clearShellProfileCache, createShellEnvProviders, @@ -435,6 +436,7 @@ export async function activate(context: ExtensionContext): Promise { try { const petPath = await getNativePythonToolsPath(); + let command: { subcommand: string; args?: string[] } | undefined; // Show quick pick menu for PET operation selection const selectedOption = await window.showQuickPick( @@ -467,8 +469,7 @@ export async function activate(context: ExtensionContext): Promise= 0 && !(arg.startsWith('"') && arg.endsWith('"'))) { return `"${arg}"`; } diff --git a/src/features/terminal/runInTerminal.ts b/src/features/terminal/runInTerminal.ts index 24ac7eb3..661474ac 100644 --- a/src/features/terminal/runInTerminal.ts +++ b/src/features/terminal/runInTerminal.ts @@ -2,9 +2,8 @@ import { Terminal, TerminalShellExecution } from 'vscode'; import { PythonEnvironment, PythonTerminalExecutionOptions } from '../../api'; import { createDeferred } from '../../common/utils/deferred'; import { onDidEndTerminalShellExecution } from '../../common/window.apis'; -import { ShellConstants } from '../common/shellConstants'; import { identifyTerminalShell } from '../common/shellDetector'; -import { quoteArgs } from '../execution/execUtils'; +import { getShellCommandAsString } from './shells/common/shellUtils'; export async function runInTerminal( environment: PythonEnvironment, @@ -29,25 +28,11 @@ export async function runInTerminal( } }); - const shouldSurroundWithQuotes = - executable.includes(' ') && !executable.startsWith('"') && !executable.endsWith('"'); - // Handle case where executable contains white-spaces. - if (shouldSurroundWithQuotes) { - executable = `"${executable}"`; - } - - if (shellType === ShellConstants.PWSH && !executable.startsWith('&')) { - // PowerShell requires commands to be prefixed with '&' to run them. - executable = `& ${executable}`; - } + executable = getShellCommandAsString(shellType, [{ executable }]); execution = terminal.shellIntegration.executeCommand(executable, allArgs); await deferred.promise; } else { - let text = quoteArgs([executable, ...allArgs]).join(' '); - if (shellType === ShellConstants.PWSH && !text.startsWith('&')) { - // PowerShell requires commands to be prefixed with '&' to run them. - text = `& ${text}`; - } + const text = getShellCommandAsString(shellType, [{ executable, args: allArgs }]); terminal.sendText(`${text}\n`); } } diff --git a/src/features/terminal/shells/common/shellUtils.ts b/src/features/terminal/shells/common/shellUtils.ts index 95e6f71a..837c721c 100644 --- a/src/features/terminal/shells/common/shellUtils.ts +++ b/src/features/terminal/shells/common/shellUtils.ts @@ -6,12 +6,13 @@ import { ShellConstants } from '../../../common/shellConstants'; import { quoteArgs } from '../../../execution/execUtils'; function getCommandAsString(command: PythonCommandRunConfiguration[], shell: string, delimiter: string): string { - const parts = []; + let parts = []; for (const cmd of command) { const args = cmd.args ?? []; parts.push(quoteArgs([normalizeShellPath(cmd.executable, shell), ...args]).join(' ')); } if (shell === ShellConstants.PWSH) { + parts = parts.map((p) => (p.startsWith('"') ? `& ${p}` : p)); if (parts.length === 1) { return parts[0]; } From 0390029e87943e9af66adaaf2e97b1295c696e43 Mon Sep 17 00:00:00 2001 From: Abdelrahman AL MAROUK Date: Fri, 22 Aug 2025 08:22:47 +0200 Subject: [PATCH 2/2] remove default parameter from function call --- src/extension.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension.ts b/src/extension.ts index eac758f5..a18ea41c 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -497,7 +497,7 @@ export async function activate(context: ExtensionContext): Promise