mirror of https://github.com/buggins/dlangide.git
terminal support
This commit is contained in:
parent
fd0f10bfc5
commit
8dd29d78a0
src
ddebug
dlangide/ui
|
@ -303,6 +303,11 @@ class DebuggerProxy : Debugger, DebuggerCallback {
|
|||
_debugger.setTerminalExecutable(terminalExecutable);
|
||||
}
|
||||
|
||||
/// set terminal device name before execution
|
||||
void setTerminalTty(string terminalTty) {
|
||||
_debugger.setTerminalTty(terminalTty);
|
||||
}
|
||||
|
||||
/// set debugger executable
|
||||
void setDebuggerExecutable(string debuggerExecutable) {
|
||||
_debugger.setDebuggerExecutable(debuggerExecutable);
|
||||
|
@ -413,7 +418,7 @@ abstract class DebuggerBase : Thread, Debugger {
|
|||
|
||||
/// provides _executableFile, _executableArgs, _executableWorkingDir, _executableEnvVars parameters and setter function setExecutableParams
|
||||
mixin ExecutableParams;
|
||||
/// provides _terminalExecutable and setTerminalExecutable setter
|
||||
/// provides _terminalExecutable, _terminalTty, setTerminalExecutable, and setTerminalTty
|
||||
mixin TerminalParams;
|
||||
|
||||
protected DebuggerCallback _callback;
|
||||
|
|
|
@ -23,6 +23,8 @@ interface ProgramExecution {
|
|||
void setExecutableParams(string executableFile, string[] args, string workingDir, string[string] envVars);
|
||||
/// set external terminal parameters before execution
|
||||
void setTerminalExecutable(string terminalExecutable);
|
||||
/// set external terminal tty before execution
|
||||
void setTerminalTty(string terminalTty);
|
||||
|
||||
/// returns true if it's debugger
|
||||
@property bool isDebugger();
|
||||
|
@ -53,15 +55,20 @@ mixin template ExecutableParams() {
|
|||
}
|
||||
|
||||
|
||||
/// provides _terminalExecutable and setTerminalExecutable setter
|
||||
/// provides _terminalExecutable, _terminalTty, setTerminalExecutable, and setTerminalTty
|
||||
mixin template TerminalParams() {
|
||||
|
||||
/// executable file name for external console/terminal
|
||||
protected string _terminalExecutable;
|
||||
protected string _terminalTty;
|
||||
|
||||
/// set external terminal parameters before execution
|
||||
void setTerminalExecutable(string terminalExecutable) {
|
||||
_terminalExecutable = terminalExecutable;
|
||||
}
|
||||
|
||||
void setTerminalTty(string terminalTty) {
|
||||
_terminalTty = terminalTty;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ class ProgramExecutionNoDebug : Thread, ProgramExecution {
|
|||
// parameters
|
||||
/// provides _executableFile, _executableArgs, _executableWorkingDir, _executableEnvVars parameters and setter function setExecutableParams
|
||||
mixin ExecutableParams;
|
||||
/// provides _terminalExecutable and setTerminalExecutable setter
|
||||
/// provides _terminalExecutable, _terminalTty, setTerminalExecutable, and setTerminalTty
|
||||
mixin TerminalParams;
|
||||
|
||||
protected ProgramExecutionStatusListener _listener;
|
||||
|
|
|
@ -115,9 +115,11 @@ class GDBInterface : ConsoleDebuggerInterface, TextCommandTarget {
|
|||
}
|
||||
|
||||
Pid terminalPid;
|
||||
string terminalTty;
|
||||
string externalTerminalTty;
|
||||
|
||||
string startTerminal() {
|
||||
if (!_terminalTty.empty)
|
||||
return _terminalTty;
|
||||
Log.d("Starting terminal ", _terminalExecutable);
|
||||
import std.random;
|
||||
import std.file;
|
||||
|
@ -125,7 +127,7 @@ class GDBInterface : ConsoleDebuggerInterface, TextCommandTarget {
|
|||
import std.string;
|
||||
import core.thread;
|
||||
uint n = uniform(0, 0x10000000, rndGen());
|
||||
terminalTty = null;
|
||||
externalTerminalTty = null;
|
||||
string termfile = buildPath(tempDir, format("dlangide-term-name-%07x.tmp", n));
|
||||
Log.d("temp file for tty name: ", termfile);
|
||||
try {
|
||||
|
@ -151,27 +153,29 @@ class GDBInterface : ConsoleDebuggerInterface, TextCommandTarget {
|
|||
}
|
||||
// read TTY from file
|
||||
if (exists(termfile)) {
|
||||
terminalTty = readText(termfile);
|
||||
if (terminalTty.endsWith("\n"))
|
||||
terminalTty = terminalTty[0 .. $-1];
|
||||
externalTerminalTty = readText(termfile);
|
||||
if (externalTerminalTty.endsWith("\n"))
|
||||
externalTerminalTty = externalTerminalTty[0 .. $-1];
|
||||
// delete file
|
||||
remove(termfile);
|
||||
Log.d("Terminal tty: ", terminalTty);
|
||||
Log.d("Terminal tty: ", externalTerminalTty);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("Failed to start terminal ", e);
|
||||
killTerminal();
|
||||
}
|
||||
if (terminalTty.length == 0) {
|
||||
if (externalTerminalTty.length == 0) {
|
||||
Log.i("Cannot start terminal");
|
||||
killTerminal();
|
||||
} else {
|
||||
Log.i("Terminal: ", terminalTty);
|
||||
Log.i("Terminal: ", externalTerminalTty);
|
||||
}
|
||||
return terminalTty;
|
||||
return externalTerminalTty;
|
||||
}
|
||||
|
||||
bool isTerminalActive() {
|
||||
if (!_terminalTty.empty)
|
||||
return true;
|
||||
if (_terminalExecutable.empty)
|
||||
return true;
|
||||
if (terminalPid is null)
|
||||
|
@ -188,6 +192,8 @@ class GDBInterface : ConsoleDebuggerInterface, TextCommandTarget {
|
|||
}
|
||||
|
||||
void killTerminal() {
|
||||
if (!_terminalTty.empty)
|
||||
return;
|
||||
if (_terminalExecutable.empty)
|
||||
return;
|
||||
if (terminalPid is null)
|
||||
|
@ -208,16 +214,18 @@ class GDBInterface : ConsoleDebuggerInterface, TextCommandTarget {
|
|||
override void startDebugging() {
|
||||
Log.d("GDBInterface.startDebugging()");
|
||||
string[] debuggerArgs;
|
||||
if (!_terminalExecutable.empty) {
|
||||
terminalTty = startTerminal();
|
||||
if (terminalTty.length == 0) {
|
||||
if (!_terminalExecutable.empty || !_terminalTty.empty) {
|
||||
externalTerminalTty = startTerminal();
|
||||
if (externalTerminalTty.length == 0) {
|
||||
//_callback.onResponse(ResponseCode.CannotRunDebugger, "Cannot start terminal");
|
||||
_status = ExecutionStatus.Error;
|
||||
_stopRequested = true;
|
||||
return;
|
||||
}
|
||||
debuggerArgs ~= "-tty";
|
||||
debuggerArgs ~= terminalTty;
|
||||
if (!USE_INIT_SEQUENCE) {
|
||||
debuggerArgs ~= "-tty";
|
||||
debuggerArgs ~= externalTerminalTty;
|
||||
}
|
||||
}
|
||||
debuggerArgs ~= "--interpreter=mi";
|
||||
debuggerArgs ~= "--silent";
|
||||
|
@ -677,8 +685,8 @@ class GDBInterface : ConsoleDebuggerInterface, TextCommandTarget {
|
|||
initRequestsWarnings = 0;
|
||||
finishedInitRequests = 0;
|
||||
submitRequest(new GDBInitRequest("-environment-cd " ~ quotePathIfNeeded(_executableWorkingDir), true));
|
||||
if (terminalTty)
|
||||
submitRequest(new GDBInitRequest("-inferior-tty-set " ~ terminalTty, true));
|
||||
if (externalTerminalTty)
|
||||
submitRequest(new GDBInitRequest("-inferior-tty-set " ~ quotePathIfNeeded(externalTerminalTty), true));
|
||||
|
||||
submitRequest(new GDBInitRequest("-gdb-set breakpoint pending on", false));
|
||||
submitRequest(new GDBInitRequest("-enable-pretty-printing", false));
|
||||
|
|
|
@ -179,6 +179,7 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL
|
|||
switch(status) {
|
||||
case ExecutionStatus.Error:
|
||||
_logPanel.logLine("Cannot run program " ~ process.executableFile);
|
||||
_logPanel.activateLogTab();
|
||||
break;
|
||||
case ExecutionStatus.Finished:
|
||||
_logPanel.logLine("Program " ~ process.executableFile ~ " finished with exit code " ~ to!string(exitCode));
|
||||
|
@ -274,8 +275,14 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL
|
|||
_logPanel.logLine("Starting debugger for " ~ executableFileName);
|
||||
_statusLine.setBackgroundOperationStatus("debug-run", program.isDebugger ? "debugging..."d : "running..."d);
|
||||
string[string] env;
|
||||
string tty = _logPanel.terminalDeviceName;
|
||||
program.setExecutableParams(executableFileName, args, workingDirectory, env);
|
||||
program.setTerminalExecutable(externalConsoleExecutable);
|
||||
if (!tty.empty) {
|
||||
Log.d("Terminal window device name: ", tty);
|
||||
program.setTerminalTty(tty);
|
||||
_logPanel.activateTerminalTab(true);
|
||||
} else
|
||||
program.setTerminalExecutable(externalConsoleExecutable);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1375,6 +1382,7 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL
|
|||
_logPanel.logLine("No project is opened");
|
||||
return;
|
||||
}
|
||||
_logPanel.activateLogTab();
|
||||
if (!listener) {
|
||||
if (buildOp == BuildOperation.Upgrade || buildOp == BuildOperation.Build || buildOp == BuildOperation.Rebuild) {
|
||||
listener = delegate(int result) {
|
||||
|
|
|
@ -132,12 +132,29 @@ class OutputPanel : DockWindow {
|
|||
|
||||
@property TabWidget getTabs() { return _tabs;}
|
||||
|
||||
void activateLogTab() {
|
||||
_tabs.selectTab("logwidget");
|
||||
}
|
||||
|
||||
void activateTerminalTab(bool clear = false) {
|
||||
_tabs.selectTab("TERMINAL");
|
||||
if (clear)
|
||||
_terminalWidget.resetTerminal();
|
||||
}
|
||||
|
||||
this(string id) {
|
||||
_showCloseButton = false;
|
||||
dockAlignment = DockAlignment.Bottom;
|
||||
super(id);
|
||||
}
|
||||
|
||||
/// terminal device for Console tab
|
||||
@property string terminalDeviceName() {
|
||||
if (_terminalWidget)
|
||||
return _terminalWidget.deviceName;
|
||||
return null;
|
||||
}
|
||||
|
||||
override protected Widget createBodyWidget() {
|
||||
layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
|
||||
_tabs = new TabWidget("OutputPanelTabs", Align.Bottom);
|
||||
|
|
|
@ -671,6 +671,10 @@ class TerminalWidget : WidgetGroup, OnScrollHandler {
|
|||
_device.write(chars.toUTF8);
|
||||
}
|
||||
|
||||
void resetTerminal() {
|
||||
_content.resetTerminal();
|
||||
}
|
||||
|
||||
private dchar[] outputChars;
|
||||
// write utf32
|
||||
void write(dstring chars) {
|
||||
|
@ -874,7 +878,9 @@ class TerminalDevice : Thread {
|
|||
break;
|
||||
DWORD bytesRead = 0;
|
||||
// read data from client
|
||||
if (ReadFile(hpipe, &buf, buf.length, &bytesRead, null)) {
|
||||
Log.d("TerminalDevice reading from pipe");
|
||||
if (ReadFile(hpipe, &buf, 1, &bytesRead, null)) { //buf.length
|
||||
Log.d("TerminalDevice bytes read: ", bytesRead);
|
||||
if (closed)
|
||||
break;
|
||||
if (bytesRead && onBytesRead.assigned) {
|
||||
|
@ -887,6 +893,7 @@ class TerminalDevice : Thread {
|
|||
Log.d("TerminalDevice client disconnecting");
|
||||
connected = false;
|
||||
// disconnect client
|
||||
FlushFileBuffers(hpipe);
|
||||
DisconnectNamedPipe(hpipe);
|
||||
}
|
||||
}
|
||||
|
@ -983,11 +990,12 @@ class TerminalDevice : Thread {
|
|||
import std.uuid;
|
||||
_name = "\\\\.\\pipe\\dlangide-terminal-" ~ randomUUID().toString;
|
||||
hpipe = CreateNamedPipeA(cast(const(char)*)_name.toStringz,
|
||||
PIPE_ACCESS_DUPLEX,
|
||||
cast(uint)PIPE_TYPE_BYTE,
|
||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, // dwOpenMode
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, // | PIPE_REJECT_REMOTE_CLIENTS,
|
||||
//PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, // | PIPE_REJECT_REMOTE_CLIENTS,
|
||||
1,
|
||||
16384,
|
||||
16384,
|
||||
1, //16384,
|
||||
1, //16384,
|
||||
50,
|
||||
null);
|
||||
if (hpipe == INVALID_HANDLE_VALUE) {
|
||||
|
|
Loading…
Reference in New Issue