1、实现将程序输入输出默认绑定在ide终端中
This commit is contained in:
parent
a18e33c0a1
commit
47047adc06
|
@ -106,8 +106,8 @@ export class MI2 extends EventEmitter implements IBackend {
|
||||||
resolve(undefined);
|
resolve(undefined);
|
||||||
}, reject);
|
}, reject);
|
||||||
} else {
|
} else {
|
||||||
if (separateConsole !== undefined) {
|
if (separateConsole === 'external') {
|
||||||
linuxTerm.spawnTerminalEmulator(separateConsole).then(tty => {
|
linuxTerm.spawnTerminalEmulator('').then(tty => {
|
||||||
promises.push(this.sendCommand("inferior-tty-set " + tty));
|
promises.push(this.sendCommand("inferior-tty-set " + tty));
|
||||||
Promise.all(promises).then(() => {
|
Promise.all(promises).then(() => {
|
||||||
this.emit("debug-ready");
|
this.emit("debug-ready");
|
||||||
|
@ -116,7 +116,9 @@ export class MI2 extends EventEmitter implements IBackend {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Promise.all(promises).then(() => {
|
Promise.all(promises).then(() => {
|
||||||
this.emit("debug-ready");
|
if(!this.application.includes('gdb')){
|
||||||
|
this.emit("debug-ready");
|
||||||
|
}
|
||||||
resolve(undefined);
|
resolve(undefined);
|
||||||
}, reject);
|
}, reject);
|
||||||
}
|
}
|
||||||
|
|
15
src/gdb.ts
15
src/gdb.ts
|
@ -44,6 +44,7 @@ export interface AttachRequestArguments extends DebugProtocol.AttachRequestArgum
|
||||||
export class GDBDebugSession extends MI2DebugSession {
|
export class GDBDebugSession extends MI2DebugSession {
|
||||||
public args:LaunchRequestArguments | AttachRequestArguments;
|
public args:LaunchRequestArguments | AttachRequestArguments;
|
||||||
protected disassember: GdbDisassembler;
|
protected disassember: GdbDisassembler;
|
||||||
|
protected supportsRunInTerminalRequest = false;
|
||||||
|
|
||||||
protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
|
protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
|
||||||
response.body.supportsGotoTargetsRequest = true;
|
response.body.supportsGotoTargetsRequest = true;
|
||||||
|
@ -63,9 +64,10 @@ export class GDBDebugSession extends MI2DebugSession {
|
||||||
response.body.supportsDisassembleRequest = true;
|
response.body.supportsDisassembleRequest = true;
|
||||||
response.body.supportsReadMemoryRequest = true;
|
response.body.supportsReadMemoryRequest = true;
|
||||||
response.body.supportsInstructionBreakpoints = true;
|
response.body.supportsInstructionBreakpoints = true;
|
||||||
|
args.supportsRunInTerminalRequest = true;
|
||||||
this.sendResponse(response);
|
this.sendResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// tslint:disable-next-line: max-line-length
|
// tslint:disable-next-line: max-line-length
|
||||||
public sendErrorResponsePub(response: DebugProtocol.Response, codeOrMessage: number | DebugProtocol.Message, format?: string, variables?: any, dest?: any): void {
|
public sendErrorResponsePub(response: DebugProtocol.Response, codeOrMessage: number | DebugProtocol.Message, format?: string, variables?: any, dest?: any): void {
|
||||||
this.sendErrorResponse(response, codeOrMessage, format, variables, dest);
|
this.sendErrorResponse(response, codeOrMessage, format, variables, dest);
|
||||||
|
@ -125,6 +127,17 @@ export class GDBDebugSession extends MI2DebugSession {
|
||||||
args.autorun.forEach(command => {
|
args.autorun.forEach(command => {
|
||||||
this.miDebugger.sendUserInput(command);
|
this.miDebugger.sendUserInput(command);
|
||||||
});
|
});
|
||||||
|
if(this.miDebugger.application === 'gdb'){
|
||||||
|
if(args.terminal === 'integrated' || args.terminal === '' || args.terminal === undefined){
|
||||||
|
let terminalRequestArgs:DebugProtocol.RunInTerminalRequestArguments = {
|
||||||
|
kind: "integrated",
|
||||||
|
title: this.miDebugger.application,
|
||||||
|
cwd: args.cwd || '',
|
||||||
|
args: [],
|
||||||
|
};
|
||||||
|
this.createIntegratedTerminalLinux(terminalRequestArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
this.sendResponse(response);
|
this.sendResponse(response);
|
||||||
}, err => {
|
}, err => {
|
||||||
this.sendErrorResponse(response, 103, `Failed to load MI Debugger: ${err.toString()}`);
|
this.sendErrorResponse(response, 103, `Failed to load MI Debugger: ${err.toString()}`);
|
||||||
|
|
|
@ -11,17 +11,19 @@ import * as net from "net";
|
||||||
import * as os from "os";
|
import * as os from "os";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { hexFormat } from './backend/common';
|
import { hexFormat } from './backend/common';
|
||||||
|
export type InferiorTerminal = 'integrated' | 'external' | '';
|
||||||
|
|
||||||
class ExtendedVariable {
|
class ExtendedVariable {
|
||||||
constructor(public name, public options) {
|
constructor(public name, public options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum RunCommand { CONTINUE, RUN, NONE }
|
export enum RunCommand { CONTINUE, RUN, NONE }
|
||||||
|
|
||||||
const STACK_HANDLES_START = 1000;
|
const STACK_HANDLES_START = 1000;
|
||||||
const VAR_HANDLES_START = 512 * 256 + 1000;
|
const VAR_HANDLES_START = 512 * 256 + 1000;
|
||||||
const VARIABLES_TAG_REGISTER = 0xab;
|
const VARIABLES_TAG_REGISTER = 0xab;
|
||||||
|
|
||||||
|
|
||||||
export class MI2DebugSession extends DebugSession {
|
export class MI2DebugSession extends DebugSession {
|
||||||
protected variableHandles = new Handles<string | VariableObject | ExtendedVariable>(VAR_HANDLES_START);
|
protected variableHandles = new Handles<string | VariableObject | ExtendedVariable>(VAR_HANDLES_START);
|
||||||
protected variableHandlesReverse: { [id: string]: number } = {};
|
protected variableHandlesReverse: { [id: string]: number } = {};
|
||||||
|
@ -853,6 +855,78 @@ export class MI2DebugSession extends DebugSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async createIntegratedTerminalLinux(args:DebugProtocol.RunInTerminalRequestArguments) {
|
||||||
|
const mkdirAsync = fs.promises.mkdir;
|
||||||
|
const mkdtempAsync = async (tempDir: string, prefix: string): Promise<string> => {
|
||||||
|
const name = `${prefix}-${Date.now()}-${Math.floor(Math.random() * 1e9)}`;
|
||||||
|
const newDirPath = `${tempDir}/${name}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await mkdirAsync(newDirPath, { recursive: true });
|
||||||
|
return newDirPath;
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`Error creating temp directory: ${err.message}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const ttyTmpDir = await mkdtempAsync(os.tmpdir(), 'debug');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
fs.writeFileSync(
|
||||||
|
`${ttyTmpDir}/get-tty`,
|
||||||
|
`#!/usr/bin/env sh
|
||||||
|
clear
|
||||||
|
echo "The input and output of program will be here."
|
||||||
|
echo "Warning of set controlling terminal fail can be ignored."
|
||||||
|
tty > ${ttyTmpDir}/ttynameTmp
|
||||||
|
mv ${ttyTmpDir}/ttynameTmp ${ttyTmpDir}/ttyname
|
||||||
|
# wait for debug to finish
|
||||||
|
# prefer using tail to detect PID exit, but that requires GNU tail
|
||||||
|
tail -f --pid=${process.pid} /dev/null 2>/dev/null || while kill -s 0 ${process.pid} 2>/dev/null; do sleep 1s; done
|
||||||
|
# cleanup
|
||||||
|
rm ${ttyTmpDir}/ttyname
|
||||||
|
rm ${ttyTmpDir}/get-tty
|
||||||
|
rmdir ${ttyTmpDir}
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
let watcher: fs.FSWatcher | undefined;
|
||||||
|
const ttyNamePromise = new Promise<string>((resolve) => {
|
||||||
|
watcher = fs.watch(ttyTmpDir, (_eventType, filename) => {
|
||||||
|
if (filename === 'ttyname') {
|
||||||
|
watcher?.close();
|
||||||
|
resolve(
|
||||||
|
fs.readFileSync(`${ttyTmpDir}/ttyname`).toString().trim()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
args.args = ['/bin/sh', `${ttyTmpDir}/get-tty`];
|
||||||
|
const response = await new Promise<DebugProtocol.Response>(
|
||||||
|
(resolve) =>
|
||||||
|
this.sendRequest(
|
||||||
|
'runInTerminal',
|
||||||
|
args,
|
||||||
|
3000,
|
||||||
|
resolve
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (response.success) {
|
||||||
|
const tty = await ttyNamePromise;
|
||||||
|
this.miDebugger.emit("debug-ready");
|
||||||
|
await this.miDebugger.sendCommand(`inferior-tty-set ${tty}`);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
watcher?.close();
|
||||||
|
const message = `could not start the terminal on the client: ${response.message}`;
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function prettyStringArray(strings) {
|
function prettyStringArray(strings) {
|
||||||
|
|
Loading…
Reference in New Issue