(load "Lib.kiss") (defun :Void main [] (let [[archiveDir] (Sys.args) controller (new ArchiveController (new Archive archiveDir) (new CLI))] (loop (Sys.print ">> ") (let [command (.trim (.toString (.readLine (Sys.stdin))))] (controller.runCommand (dictGet controller.commands command)))))) (defnew []) (defmethod :Void enterText [prompt resolve minLength maxLength] (Sys.print "$prompt ") (loop (let [entered (.toString (.readLine (Sys.stdin)))] (if !(<= minLength entered.length maxLength) (Sys.print "Try again? ") {(resolve entered) (break)})))) (defmethod :Void enterNumber [prompt resolve min max &opt inStepsOf] (Sys.print "$prompt ") (loop (let [entered (Std.parseFloat (.toString (.readLine (Sys.stdin))))] (if (or !(<= min entered max) (and inStepsOf !(= 0 (% (- entered min) inStepsOf)))) (Sys.print "Try again? ") {(resolve entered) (break)})))) (defmethod :Void chooseEntry [prompt :Archive archive resolve] // TODO allow narrowing down with a tag string (enterText "entry name for $prompt" ->name { (let [matchingEntries []] (.process (archive.addSystem (stringComponentSystem archive Name name (lambda [archive e] (matchingEntries.push e)))) archive) (case (the Array matchingEntries) ([e] (resolve e)) // TODO disambiguate entries with the same names by listing stringified versions of them and using enterNumber (multipleEntries (throw "ambiguous between multiple entries"))))} 0 Math.POSITIVE_INFINITY)) (defmethod :Void chooseEntries [prompt archive resolve min max] (resolve [])) (defmethod handleChanges [changeSet]) (defmethod :Void displayMessage [message] (print message)) (defmethod :Void reportError [error] ~error)