Created
June 28, 2017 14:04
-
-
Save sasq64/1bbb6ec3ab4f1d0fa7dd496658a561b8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import std.stdio; | |
| import std.conv; | |
| import std.exception; | |
| import diesel; | |
| import ansi; | |
| import textscreen; | |
| import std.string; | |
| alias toz = std.string.toStringz; | |
| string which(string cmd, string path = null) | |
| { | |
| import std.c.stdlib : getenv; | |
| import std.path : buildPath; | |
| import std.file : exists; | |
| import std.algorithm.iteration : splitter; | |
| if(!path) | |
| path = to!string(getenv("PATH")); | |
| foreach(d ; splitter(path, ":")) | |
| { | |
| auto p = buildPath(d, cmd); | |
| if(exists(p)) | |
| return p; | |
| } | |
| return null; | |
| } | |
| unittest { | |
| import std.string : indexOf; | |
| assert(which("ls").indexOf("bin") > 0); | |
| } | |
| import core.sys.posix.termios; | |
| extern(C) void cfmakeraw(termios *termios_p); | |
| void setRaw(int fd) | |
| { | |
| termios ostate; | |
| termios nstate; | |
| tcgetattr(fd, &nstate); | |
| cfmakeraw(&nstate); | |
| tcsetattr(fd, TCSADRAIN, &nstate); | |
| // | |
| // tcsetattr(f.fileno, TCSADRAIN, &ostate); | |
| // return to original mode | |
| } | |
| struct winsize | |
| { | |
| ushort ws_row; /* rows, in characters */ | |
| ushort ws_col; /* columns, in characters */ | |
| ushort ws_xpixel; /* horizontal size, pixels */ | |
| ushort ws_ypixel; /* vertical size, pixels */ | |
| }; | |
| T tox(T, S)(S s) if(is(T == char**)) { | |
| import core.stdc.stdlib; | |
| char** argv = cast(char**) malloc((char*).sizeof * (s.length + 1)); | |
| foreach(i, arg; s) { | |
| argv[i] = cast(char*) malloc(arg.length + 1); | |
| argv[i][0 .. arg.length] = arg[]; | |
| argv[i][arg.length] = 0; | |
| } | |
| argv[s.length] = null; | |
| return argv; | |
| } | |
| import core.sys.posix.unistd; | |
| extern(C) pid_t forkpty(int *amaster, char *name, termios *termp, winsize *winp); | |
| struct PtyFile | |
| { | |
| this(int fd) | |
| { | |
| this.fd = fd; | |
| } | |
| PtyFile blocking(bool on) | |
| { | |
| import core.sys.posix.fcntl; | |
| int flags = fcntl(fd, F_GETFL, 0); | |
| fcntl(fd, F_SETFL, (!on) ? flags | O_NONBLOCK : flags & ~O_NONBLOCK); | |
| return this; | |
| } | |
| PtyFile nonBlocking() | |
| { | |
| return blocking(false); | |
| } | |
| void write(T)(T[] data) { | |
| writefln("Write %d %s", data.length, T.stringof); | |
| long rc = core.sys.posix.unistd.write(fd, data.ptr, data.length); | |
| } | |
| long read(T)(T[] data) { | |
| long rc = core.sys.posix.unistd.read(fd, data.ptr, data.length); | |
| return rc; | |
| } | |
| int fd; | |
| } | |
| const int PENDIN = 0x20000000; | |
| const int ECHOCTL = 0x00000040; | |
| const int ECHOKE = 0x00000001; | |
| const int OXTABS = 0x00000004; | |
| const int IUTF8 = 0x00004000; | |
| PtyFile launch(string[] args) | |
| { | |
| import core.sys.posix.signal; | |
| import core.sys.posix.sys.wait; | |
| import core.sys.posix.stdlib; | |
| winsize ws = winsize(24, 80, 512, 640); | |
| termios tp; | |
| int master; | |
| char[128] name; | |
| writeln(args); | |
| extern(C) nothrow static @nogc | |
| void childdead(int) { | |
| try { | |
| puts("CHILD DIED\n"); | |
| //writeln("Child died"); | |
| } catch(Error e) {} | |
| wait(null); | |
| } | |
| signal(SIGCHLD, &childdead); | |
| tcgetattr(0, &tp); | |
| tp.c_lflag |= (ECHO | ECHOK | ECHOE); | |
| tp.c_lflag |= (ICANON | ISIG | IEXTEN | ECHO); | |
| tp.c_lflag |= (ECHOKE | ECHOCTL | PENDIN); | |
| tp.c_iflag |= IUTF8; | |
| tp.c_iflag &= ~IXON; | |
| tp.c_oflag &= ~OXTABS; | |
| tp.c_cflag |= CS8; | |
| tp.c_cflag &= ~PARENB; | |
| int rc = forkpty(&master, name.ptr, &tp, &ws); | |
| if(rc == 0) { | |
| // In child process | |
| import core.stdc.stdlib; | |
| setenv("TERM", "xterm", 1); | |
| auto argv = tox!(char**)(args); | |
| core.sys.posix.unistd.execv(argv[0], argv); | |
| } | |
| auto f = PtyFile(master); | |
| f.nonBlocking(); | |
| return f; | |
| } | |
| void main(string[] args) | |
| { | |
| if(args.length < 2) | |
| return; | |
| auto cmd = which(args[1]); | |
| writeln(cmd); | |
| auto tty = launch([cmd] ~ args[2..$]); | |
| auto screen = new TextScreen(80, 24); | |
| auto as = ScreenParser.create("ansi", tty, screen); | |
| init_video(); | |
| auto win = Window(80*8, 24*8); | |
| auto font = new Font("unscii-8-fantasy.ttf", 16); | |
| ubyte[] x = [0x1b, '[', 'B']; | |
| win.onKey(win.KEY_ESC, { writeln("AAAH"); tty.write([cast(char)0x1b]); }); | |
| //win.onKey(win.KEY_CR, { writeln("C"); tty.rawWrite(x"0d"); }); | |
| win.onKey(win.KEY_DOWN, { | |
| writeln(x); | |
| tty.blocking(true); | |
| tty.write(x); | |
| tty.blocking(false); | |
| }); | |
| win.onKey(win.KEY_UP, { writeln("U"); tty.write(x"1B" ~ "[A"); }); | |
| win.onKeyDefault((int c){ writeln("d"); | |
| char[] b = [ cast(char)c ]; | |
| tty.write(b); | |
| }); | |
| win.runLoop({ | |
| for(int i=0; i<10; i++) | |
| as.update(); | |
| screen.foreachString((int x, int y, string txt, uint fg, uint bg) { | |
| font.renderText(x*8, y*8, txt, 0xffffff, bg); | |
| }); | |
| }); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment