package bin; import lib.TermHandle; import lib.CLIBase; import util.Color; import kernel.ui.WindowContext; import kernel.ui.WindowManager; class Terminal { private var context:WindowContext; private var input:String = ""; private var backlog: Array = []; public function new() {} public function execute() { this.context = WindowManager.instance.createNewContext(); this.context.onChar.handle(char -> { this.input += char; this.redrawInput(); }); this.context.onKey.handle(e -> { if (e.keyCode == 259) { this.input = this.input.substr(0, this.input.length - 1); this.redrawInput(); } else if (e.keyCode == 257) { this.backlog.push("> " + this.input); var command = this.input; this.input = ""; this.redrawBacklog(); this.redrawInput(); this.invokeCommand(command); } }); WindowManager.instance.focusContextToOutput(context, "main"); this.redrawInput(); } private function redrawBacklog() { var size = this.context.getSize(); var linesAvailable = size.y - 1; var start:Int = this.backlog.length - linesAvailable; for (i in 0...linesAvailable){ var line = this.backlog[start + i]; this.context.setCursorPos(0, i); this.context.clearLine(); if (line != null) { this.context.write(line); } } this.moveCursorToInput(); } private function redrawInput() { var size = this.context.getSize(); this.context.setCursorPos(0, size.y - 1); this.context.clearLine(); this.context.setTextColor(Color.Blue); this.context.write("> "); this.context.setTextColor(Color.White); this.context.write(this.input); this.context.setCursorBlink(true); } private function invokeCommand(command: String):Void{ var args = this.parseArgs(command); if (args.length == 0) { return; } var commandName = args[0]; // Handle built-in commands switch (commandName) { case "clear": this.clear(); return; } var commandArgs:Array = args.slice(1); var hadInput = false; var handle = new TermHandle(commandArgs,{ onWrite: (s:String) -> { if (!hadInput) { this.backlog.push(""); hadInput = true; } this.backlog[this.backlog.length - 1] += s; this.redrawBacklog(); }, onNewLine: () -> { this.backlog.push(""); this.redrawBacklog(); } }); var prog:CLIBase = getProgByName(commandName); if (prog == null) { this.backlog.push("Command not found: " + commandName); this.redrawBacklog(); return; } this.context.setCursorBlink(false); prog.invoke(handle); // Cleanup extra newline if (this.backlog[this.backlog.length - 1] == "") { this.backlog.pop(); } this.redrawInput(); } private function parseArgs(command: String): Array { // TODO: tim and quote handling return command.split(" "); } private function clear() { this.backlog = []; this.redrawBacklog(); } private function getProgByName(name: String): CLIBase { switch (name) { case "hello": return new HelloWorld(); case "net": return new Net(); default: return null; } } private function moveCursorToInput() { var size = this.context.getSize(); this.context.setCursorPos(this.input.length + 2, size.y - 1); } }