Skip to content

Instantly share code, notes, and snippets.

@Laeeth
Last active October 5, 2015 20:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Laeeth/086419b7c67d2d6f29db to your computer and use it in GitHub Desktop.
Save Laeeth/086419b7c67d2d6f29db to your computer and use it in GitHub Desktop.
very simplistic arsd terminal lua repl
/*
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