diff --git a/src/bin/Disk.hx b/src/bin/Disk.hx index f40d0d4..857f033 100644 --- a/src/bin/Disk.hx +++ b/src/bin/Disk.hx @@ -1,19 +1,18 @@ package bin; +import kernel.ps.ProcessHandle; +import kernel.ps.Process; import kernel.peripherals.Peripherals.Peripheral; -import lib.cli.TermHandle; -import lib.cli.CLIApp; using tink.CoreApi; using Lambda; -class Disk extends CLIApp { - - private var handle:TermHandle; +class Disk implements Process { + private var handle:ProcessHandle; public function new() {} - public function invoke(handle:TermHandle):Future { + public function run(handle:ProcessHandle):Void { this.handle = handle; var subcommand = handle.args[0]; var driveAddr:Null = handle.args[1]; @@ -27,12 +26,12 @@ class Disk extends CLIApp { if (drive.isDiskPresent()){ if (drive.hasAudio()){ - handle.writeLn('${addr} => ${label} [AUDIO]'); + handle.writeLine('${addr} => ${label} [AUDIO]'); }else{ - handle.writeLn('${addr} => ${label} (${id})'); + handle.writeLine('${addr} => ${label} (${id})'); } }else { - handle.writeLn('${addr} => [NO DISK]'); + handle.writeLine('${addr} => [NO DISK]'); } return true; @@ -41,18 +40,15 @@ class Disk extends CLIApp { var drive = Peripheral.instance.getDrive(driveAddr); if (drive == null){ - handle.writeLn("Drive not found: " + driveAddr); - return Future.sync(false); + handle.writeLine("Drive not found: " + driveAddr); } if (!drive.isDiskPresent()){ - handle.writeLn("No disk in drive: " + driveAddr); - return Future.sync(false); + handle.writeLine("No disk in drive: " + driveAddr); } if (!drive.hasAudio()){ - handle.writeLn("Disk in drive " + driveAddr + " does not have audio"); - return Future.sync(false); + handle.writeLine("Disk in drive " + driveAddr + " does not have audio"); } drive.playAudio(); @@ -60,18 +56,15 @@ class Disk extends CLIApp { var drive = Peripheral.instance.getDrive(driveAddr); if (drive == null){ - handle.writeLn("Drive not found: " + driveAddr); - return Future.sync(false); + handle.writeLine("Drive not found: " + driveAddr); } if (!drive.isDiskPresent()){ - handle.writeLn("No disk in drive: " + driveAddr); - return Future.sync(false); + handle.writeLine("No disk in drive: " + driveAddr); } if (!drive.hasAudio()){ - handle.writeLn("Disk in drive: " + driveAddr + " does not have audio"); - return Future.sync(false); + handle.writeLine("Disk in drive: " + driveAddr + " does not have audio"); } drive.stopAudio(); @@ -80,13 +73,11 @@ class Disk extends CLIApp { var drive = Peripheral.instance.getDrive(driveAddr); if (drive == null){ - handle.writeLn("Drive not found: " + driveAddr); - return Future.sync(false); + handle.writeLine("Drive not found: " + driveAddr); } if (!drive.isDiskPresent()){ - handle.writeLn("No disk in drive: " + driveAddr); - return Future.sync(false); + handle.writeLine("No disk in drive: " + driveAddr); } drive.ejectDisk(); @@ -95,43 +86,39 @@ class Disk extends CLIApp { var label:String = handle.args[2]; if (drive == null){ - handle.writeLn("Drive not found: " + driveAddr); - return Future.sync(false); + handle.writeLine("Drive not found: " + driveAddr); } if (!drive.isDiskPresent()){ - handle.writeLn("No disk in drive: " + driveAddr); - return Future.sync(false); + handle.writeLine("No disk in drive: " + driveAddr); } if (label == null || label == ""){ - handle.writeLn(drive.getDiskLabel()); + handle.writeLine(drive.getDiskLabel()); }else{ var err = drive.setDiskLabel(label); if (err != null){ - handle.writeLn("Failed to set lable"); - return Future.sync(false); + handle.writeLine("Failed to set lable"); } } case "help": case null: printHelp(); default: - handle.writeLn("Unknown subcommand: " + subcommand); + handle.writeLine("Unknown subcommand: " + subcommand); printHelp(); - return Future.sync(false); } - return Future.sync(true); + return handle.close(true); } private function printHelp() { - handle.writeLn("Usage: disk [args]"); - handle.writeLn("Subcommands:"); - handle.writeLn(" ls"); - handle.writeLn(" play "); - handle.writeLn(" stop "); - handle.writeLn(" eject "); - handle.writeLn(" label [label]"); + handle.writeLine("Usage: disk [args]"); + handle.writeLine("Subcommands:"); + handle.writeLine(" ls"); + handle.writeLine(" play "); + handle.writeLine(" stop "); + handle.writeLine(" eject "); + handle.writeLine(" label [label]"); } } diff --git a/src/bin/GPS.hx b/src/bin/GPS.hx index 01bbb19..04beb69 100644 --- a/src/bin/GPS.hx +++ b/src/bin/GPS.hx @@ -1,19 +1,19 @@ package bin; +import kernel.ps.ProcessHandle; +import kernel.ps.Process; import kernel.gps.INS; import lib.Pos3; import lib.Vec.Vec3; -import lib.cli.TermHandle; -import lib.cli.CLIApp; using tink.CoreApi; -class GPS extends CLIApp { - private var handle:TermHandle; +class GPS implements Process { + private var handle:ProcessHandle; public function new() {} - public function invoke(handle: TermHandle):Future { + public function run(handle: ProcessHandle):Void { this.handle = handle; var subcommand = handle.args[0]; @@ -21,30 +21,37 @@ class GPS extends CLIApp { switch (subcommand) { case "set": - return Future.sync(setManuelPos(subcommand_args)); + handle.close(setManuelPos(subcommand_args)); case "status": - return Future.sync(getGPSStatus()); + handle.close(getGPSStatus()); case "locate": - kernel.gps.GPS.instance.locate(); - return Future.sync(true); + kernel.gps.GPS.instance.locate().handle((pos)->{ + if (pos != null) { + handle.writeLine('Position x:${pos.x} y:${pos.y} z:${pos.z}'); + handle.close(true); + } else { + handle.writeLine("Position not available"); + handle.close(false); + } + }); case "ins": - return INS.instance.align().isSuccess(); + INS.instance.align().handle(()->{ + handle.writeLine("INS aligned"); + handle.close(true); + }); default: - handle.writeLn("Unknown subcommand: " + subcommand); + handle.writeLine("Unknown subcommand: " + subcommand); printHelp(); - return Future.sync(false); - + handle.close(false); } - - return Future.sync(true); } private function printHelp(){ - handle.writeLn("GPS commands:"); - handle.writeLn("set - set manual position"); - handle.writeLn("status - get current position and accuracy"); - handle.writeLn("locate - get current position"); - handle.writeLn("ins - align INS"); + handle.writeLine("GPS commands:"); + handle.writeLine("set - set manual position"); + handle.writeLine("status - get current position and accuracy"); + handle.writeLine("locate - get current position"); + handle.writeLine("ins - align INS"); } private function setManuelPos(args: Array): Bool { @@ -63,26 +70,26 @@ class GPS extends CLIApp { var pos = kernel.gps.GPS.instance.getPosition(); if (pos != null) { - handle.writeLn('Position x:${pos.x} y:${pos.y} z:${pos.z}'); + handle.writeLine('Position x:${pos.x} y:${pos.y} z:${pos.z}'); } else { - handle.writeLn("Position not available"); + handle.writeLine("Position not available"); return true; } var acc = kernel.gps.GPS.instance.getAccuracy(); if (acc == 1){ - handle.writeLn("Accuracy: Low"); + handle.writeLine("Accuracy: Low"); } else if (acc == 2){ - handle.writeLn("Accuracy: Medium"); + handle.writeLine("Accuracy: Medium"); } else if (acc == 3){ - handle.writeLn("Accuracy: High"); + handle.writeLine("Accuracy: High"); } var ins = INS.instance.getHeading(); if (ins != null) { - handle.writeLn('INS heading: ${ins.x} y:${ins.y} z:${ins.z}'); + handle.writeLine('INS heading: ${ins.x} y:${ins.y} z:${ins.z}'); } else { - handle.writeLn("INS heading not available"); + handle.writeLine("INS heading not available"); } return true; diff --git a/src/bin/HelloWorld.hx b/src/bin/HelloWorld.hx index 2be0165..7a139f2 100644 --- a/src/bin/HelloWorld.hx +++ b/src/bin/HelloWorld.hx @@ -1,21 +1,16 @@ package bin; -import lib.cli.TermHandle; -import lib.cli.CLIApp; +import kernel.ps.ProcessHandle; +import kernel.ps.Process; using tink.CoreApi; -class HelloWorld extends CLIApp { +class HelloWorld implements Process { public function new() {} - public function invoke(handle: TermHandle):Future { - var world:String = "world"; - if (handle.args.length > 0) { - world = handle.args[0]; - } - - handle.write('Hello, $world!'); - return Future.sync(true); + public function run(handle:ProcessHandle) { + handle.write("Hello World!"); + handle.close(); } } diff --git a/src/bin/Net.hx b/src/bin/Net.hx index a5a2ec4..0026948 100644 --- a/src/bin/Net.hx +++ b/src/bin/Net.hx @@ -1,19 +1,19 @@ package bin; +import kernel.ps.ProcessHandle; +import kernel.ps.Process; import kernel.peripherals.Peripherals.Peripheral; import kernel.net.Routing; import haxe.ds.ReadOnlyArray; -import lib.cli.TermHandle; -import lib.cli.CLIApp; using tink.CoreApi; -class Net extends CLIApp { - private var handle:TermHandle; +class Net implements Process { + private var handle:ProcessHandle; public function new() {} - public function invoke(handle:TermHandle):Future { + public function run(handle:ProcessHandle):Void { this.handle = handle; var subcommand = handle.args[0]; @@ -21,86 +21,82 @@ class Net extends CLIApp { switch (subcommand) { case "route": - return Future.sync(route(subcommand_args)); + route(subcommand_args); + return handle.close(); case "iface": - return Future.sync(iface(subcommand_args)); + iface(subcommand_args); + return handle.close(); case "help": printHelp(); - return Future.sync(true); + return handle.close(); case "ping": - return ping(subcommand_args); + ping(subcommand_args); + // Closes itself case "proto": - return Future.sync(protos()); + protos(); + return handle.close(); default: - handle.writeLn("Unknown subcommand: " + subcommand); + handle.write("Unknown subcommand: " + subcommand); printHelp(); - return Future.sync(false); + return handle.close(false); } } private function printHelp() { - handle.writeLn("net route"); - handle.writeLn("net iface"); - handle.writeLn("net help"); - handle.writeLn("net proto"); + handle.write("net route"); + handle.write("net iface"); + handle.write("net help"); + handle.write("net proto"); } - private function route(args:ReadOnlyArray):Bool { + private function route(args:ReadOnlyArray):Void { var routes = Routing.instance.getRouteTable(); for(k => v in routes) { - handle.writeLn('${k} => ${v.interf.name()}(${v.cost})'); + handle.write('${k} => ${v.interf.name()}(${v.cost})'); } - - return true; } private function iface(args:ReadOnlyArray):Bool { var modems = Peripheral.instance.getModems(); for (modem in modems) { - handle.writeLn(modem.name()); + handle.write(modem.name()); } return true; } - function ping(args:ReadOnlyArray): Future { - return new Future(trigger -> { - if (args.length != 1) { - handle.writeLn("Usage: net ping id"); - trigger(false); - return null; + function ping(args:ReadOnlyArray): Void { + if (args.length != 1) { + handle.write("Usage: net ping id"); + return handle.close(false); + } + + var toID:Null = Std.parseInt(args[0]); + + if (toID == null) { + handle.write("Invalid ID"); + return handle.close(false); + } + + kernel.net.Net.instance.ping(toID).handle(result -> { + switch (result){ + case Success(_): + handle.write("Ping succeeded"); + return handle.close(); + case Failure(failure): + handle.write("Ping failed: " + failure); + return handle.close(false); } - - var toID:Null = Std.parseInt(args[0]); - - if (toID == null) { - handle.writeLn("Invalid ID"); - trigger(false); - return null; - } - - kernel.net.Net.instance.ping(toID).handle(result -> { - switch (result){ - case Success(_): - handle.writeLn("Ping succeeded"); - trigger(true); - case Failure(failure): - handle.writeLn("Ping failed: " + failure); - trigger(false); - } - }); }); } - function protos():Bool { + function protos():Void { var protos = kernel.net.Net.instance.getActiveProtocols(); for (proto in protos) { - handle.writeLn(proto); + handle.write(proto); } - - return true; } } diff --git a/src/bin/Redstone.hx b/src/bin/Redstone.hx index 8c620dc..a269341 100644 --- a/src/bin/Redstone.hx +++ b/src/bin/Redstone.hx @@ -1,27 +1,27 @@ package bin; +import kernel.ps.ProcessHandle; +import kernel.ps.Process; import kernel.peripherals.Peripherals.Peripheral; import kernel.peripherals.Side; -import lib.cli.TermHandle; -import lib.cli.CLIApp; using tink.CoreApi; -class Redstone extends CLIApp { +class Redstone implements Process { public function new() {} - public function invoke(handle:TermHandle):Future { + public function run(handle: ProcessHandle):Void { var subcommand = handle.args[0]; if (subcommand == null) { - handle.writeLn("Usage: redstone "); - return Future.sync(false); + handle.write("Usage: redstone "); + return handle.close(false); } var side:Null = handle.args[1]; if (side == null) { - handle.writeLn("Invalid side"); - return Future.sync(false); + handle.write("Invalid side"); + return handle.close(false); } switch (subcommand) { @@ -31,14 +31,14 @@ class Redstone extends CLIApp { Peripheral.instance.getRedstone(side).setOutput(false); case "get": var value = Peripheral.instance.getRedstone(side).getAnalogInput(); - handle.writeLn("Analog input: " + value); + handle.write("Analog input: " + value); case "help": - handle.writeLn("Usage: redstone "); + handle.write("Usage: redstone "); default: - handle.writeLn("Invalid subcommand"); - return Future.sync(false); + handle.write("Invalid subcommand"); + return handle.close(false); } - return Future.sync(true); + return handle.close(); } } diff --git a/src/bin/Terminal.hx b/src/bin/Terminal.hx index b7b3f1e..a221793 100644 --- a/src/bin/Terminal.hx +++ b/src/bin/Terminal.hx @@ -1,8 +1,9 @@ package bin; +import kernel.ps.Process; +import kernel.ps.ProcessManager; +import kernel.ps.ProcessHandle; import lib.ui.UIApp; -import lib.cli.TermHandle; -import lib.cli.CLIApp; import lib.Color; import kernel.ui.WindowContext; import kernel.ui.WindowManager; @@ -99,7 +100,17 @@ class Terminal extends UIApp { var commandArgs:Array = args.slice(1); var hadInput = false; - var handle = new TermHandle(commandArgs, { + + var ps = getProgByName(commandName); + if (ps == null) { + this.backlog.push("Unknown command: " + commandName); + this.redrawBacklog(); + this.redrawInput(); + return; + } + + ProcessManager.run(ps,{ + args: commandArgs, onWrite: (s:String) -> { if (!hadInput) { this.backlog.push(""); @@ -108,30 +119,16 @@ class Terminal extends UIApp { this.backlog[this.backlog.length - 1] += s; this.redrawBacklog(); }, - onNewLine: () -> { - this.backlog.push(""); - this.redrawBacklog(); + onExit: (success:Bool) -> { + if (this.backlog[this.backlog.length - 1] == "") { + this.backlog.pop(); + } + + this.redrawInput(); } }); - var prog:CLIApp = getProgByName(commandName); - - if (prog == null) { - this.backlog.push("Command not found: " + commandName); - this.redrawBacklog(); - return; - } - this.context.setCursorBlink(false); - - prog.invoke(handle).handle((exitCode) -> { - // Cleanup extra newline - if (this.backlog[this.backlog.length - 1] == "") { - this.backlog.pop(); - } - - this.redrawInput(); - }); } private function parseArgs(command:String):Array { @@ -144,7 +141,7 @@ class Terminal extends UIApp { this.redrawBacklog(); } - private function getProgByName(name:String):CLIApp { + private function getProgByName(name:String):Process { switch (name) { case "hello": return new HelloWorld(); diff --git a/src/lib/cli/CLIApp.hx b/src/lib/cli/CLIApp.hx deleted file mode 100644 index 7cb2950..0000000 --- a/src/lib/cli/CLIApp.hx +++ /dev/null @@ -1,7 +0,0 @@ -package lib.cli; - -using tink.CoreApi; - -abstract class CLIApp { - public abstract function invoke(handle: TermHandle): Future; -} diff --git a/src/lib/cli/TermHandle.hx b/src/lib/cli/TermHandle.hx deleted file mode 100644 index d6c1397..0000000 --- a/src/lib/cli/TermHandle.hx +++ /dev/null @@ -1,29 +0,0 @@ -package lib.cli; - -import haxe.ds.ReadOnlyArray; - -typedef TermHandleEvents = { - onWrite: String->Void, - onNewLine: Void->Void, -} - -class TermHandle { - public final args:ReadOnlyArray; - private final events:TermHandleEvents; - - @:allow(bin.Terminal) - private function new(args: Array, events: TermHandleEvents) { - this.args = args; - this.events = events; - } - - public function write(s:String) { - this.events.onWrite(s); - } - - public function writeLn(s:String = "") { - if (s != "") - this.events.onWrite(s); - this.events.onNewLine(); - } -}