Added support to run process in a separate console (fix #28)

This commit is contained in:
WebFreak001 2016-02-23 17:26:12 +01:00
commit 30731c2ba1
6 changed files with 64 additions and 12 deletions

View file

@ -54,6 +54,11 @@ path for GDB to find the debug symbols.
This will attach to PID 4285 which should already run. GDB will pause the program on entering.
Additionally you can set `terminal` if you want to run the program in a separate terminal with
support for input. On Windows set it to an empty string (`""`) to enable this feature. On linux
set it to an empty string (`""`) to use the default terminal emulator specified with `x-terminal-emulator`
or specify a custom one. Note that it must support the `-e` argument.
### Using `gdbserver` for remote debugging
You can also connect to a gdbserver instance and debug using that. For that modify the

View file

@ -49,6 +49,10 @@
"type": "string",
"description": "Arguments to append after the executable. You can also use pipes."
},
"terminal": {
"type": "string",
"description": "Leave this field undefined to keep program output in the vscode console at the bottom. If this is set to empty string the program will spawn in a new console using x-terminal-emulator on linux, otherwise with the specified terminal. On windows setting this to an empty string spawns the program in a console, but no other console is supported."
},
"cwd": {
"type": "string",
"description": "Path of project"
@ -187,4 +191,4 @@
"typescript": "^1.7.5",
"vscode": "0.11.x"
}
}
}

View file

@ -28,8 +28,8 @@ export interface SSHArguments {
}
export interface IBackend {
load(cwd: string, target: string, procArgs: string): Thenable<any>;
ssh(args: SSHArguments, cwd: string, target: string, procArgs: string): Thenable<any>;
load(cwd: string, target: string, procArgs: string, separateConsole: string): Thenable<any>;
ssh(args: SSHArguments, cwd: string, target: string, procArgs: string, separateConsole: string): Thenable<any>;
attach(cwd: string, executable: string, target: string): Thenable<any>;
connect(cwd: string, executable: string, target: string): Thenable<any>;
start(): Thenable<boolean>;

View file

@ -0,0 +1,21 @@
import * as ChildProcess from "child_process"
import * as fs from "fs"
export function spawnTerminalEmulator(preferedEmulator: string): Thenable<string> {
return new Promise((resolve, reject) => {
let ttyFileOutput = "/tmp/vscode-gdb-tty-0" + Math.floor(Math.random() * 100000000).toString(36);
ChildProcess.spawn(preferedEmulator || "x-terminal-emulator", ["-e", "sh -c \"tty > " + ttyFileOutput + " && sleep 4294967294\""]);
let it = 0;
let interval = setInterval(() => {
if (fs.existsSync(ttyFileOutput)) {
clearInterval(interval);
let tty = fs.readFileSync(ttyFileOutput).toString("utf8");
fs.unlink(ttyFileOutput);
return resolve(tty);
}
it++;
if (it > 500)
reject();
}, 10);
});
}

View file

@ -2,6 +2,7 @@ import { Breakpoint, IBackend, Stack, SSHArguments } from "../backend.ts"
import * as ChildProcess from "child_process"
import { EventEmitter } from "events"
import { parseMI, MINode } from '../mi_parse';
import * as linuxTerm from '../linux/console';
import * as net from "net"
import * as fs from "fs"
import { posix } from "path"
@ -26,7 +27,7 @@ export class MI2 extends EventEmitter implements IBackend {
super();
}
load(cwd: string, target: string, procArgs: string): Thenable<any> {
load(cwd: string, target: string, procArgs: string, separateConsole: string): Thenable<any> {
if (!nativePath.isAbsolute(target))
target = nativePath.join(cwd, target);
return new Promise((resolve, reject) => {
@ -41,14 +42,35 @@ export class MI2 extends EventEmitter implements IBackend {
];
if (procArgs && procArgs.length)
promises.push(this.sendCommand("exec-arguments " + procArgs));
Promise.all(promises).then(() => {
this.emit("debug-ready")
resolve();
}, reject);
if (process.platform == "win32") {
if (separateConsole !== undefined)
promises.push(this.sendCommand("gdb-set new-console on"))
Promise.all(promises).then(() => {
this.emit("debug-ready")
resolve();
}, reject);
}
else {
if (separateConsole !== undefined) {
linuxTerm.spawnTerminalEmulator(separateConsole).then(tty => {
promises.push(this.sendCommand("inferior-tty-set " + tty));
Promise.all(promises).then(() => {
this.emit("debug-ready")
resolve();
}, reject);
});
}
else {
Promise.all(promises).then(() => {
this.emit("debug-ready")
resolve();
}, reject);
}
}
});
}
ssh(args: SSHArguments, cwd: string, target: string, procArgs: string): Thenable<any> {
ssh(args: SSHArguments, cwd: string, target: string, procArgs: string, separateConsole: string): Thenable<any> {
return new Promise((resolve, reject) => {
this.isSSH = true;
this.sshReady = false;

View file

@ -14,6 +14,7 @@ export interface LaunchRequestArguments {
cwd: string;
target: string;
arguments: string;
terminal: string;
autorun: string[];
ssh: SSHArguments;
printCalls: boolean;
@ -110,7 +111,7 @@ class MI2DebugSession extends DebugSession {
this.isSSH = true;
this.trimCWD = args.cwd.replace(/\\/g, "/");
this.switchCWD = args.ssh.cwd;
this.gdbDebugger.ssh(args.ssh, args.ssh.cwd, args.target, args.arguments).then(() => {
this.gdbDebugger.ssh(args.ssh, args.ssh.cwd, args.target, args.arguments, args.terminal).then(() => {
if (args.autorun)
args.autorun.forEach(command => {
this.gdbDebugger.sendUserInput(command);
@ -121,7 +122,7 @@ class MI2DebugSession extends DebugSession {
});
}
else {
this.gdbDebugger.load(args.cwd, args.target, args.arguments).then(() => {
this.gdbDebugger.load(args.cwd, args.target, args.arguments, args.terminal).then(() => {
if (args.autorun)
args.autorun.forEach(command => {
this.gdbDebugger.sendUserInput(command);
@ -357,7 +358,6 @@ class MI2DebugSession extends DebugSession {
}
protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void {
this.handleMsg("console", "Evaluate (" + args.context + "): " + args.expression + "\n")
if (args.context == "watch" || args.context == "hover")
this.gdbDebugger.evalExpression(args.expression).then((res) => {
response.body = {