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. 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 ### Using `gdbserver` for remote debugging
You can also connect to a gdbserver instance and debug using that. For that modify the You can also connect to a gdbserver instance and debug using that. For that modify the

View file

@ -49,6 +49,10 @@
"type": "string", "type": "string",
"description": "Arguments to append after the executable. You can also use pipes." "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": { "cwd": {
"type": "string", "type": "string",
"description": "Path of project" "description": "Path of project"
@ -187,4 +191,4 @@
"typescript": "^1.7.5", "typescript": "^1.7.5",
"vscode": "0.11.x" "vscode": "0.11.x"
} }
} }

View file

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

View file

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