// // Runs commands in the user's terminal application. // // Nova has no terminal of its own, so anything interactive or long running -- // shells, followed logs, compose output -- is handed to Terminal or iTerm2 // through AppleScript. // const { exec } = require("../Utilities/Process"); class Terminal { // Quotes a single argument for /bin/sh. static quote(argument) { return `'${String(argument).replace(/'/g, `'\\''`)}'`; } // Joins an argument vector into a shell command. static command(parts) { return parts.map((part) => this.quote(part)).join(" "); } static escapeAppleScript(text) { return text.replace(/\\/g, "\\\\").replace(/"/g, '\\"'); } // Opens a new terminal window running the given shell command. static async run(command, cwd) { let full = cwd ? `cd ${this.quote(cwd)} && ${command}` : command; let script = nova.config.get("apple_container.cli.terminal", "string") === "iTerm2" ? this.iTermScript(full) : this.terminalScript(full); return exec("/usr/bin/osascript", ["-e", script]); } static terminalScript(command) { let escaped = this.escapeAppleScript(command); return [ 'tell application "Terminal"', ` do script "${escaped}"`, " activate", "end tell" ].join("\n"); } static iTermScript(command) { let escaped = this.escapeAppleScript(command); return [ 'tell application "iTerm"', " activate", " set newWindow to (create window with default profile)", " tell current session of newWindow", ` write text "${escaped}"`, " end tell", "end tell" ].join("\n"); } } module.exports = { Terminal };