mirror of https://github.com/adamdruppe/arsd.git
this thing might work
This commit is contained in:
parent
8cdfd125c4
commit
aab7b0fd00
160
terminal.d
160
terminal.d
|
@ -1754,6 +1754,7 @@ struct Terminal {
|
||||||
void flush() {
|
void flush() {
|
||||||
if(pipeThroughStdOut) {
|
if(pipeThroughStdOut) {
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
fflush(stderr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4780,6 +4781,14 @@ class LineGetter {
|
||||||
version(TerminalDirectToEmulator) {
|
version(TerminalDirectToEmulator) {
|
||||||
if(!terminal.usingDirectEmulator)
|
if(!terminal.usingDirectEmulator)
|
||||||
return updateCursorPosition_impl();
|
return updateCursorPosition_impl();
|
||||||
|
|
||||||
|
if(terminal.pipeThroughStdOut) {
|
||||||
|
terminal.tew.terminalEmulator.waitingForInboundSync = true;
|
||||||
|
terminal.writeStringRaw("\xff");
|
||||||
|
terminal.flush();
|
||||||
|
terminal.tew.terminalEmulator.syncSignal.wait();
|
||||||
|
}
|
||||||
|
|
||||||
startOfLineX = terminal.tew.terminalEmulator.cursorX;
|
startOfLineX = terminal.tew.terminalEmulator.cursorX;
|
||||||
startOfLineY = terminal.tew.terminalEmulator.cursorY;
|
startOfLineY = terminal.tew.terminalEmulator.cursorY;
|
||||||
} else
|
} else
|
||||||
|
@ -6194,74 +6203,89 @@ version(TerminalDirectToEmulator) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
version(Posix) {
|
if(term.pipeThroughStdOut) {
|
||||||
import unix = core.sys.posix.unistd;
|
version(Posix) {
|
||||||
import core.stdc.stdio;
|
import unix = core.sys.posix.unistd;
|
||||||
|
import core.stdc.stdio;
|
||||||
|
|
||||||
auto fp = stdout;
|
auto fp = stdout;
|
||||||
|
|
||||||
int[2] fds;
|
int[2] fds;
|
||||||
auto ret = pipe(fds);
|
auto ret = pipe(fds);
|
||||||
|
|
||||||
auto fd = fileno(fp);
|
auto fd = fileno(fp);
|
||||||
|
|
||||||
dup2(fds[1], fd);
|
dup2(fds[1], fd);
|
||||||
unix.close(fds[1]);
|
unix.close(fds[1]);
|
||||||
auto listener = new PosixFdReader(() {
|
if(isatty(2))
|
||||||
ubyte[1024] buffer;
|
dup2(1, 2);
|
||||||
auto ret = read(fds[0], buffer.ptr, buffer.length);
|
auto listener = new PosixFdReader(() {
|
||||||
if(ret <= 0) return;
|
ubyte[1024] buffer;
|
||||||
tew.terminalEmulator.sendRawInput(buffer[0 .. ret]);
|
auto ret = read(fds[0], buffer.ptr, buffer.length);
|
||||||
tew.terminalEmulator.redraw();
|
if(ret <= 0) return;
|
||||||
}, fds[0]);
|
tew.terminalEmulator.sendRawInput(buffer[0 .. ret]);
|
||||||
}
|
tew.terminalEmulator.redraw();
|
||||||
|
}, fds[0]);
|
||||||
version(Windows) {
|
|
||||||
|
|
||||||
CHAR[MAX_PATH] PipeNameBuffer;
|
|
||||||
|
|
||||||
static shared(int) PipeSerialNumber = 0;
|
|
||||||
|
|
||||||
import core.atomic;
|
|
||||||
|
|
||||||
import core.stdc.string;
|
|
||||||
|
|
||||||
// we need a unique name in the universal filesystem
|
|
||||||
// so it can be freopen'd. When the process terminates,
|
|
||||||
// this is auto-closed too, so the pid is good enough, just
|
|
||||||
// with the shared number
|
|
||||||
sprintf(PipeNameBuffer.ptr,
|
|
||||||
"\\\\.\\Pipe\\SilPipe.%08x.%08x".ptr,
|
|
||||||
GetCurrentProcessId(),
|
|
||||||
atomicOp!"+="(PipeSerialNumber, 1)
|
|
||||||
);
|
|
||||||
|
|
||||||
readPipe = CreateNamedPipeA(
|
|
||||||
PipeNameBuffer.ptr,
|
|
||||||
1/*PIPE_ACCESS_INBOUND*/ | FILE_FLAG_OVERLAPPED,
|
|
||||||
0 /*PIPE_TYPE_BYTE*/ | 0/*PIPE_WAIT*/,
|
|
||||||
1, // Number of pipes
|
|
||||||
0, // Out buffer size
|
|
||||||
0, // In buffer size
|
|
||||||
0,//120 * 1000, // Timeout in ms
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!readPipe) {
|
|
||||||
throw new Exception("CreateNamedPipeA");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(freopen(PipeNameBuffer.ptr, "wb", stdout) is null)
|
version(Windows) {
|
||||||
throw new Exception("freopen");
|
|
||||||
|
|
||||||
setvbuf(stdout, null, _IONBF, 0); // I'd prefer to line buffer it, but that doesn't seem to work for some reason.
|
CHAR[MAX_PATH] PipeNameBuffer;
|
||||||
|
|
||||||
ConnectNamedPipe(readPipe, null);
|
static shared(int) PipeSerialNumber = 0;
|
||||||
|
|
||||||
this.overlapped = new OVERLAPPED();
|
import core.atomic;
|
||||||
this.overlapped.hEvent = cast(void*) this;
|
|
||||||
this.overlappedBuffer = new ubyte[](4096);
|
import core.stdc.string;
|
||||||
WindowsRead(0, 0, this.overlapped);
|
|
||||||
|
// we need a unique name in the universal filesystem
|
||||||
|
// so it can be freopen'd. When the process terminates,
|
||||||
|
// this is auto-closed too, so the pid is good enough, just
|
||||||
|
// with the shared number
|
||||||
|
sprintf(PipeNameBuffer.ptr,
|
||||||
|
`\\.\pipe\arsd.terminal.pipe.%08x.%08x`.ptr,
|
||||||
|
GetCurrentProcessId(),
|
||||||
|
atomicOp!"+="(PipeSerialNumber, 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
readPipe = CreateNamedPipeA(
|
||||||
|
PipeNameBuffer.ptr,
|
||||||
|
1/*PIPE_ACCESS_INBOUND*/ | FILE_FLAG_OVERLAPPED,
|
||||||
|
0 /*PIPE_TYPE_BYTE*/ | 0/*PIPE_WAIT*/,
|
||||||
|
1, // Number of pipes
|
||||||
|
1024, // Out buffer size
|
||||||
|
1024, // In buffer size
|
||||||
|
0,//120 * 1000, // Timeout in ms
|
||||||
|
null
|
||||||
|
);
|
||||||
|
if (!readPipe) {
|
||||||
|
throw new Exception("CreateNamedPipeA");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.overlapped = new OVERLAPPED();
|
||||||
|
this.overlapped.hEvent = cast(void*) this;
|
||||||
|
this.overlappedBuffer = new ubyte[](4096);
|
||||||
|
|
||||||
|
import std.conv;
|
||||||
|
import core.stdc.errno;
|
||||||
|
if(freopen(PipeNameBuffer.ptr, "wb", stdout) is null)
|
||||||
|
//MessageBoxA(null, ("excep " ~ to!string(errno) ~ "\0").ptr, "asda", 0);
|
||||||
|
throw new Exception("freopen");
|
||||||
|
|
||||||
|
setvbuf(stdout, null, _IOLBF, 128); // I'd prefer to line buffer it, but that doesn't seem to work for some reason.
|
||||||
|
|
||||||
|
ConnectNamedPipe(readPipe, this.overlapped);
|
||||||
|
|
||||||
|
// also send stderr to stdout if it isn't already redirected somewhere else
|
||||||
|
if(_fileno(stderr) < 0) {
|
||||||
|
freopen("nul", "wb", stderr);
|
||||||
|
|
||||||
|
_dup2(_fileno(stdout), _fileno(stderr));
|
||||||
|
setvbuf(stderr, null, _IOLBF, 128); // if I don't unbuffer this it can really confuse things
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowsRead(0, 0, this.overlapped);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6276,9 +6300,9 @@ version(TerminalDirectToEmulator) {
|
||||||
w.tew.terminalEmulator.redraw();
|
w.tew.terminalEmulator.redraw();
|
||||||
}
|
}
|
||||||
import std.conv;
|
import std.conv;
|
||||||
if(!ReadFileEx(w.readPipe, w.overlappedBuffer.ptr, w.overlappedBuffer.length, overlapped, &WindowsRead))
|
if(!ReadFileEx(w.readPipe, w.overlappedBuffer.ptr, cast(DWORD) w.overlappedBuffer.length, overlapped, &WindowsRead))
|
||||||
if(GetLastError() == 997) {}
|
if(GetLastError() == 997) {}
|
||||||
else throw new Exception("ReadFileEx " ~ to!string(GetLastError()));
|
//else throw new Exception("ReadFileEx " ~ to!string(GetLastError()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6619,6 +6643,13 @@ version(TerminalDirectToEmulator) {
|
||||||
size_t last = 0;
|
size_t last = 0;
|
||||||
const ubyte[2] crlf = [13, 10];
|
const ubyte[2] crlf = [13, 10];
|
||||||
foreach(idx, ch; data) {
|
foreach(idx, ch; data) {
|
||||||
|
if(waitingForInboundSync && ch == 255) {
|
||||||
|
send(data[last .. idx]);
|
||||||
|
last = idx + 1;
|
||||||
|
waitingForInboundSync = false;
|
||||||
|
syncSignal.notify();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if(ch == 10) {
|
if(ch == 10) {
|
||||||
send(data[last .. idx]);
|
send(data[last .. idx]);
|
||||||
send(crlf[]);
|
send(crlf[]);
|
||||||
|
@ -6642,9 +6673,12 @@ version(TerminalDirectToEmulator) {
|
||||||
alias fromHsl = arsd.color.fromHsl;
|
alias fromHsl = arsd.color.fromHsl;
|
||||||
|
|
||||||
const(ubyte)[] pendingForApplication;
|
const(ubyte)[] pendingForApplication;
|
||||||
|
Semaphore syncSignal;
|
||||||
Semaphore outgoingSignal;
|
Semaphore outgoingSignal;
|
||||||
Semaphore incomingSignal;
|
Semaphore incomingSignal;
|
||||||
|
|
||||||
|
private shared(bool) waitingForInboundSync;
|
||||||
|
|
||||||
override void sendToApplication(scope const(void)[] what) {
|
override void sendToApplication(scope const(void)[] what) {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
pendingForApplication ~= cast(const(ubyte)[]) what;
|
pendingForApplication ~= cast(const(ubyte)[]) what;
|
||||||
|
@ -6659,6 +6693,7 @@ version(TerminalDirectToEmulator) {
|
||||||
|
|
||||||
private this(TerminalEmulatorWidget widget) {
|
private this(TerminalEmulatorWidget widget) {
|
||||||
|
|
||||||
|
this.syncSignal = new Semaphore();
|
||||||
this.outgoingSignal = new Semaphore();
|
this.outgoingSignal = new Semaphore();
|
||||||
this.incomingSignal = new Semaphore();
|
this.incomingSignal = new Semaphore();
|
||||||
|
|
||||||
|
@ -6844,6 +6879,9 @@ private version(Windows) {
|
||||||
DWORD nDefaultTimeOut,
|
DWORD nDefaultTimeOut,
|
||||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes
|
||||||
);
|
);
|
||||||
|
|
||||||
|
extern(C) int _dup2(int, int);
|
||||||
|
extern(C) int _fileno(FILE*);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue