Last active
October 5, 2015 20:17
-
-
Save Laeeth/086419b7c67d2d6f29db to your computer and use it in GitHub Desktop.
very simplistic arsd terminal lua repl
This file contains 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
/* | |
Basic idea is to create an inspector for exploring state of a D program from a console using Lua | |
to view and perhaps modify D state. You can then call this inspector either like a breakpoint by | |
just placing a call to it where you wish your code to stop, or implement something fancier so that | |
you can interrupt the code live from the debugging console or specify conditions that will lead to | |
a 'breakpoint'. (Perhaps annotate the functions that need to check if they need to call in to the | |
debugger, and conceivably have some kind of interprocess communication). | |
Also means you can log to a data structure rather than text file, and inspect the data structure in | |
a more precise and structured way via Lua | |
So far this doesn't do much - just a proof of concept to convince myself it's feasible | |
*/ | |
import arsd.terminal; | |
import arsd.script; | |
import luad.all; | |
import std.stream; | |
import std.stdio; | |
import std.array; | |
import std.algorithm; | |
import std.conv; | |
import std.string; | |
import std.exception; | |
import std.datetime; | |
// for some reason this segfaults on Lua Exception | |
// proof of concept for my use case and this doesn't use | |
// many features of arsd terminal so far | |
string lastLine; | |
string[128] clicks; | |
static void panic(LuaState lua, in char[] error) | |
{ | |
throw new Exception(error.idup); | |
} | |
struct Test | |
{ | |
string date; | |
double value; | |
} | |
auto makeTests() | |
{ | |
Test[] tests; | |
tests.length=100; | |
foreach(i;0..tests.length) | |
{ | |
tests[i].date=(DateTime(1990,1,1)+i.days).to!string; | |
tests[i].value=100.0-i; | |
} | |
return tests; | |
} | |
/** | |
In REPL enter: | |
return tests[1]["date"] | |
return tests[1]["value"] | |
I made it ignore stuff entered in REPL that doesn't have a ( in it. you can get rid of that. | |
remember that Lua tables are indexed from 1, so tests[1] in Lua refers to tests[0] in D | |
*/ | |
void main(string[] args) | |
{ | |
auto lua = new LuaState; | |
lua.openLibs(); | |
lua.setPanicHandler(&panic); | |
auto terminal = Terminal(ConsoleOutputType.cellular); | |
terminal.setTitle("Arsd Lua REPL"); | |
auto input = RealTimeConsoleInput(&terminal, ConsoleInputFlags.raw | ConsoleInputFlags.allInputEvents); | |
auto tests=makeTests(); | |
auto lineGetter = new LineGetter(&terminal, "lua"); | |
scope(exit) lineGetter.dispose(); | |
lineGetter.prompt = "> "; | |
terminal.moveTo(0, terminal.height - 1); | |
lineGetter.startGettingLine(); | |
bool running = true; | |
int pos; | |
void executeLine(string line) { | |
string status; | |
try { | |
if(line.length>0 && line.canFind("(")) | |
{ | |
lua["tests"]=tests; | |
lua.doString(line); | |
auto results= lua.doString(line); | |
if(results.length>0) | |
status=results[0].toString; | |
} | |
drawInspectionWindow(&terminal, status); // lua.doString(line).map!(a=>a.to!string).join(",")); | |
} catch(Exception e) { | |
drawInspectionWindow(&terminal, e.msg.to!string); | |
} | |
terminal.moveTo(0, terminal.height - 1); | |
lineGetter.startGettingLine(); | |
} | |
void handleEvent(InputEvent event) { | |
switch(event.type) { | |
case InputEvent.Type.MouseEvent: | |
auto ev = event.get!(InputEvent.Type.MouseEvent); | |
/* | |
if(ev.eventType == MouseEvent.Type.Pressed) { | |
if(ev.y == 0) { | |
// clicks on the top bar | |
if(ev.x >= 0 && ev.x < 4) { | |
// back button | |
if(pos) { | |
pos--; | |
globals.inspecting = globals.inspectionStack[pos]; | |
drawInspectionWindow(&terminal, globals.inspectionStack[pos]); | |
} | |
break; | |
} | |
if(ev.x >= 5 && ev.x < 5+4) { | |
// forward button | |
if(pos + 1 < globals.inspectionStack.length) { | |
pos++; | |
globals.inspecting = globals.inspectionStack[pos]; | |
drawInspectionWindow(&terminal, globals.inspectionStack[pos]); | |
} | |
break; | |
} | |
} else { | |
if(clicks[ev.y].length) | |
executeLine("inspecting["~clicks[ev.y]~"];"); | |
// click on the main window | |
break; | |
} | |
}*/ | |
goto pass_on; | |
case InputEvent.Type.CharacterEvent: | |
auto ev = event.get!(InputEvent.Type.CharacterEvent); | |
if(ev.character == ('x' - 'a' + 1)) { | |
lineGetter.addString("shortcut"); | |
lineGetter.redraw(); | |
break; | |
} | |
goto pass_on; | |
default: | |
pass_on: | |
try | |
if(!lineGetter.workOnLine(event)) { | |
auto line = lineGetter.finishGettingLine(); | |
lastLine = line; | |
executeLine(line); | |
} | |
catch(Exception e) | |
running = false; | |
} | |
} | |
while(running) { | |
auto event = input.nextEvent(); | |
handleEvent(event); | |
} | |
} | |
void drawInspectionWindow(Terminal* terminal, string inspecting) | |
{ | |
terminal.clear(); | |
terminal.write(" | "); | |
terminal.writeln(lastLine); | |
foreach(i; 0 .. terminal.width) | |
terminal.write("-"); | |
terminal.moveTo(0, 2); | |
clicks[] = null; | |
terminal.write(inspecting); | |
terminal.flush(); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment