diff --git a/src/bashDebug.spec.ts b/src/bashDebug.spec.ts new file mode 100644 index 0000000..cd2d08e --- /dev/null +++ b/src/bashDebug.spec.ts @@ -0,0 +1,22 @@ +import { createRunInTerminalArgs } from "./bashDebug"; + +describe("bashDebug - createRunInTerminalArgs", () => { + + it("preserves shell interpretation for runInTerminal commands", () => { + + expect(createRunInTerminalArgs("integrated", "wsl.exe", "bash", "while [[ ! -p fifo ]]; do sleep 0.25; done")) + .toEqual({ + kind: "integrated", + title: "Bash Debug Console", + cwd: ".", + args: ["wsl.exe", "bash", "-c", "while [[ ! -p fifo ]]; do sleep 0.25; done"], + argsCanBeInterpretedByShell: true, + }); + }); + + it("omits the extra bash path argument when it is not needed", () => { + + expect(createRunInTerminalArgs("external", "/bin/bash", "", "echo ok").args) + .toEqual(["/bin/bash", "-c", "echo ok"]); + }); +}); diff --git a/src/bashDebug.ts b/src/bashDebug.ts index b27ee92..12db727 100644 --- a/src/bashDebug.ts +++ b/src/bashDebug.ts @@ -36,6 +36,26 @@ export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArgum trace?: boolean; } +interface RunInTerminalRequestArgumentsWithShellInterpretation extends DebugProtocol.RunInTerminalRequestArguments { + argsCanBeInterpretedByShell?: boolean; +} + +export function createRunInTerminalArgs( + kind: 'integrated' | 'external', + currentShell: string, + optionalBashPathArgument: string, + command: string +): RunInTerminalRequestArgumentsWithShellInterpretation { + return { + kind, + title: "Bash Debug Console", + cwd: ".", + args: [currentShell, optionalBashPathArgument, `-c`, command].filter(arg => arg !== ""), + // Keep the -c payload intact so the client does not escape shell operators like '!'. + argsCanBeInterpretedByShell: true, + }; +} + export class BashDebugSession extends LoggingDebugSession { private static THREAD_ID = 42; @@ -164,12 +184,11 @@ export class BashDebugSession extends LoggingDebugSession { else { const currentShell = (process.platform === "win32") ? getWSLLauncherPath(true) : args.pathBash; const optionalBashPathArgument = (currentShell !== args.pathBash) ? args.pathBash : ""; - const termArgs: DebugProtocol.RunInTerminalRequestArguments = { - kind: this.launchArgs.terminalKind, - title: "Bash Debug Console", - cwd: ".", - args: [currentShell, optionalBashPathArgument, `-c`, command].filter(arg => arg !== ""), - }; + const termArgs = createRunInTerminalArgs( + this.launchArgs.terminalKind, + currentShell, + optionalBashPathArgument, + command); this.runInTerminalRequest(termArgs, 10000, (response) => { if (!response.success) {