1 module repl; 2 private {// import 3 import std.stdio; 4 import std.range; 5 import std.string; 6 import std.algorithm; 7 import std.functional; 8 import std.typetuple; 9 import std.conv; 10 import std.concurrency; 11 } 12 13 class Repl 14 { 15 private string delegate(string[])[string] actions; 16 17 void opIndexAssign(B, A...)(B delegate(A) action, string name) 18 { 19 actions[name] = (string[] argStrs) 20 { 21 if(argStrs.length != A.length) 22 return text( 23 name, " expects ", A.stringof, 24 ", got (", argStrs.join(", "), ")" 25 ); 26 27 A args; 28 29 foreach(i,_; args) 30 args[i] = argStrs[i].to!(A[i]); 31 32 static if(is(B == void)) 33 { 34 action(args); 35 return ""; 36 } 37 else 38 { 39 return action(args).text; 40 } 41 }; 42 } 43 void opIndexAssign(typeof(null), string name) 44 { 45 actions.remove(name); 46 } 47 48 string read() 49 { 50 return stdin.readln!string; 51 } 52 string eval(string command) 53 { 54 auto cmd = command.split(" ").map!strip.filter!(not!empty); 55 56 if(cmd.empty) 57 return help; 58 if(auto action = cmd.front in actions) 59 try 60 return (*action)(cmd.dropOne.array); 61 catch(Exception ex) 62 return ex.msg; 63 else 64 return help; 65 } 66 void print(string result) 67 { 68 result.writeln; 69 } 70 void loop() 71 { 72 while(1) 73 print(eval(read)); 74 } 75 string help() 76 { 77 return text("commands: ", actions.keys.join(", ")); 78 } 79 }