Skip to content

Commit

Permalink
Merge pull request #312 from danielpinto8zz6/feature/runner-improvements
Browse files Browse the repository at this point in the history
Feature/runner improvements
  • Loading branch information
danielpinto8zz6 authored Feb 16, 2023
2 parents 7200d24 + b1f5470 commit 9d08487
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 228 deletions.
7 changes: 7 additions & 0 deletions src/enums/shell-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export enum ShellType {
cmd = "Command Prompt",
powerShell = "PowerShell",
gitBash = "Git Bash",
wsl = "WSL Bash",
others = "Others"
}
87 changes: 87 additions & 0 deletions src/external-terminal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { exec } from "child_process";
import { lookpath } from "lookpath";
import { Configuration } from "./configuration";
import { ShellType } from "./enums/shell-type";
import { Notification } from "./notification";
import { terminal } from "./terminal";
import { getPath } from "./utils/shell-utils";
import { escapeStringAppleScript, isStringNullOrWhiteSpace } from "./utils/string-utils";

class ExternalTerminal {
public async runInExternalTerminal(command: string, cwd: string, shell: ShellType) {
const parsedOutputLocation = await getPath(cwd, shell);

const externalCommand = await this.getExternalCommand(command, parsedOutputLocation, shell);
if (isStringNullOrWhiteSpace(externalCommand)) {
return;
}

exec(externalCommand, { cwd: cwd });
}

private async getExternalCommand(runCommand: string, outputLocation: string, shell: ShellType): Promise<string> {
switch (process.platform) {
case "win32":
switch (shell) {
case ShellType.powerShell:
const winTerminal: string = Configuration.winTerminal();
return `start ${winTerminal} -Command "cd ${outputLocation};${runCommand};Write-Host;Write-Host -NoNewLine 'Press any key to continue...';$Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');"`;
default:
return `start cmd /c "cd ${outputLocation} & ${runCommand} & echo. & pause"`;
}

case "darwin":
const osxTerminal: string = Configuration.osxTerminal();
switch (osxTerminal) {
case "iTerm.app":
return "osascript -e 'tell application \"iTerm\"' "
+ "-e 'set newWindow to (create window with default profile)' "
+ "-e 'tell current session of newWindow' "
+ `-e 'write text "cd ${escapeStringAppleScript(outputLocation)}"' `
+ `-e 'write text "${escapeStringAppleScript(runCommand)}"' `
+ "-e 'end tell' "
+ "-e 'end tell' ";
default:
return `osascript -e 'do shell script "open -a Terminal " & "${escapeStringAppleScript(outputLocation)}"' -e 'delay 0.3' -e `
+ `'tell application "Terminal" to do script ("${escapeStringAppleScript(runCommand)}") in first window'`;
}

case "linux":
const linuxTerminal: string = Configuration.linuxTerminal();

if (isStringNullOrWhiteSpace(linuxTerminal)
|| isStringNullOrWhiteSpace(await lookpath(linuxTerminal))) {
Notification.showErrorMessage(`${terminal} not found! Try to enter a valid terminal in 'terminal.external.linuxExec' `
+ "settings!(gnome - terminal, xterm, konsole)");

return null;
}

switch (linuxTerminal) {
case "xterm":
return `${linuxTerminal} -T 'C/C++ Compile Run' -e '${runCommand}; echo; read -n1 -p \"Press any key to continue...\"'`;
case "gnome-terminal":
case "tilix":
case "mate-terminal":
return `${linuxTerminal} -t 'C/C++ Compile Run' -x bash -c '${runCommand}; echo; read -n1 -p \"Press any key to continue...\"'`;
case "xfce4-terminal":
return `${linuxTerminal} --title 'C/C++ Compile Run' -x bash -c '${runCommand}; echo; read -n1 -p \"Press any key to continue...\"'`;
case "konsole":
return `${linuxTerminal} -p tabtitle='C/C++ Compile Run' --noclose -e bash -c '${runCommand}; echo;'`;
case "io.elementary.terminal":
return `${linuxTerminal} -n -w '${outputLocation}' -x '${runCommand}'`;
default:
Notification.showErrorMessage(`${linuxTerminal} isn't supported! Try to enter a supported terminal in `
+ "'terminal.external.linuxExec' settings! (gnome-terminal, xterm, konsole)");

return null;
}
default:
Notification.showErrorMessage("Unsupported platform!");

return null;
}
}
}

export const externalTerminal: ExternalTerminal = new ExternalTerminal();
118 changes: 34 additions & 84 deletions src/runner.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { exec } from "child_process";
import { existsSync } from "fs";
import { lookpath } from "lookpath";
import { File } from "./models/file";
import { terminal, getRunPrefix } from "./terminal";
import { promptRunArguments } from "./utils/prompt-utils";
import { escapeStringAppleScript, isStringNullOrWhiteSpace } from "./utils/string-utils";
import { Configuration } from "./configuration";
import { ShellType } from "./enums/shell-type";
import { File } from "./models/file";
import { Notification } from "./notification";
import { terminal } from "./terminal";
import { promptRunArguments } from "./utils/prompt-utils";
import { currentShell, getPath, getRunPrefix, parseShell } from "./utils/shell-utils";
import { isStringNullOrWhiteSpace } from "./utils/string-utils";
import path = require("path");
import { basename } from "path";
import { externalTerminal } from "./external-terminal";

export class Runner {
private file: File;
Expand Down Expand Up @@ -37,96 +40,43 @@ export class Runner {

let customPrefix = Configuration.customRunPrefix();

const runCommand = this.buildRunCommand(this.file.executable, args, customPrefix);
const shell = this.getShell(shouldRunInExternalTerminal);

if (shouldRunInExternalTerminal) {
const command = await this.getExternalCommand(runCommand, outputLocation);
if (isStringNullOrWhiteSpace(command)) {
return;
}
const parsedExecutable = await getPath(this.file.executable, shell);

exec(command, { cwd: outputLocation });
const runCommand = this.getRunCommand(parsedExecutable, args, customPrefix, shell);

if (shouldRunInExternalTerminal) {
await externalTerminal.runInExternalTerminal(runCommand, outputLocation, shell);
}
else {
await terminal.runInTerminal(runCommand, { name: "C/C++ Compile Run", cwd: outputLocation });
}
}

private async getExternalCommand(runCommand: string, outputLocation: string): Promise<string> {
switch (process.platform) {
case "win32":
const winTerminal: string = Configuration.winTerminal();
switch (winTerminal) {
case "pwsh.exe":
case "powershell.exe":
return `start ${winTerminal} -Command "Set-Location '${outputLocation}';${runCommand};Write-Host;Write-Host -NoNewLine 'Press any key to continue...';$Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');"`;
default:
return `start cmd /c "cd "${outputLocation}" & ${runCommand} & echo. & pause"`;
}

case "darwin":
const osxTerminal: string = Configuration.osxTerminal();
switch (osxTerminal) {
case "iTerm.app":
return "osascript -e 'tell application \"iTerm\"' "
+ "-e 'set newWindow to (create window with default profile)' "
+ "-e 'tell current session of newWindow' "
+ `-e 'write text "cd ${outputLocation}"' `
+ `-e 'write text "${escapeStringAppleScript(runCommand)}"' `
+ "-e 'end tell' "
+ "-e 'end tell' ";
default:
return `osascript -e 'do shell script "open -a Terminal " & "${outputLocation}"' -e 'delay 0.3' -e `
+ `'tell application "Terminal" to do script ("${escapeStringAppleScript(runCommand)}") in first window'`;
}

case "linux":
const linuxTerminal: string = Configuration.linuxTerminal();

if (isStringNullOrWhiteSpace(linuxTerminal)
|| isStringNullOrWhiteSpace(await lookpath(linuxTerminal))) {
Notification.showErrorMessage(`${terminal} not found! Try to enter a valid terminal in 'terminal.external.linuxExec' `
+ "settings!(gnome - terminal, xterm, konsole)");

return null;
}

switch (linuxTerminal) {
case "xterm":
return `${linuxTerminal} -T '${this.file.title}' -e '${runCommand}; echo; read -n1 -p \"Press any key to continue...\"'`;
case "gnome-terminal":
case "tilix":
case "mate-terminal":
return `${linuxTerminal} -t '${this.file.title}' -x bash -c '${runCommand}; echo; read -n1 -p \"Press any key to continue...\"'`;
case "xfce4-terminal":
return `${linuxTerminal} --title '${this.file.title}' -x bash -c '${runCommand}; echo; read -n1 -p \"Press any key to continue...\"'`;
case "konsole":
return `${linuxTerminal} -p tabtitle='${this.file.title}' --noclose -e bash -c '${runCommand}; echo;'`;
case "io.elementary.terminal":
return `${linuxTerminal} -n -w '${outputLocation}' -x '${runCommand}'`;
default:
Notification.showErrorMessage(`${linuxTerminal} isn't supported! Try to enter a supported terminal in `
+ "'terminal.external.linuxExec' settings! (gnome-terminal, xterm, konsole)");

return null;
}
default:
Notification.showErrorMessage("Unsupported platform!");

return null;
}
}
getRunCommand(executable: string, args: string, customPrefix: string, shell: ShellType) {
const prefix = getRunPrefix(shell);

buildRunCommand(executable: string, args: string, customPrefix: string) {
const winTerminal: string = Configuration.winTerminal();
const isPowershell = process.platform === "win32" && (winTerminal === "powershell.exe" || winTerminal === "pwsh.exe");
const prefix = process.platform === "win32" ? ".\\" : "./";
const executableEscaped = isPowershell ? `'${executable}'` : JSON.stringify(executable);

if (customPrefix) {
return [customPrefix, " ", prefix, executableEscaped, " ", args].join("").trim();
return [customPrefix, " ", prefix, executable, " ", args].join("").trim();
}

return [prefix, executableEscaped, " ", args].join("").trim();
return [prefix, executable, " ", args].join("").trim();
}

getShell(runInExternalTerminal: boolean): ShellType {
if (runInExternalTerminal) {
switch (process.platform) {
case "win32":
const terminal = basename(Configuration.winTerminal());
return parseShell(terminal);
default:
return ShellType.others;
}
} else {
return currentShell();
}
}
}


Loading

0 comments on commit 9d08487

Please sign in to comment.