partially applied string and float args to NAT commands

This commit is contained in:
2022-07-03 01:47:30 +00:00
parent d52209448c
commit f6a3e0e68f
2 changed files with 74 additions and 38 deletions

View File

@@ -2,6 +2,7 @@ package nat;
import kiss.Prelude; import kiss.Prelude;
import kiss.List; import kiss.List;
import kiss.Stream;
import haxe.Constraints; import haxe.Constraints;
import haxe.DynamicAccess; import haxe.DynamicAccess;
import uuid.Uuid; import uuid.Uuid;
@@ -25,6 +26,9 @@ enum CommandArgType {
// TODO VarTag // TODO VarTag
// TODO playground name -- choose from archive.playgrounds // TODO playground name -- choose from archive.playgrounds
// Then again the more of these I add the more convoluted CollectAndValidateArgs gets,
// and the more stream reader methods I need to write
} }
typedef CommandArg = { typedef CommandArg = {

View File

@@ -1,6 +1,6 @@
(load "Lib.kiss") (load "Lib.kiss")
(method :Void _collectAndValidateArg [:CommandArg arg :Dynamic->Void continuation] (method :Void _collectAndValidateArg [:CommandArg arg :Stream stream :Dynamic->Void continuation]
(case arg.type (case arg.type
(SelectedEntry (SelectedEntry
(if (= 1 _selectedEntries.length) (if (= 1 _selectedEntries.length)
@@ -15,32 +15,39 @@
(continuation _selectedEntries))) (continuation _selectedEntries)))
((Text maxLength) ((Text maxLength)
(unless maxLength (set maxLength Math.POSITIVE_INFINITY)) (unless maxLength (set maxLength Math.POSITIVE_INFINITY))
(ui.enterText (stream.dropWhitespace)
"${arg.name} (up to ${maxLength} characters):" (localFunction :Void trySubmit [text]
(lambda :Void [text] (if !(<= text.length maxLength)
(if !(<= text.length maxLength) (ui.reportError "The requested command expected a string up to $maxLength characters long. You entered: $text.length characters")
(ui.reportError "The requested command expected a string up to $maxLength characters long. You entered: $text.length characters") (continuation text)))
(continuation text))) (if (or (stream.isEmpty) (stream.dropStringIf "_"))
maxLength)) // If no text argument was pre-supplied, use the ui for it
(ui.enterText
"${arg.name} (up to ${maxLength} characters):"
trySubmit
maxLength))
(trySubmit (readString stream)))
((VarText maxLength) ((VarText maxLength)
(unless maxLength (set maxLength Math.POSITIVE_INFINITY)) (unless maxLength (set maxLength Math.POSITIVE_INFINITY))
(let [collectedText (let [collectedText []]
[]
&mut :Void->Void enterTextAgain
null (localFunction :Void enterTextAgain []
_enterTextAgain (localFunction :Void trySubmit [text]
->:Void (if !text
(continuation collectedText)
(if !(<= text.length maxLength)
(ui.reportError "The requested command expected a list of strings up to $maxLength characters long. You entered: $text.length characters")
{(collectedText.push text)
(enterTextAgain)})))
(if (or (stream.isEmpty) (stream.dropStringIf "_"))
// If no vartext argument was pre-supplied, use the ui for it
(ui.enterText (ui.enterText
"${arg.name} (up to ${maxLength} characters):" "${arg.name} (up to ${maxLength} characters):"
(lambda :Void [text] trySubmit
(if !text maxLength)
(continuation collectedText) (trySubmit (readString stream))))
(if !(<= text.length maxLength)
(ui.reportError "The requested command expected a list of strings up to $maxLength characters long. You entered: $text.length characters")
{(collectedText.push text)
(enterTextAgain)})))
maxLength)]
(set enterTextAgain _enterTextAgain)
(enterTextAgain))) (enterTextAgain)))
((Number min max inStepsOf) ((Number min max inStepsOf)
(unless min (set min Math.NEGATIVE_INFINITY)) (unless min (set min Math.NEGATIVE_INFINITY))
@@ -50,10 +57,8 @@
(+= prompt " in steps of ${inStepsOf}")) (+= prompt " in steps of ${inStepsOf}"))
(+= prompt "):") (+= prompt "):")
(ui.enterNumber (localFunction :Void trySubmit [number]
prompt (let [minMaxError
(lambda :Void [number]
(let [minMaxError
"The requested command expected a number between $min and $max" "The requested command expected a number between $min and $max"
stepError stepError
"$minMaxError in steps of $inStepsOf" "$minMaxError in steps of $inStepsOf"
@@ -66,9 +71,17 @@
(ui.reportError "${stepError}$youEntered") (ui.reportError "${stepError}$youEntered")
(ui.reportError "${minMaxError}$youEntered")) (ui.reportError "${minMaxError}$youEntered"))
(continuation number)))) (continuation number))))
min
max // If no text argument was pre-supplied, use the ui for it
inStepsOf))) (if (or (stream.isEmpty) (stream.dropStringIf "_"))
(ui.enterNumber
prompt
trySubmit
min
max
inStepsOf)
(trySubmit (readNumber stream)))))
(OneEntry (OneEntry
(ui.chooseEntry (ui.chooseEntry
"${arg.name}:" "${arg.name}:"
@@ -92,17 +105,36 @@
max)) max))
(null))) (null)))
(method :Void->Void _composeArgCollector [:Array<Dynamic> collectedArgs :CommandArg arg :Void->Void lastCollector] // TODO try catch and ui.reportError
(lambda :Void [] // TODO maaaybe support escape sequences?
(_collectAndValidateArg arg ->:Void [:Dynamic argValue] {(collectedArgs.push argValue) (lastCollector)}))) (function readString [:Stream stream]
(let [terminator
(case (stream.takeChars 1)
((Some "\"") "\"")
((Some "'") "'")
(otherwise (throw "string arg must start with \" or '")))]
(case (stream.takeUntilAndDrop terminator)
((Some s) s)
(otherwise (throw "string arg must end with $terminator")))))
(method :Void tryRunCommand [:String commandName] // TODO try catch and ui.reportError
(let [lowerCommandName (commandName.toLowerCase)] (function readNumber [:Stream stream]
(Std.parseFloat (case (stream.takeUntilOneOf [" "] true) ((Some f) f) (otherwise ""))))
(method :Void->Void _composeArgCollector [:Array<Dynamic> collectedArgs :CommandArg arg :Stream stream :Void->Void lastCollector]
(lambda :Void []
(_collectAndValidateArg arg stream ->:Void [:Dynamic argValue] {(collectedArgs.push argValue) (lastCollector)})))
(method :Void tryRunCommand [:String command]
(let [parts (command.split " ")
commandName (parts.shift)
stream (Stream.fromString (parts.join " "))
lowerCommandName (commandName.toLowerCase)]
(if (commands.exists lowerCommandName) (if (commands.exists lowerCommandName)
(_runCommand (dictGet commands lowerCommandName)) (_runCommand (dictGet commands lowerCommandName) stream)
(ui.reportError "$commandName is not a valid command")))) (ui.reportError "$commandName is not a valid command"))))
(method :Void _runCommand [:Command command] (method :Void _runCommand [:Command command :Stream stream]
(let [collectedArgs (let [collectedArgs
[] []
&mut lastCollector &mut lastCollector
@@ -111,7 +143,7 @@
(when lastChangeSet (ui.handleChanges archive lastChangeSet)))] (when lastChangeSet (ui.handleChanges archive lastChangeSet)))]
// To facilitate asynchronous arg input via UI, we need to construct an insanely complicated nested callback to give the UI // To facilitate asynchronous arg input via UI, we need to construct an insanely complicated nested callback to give the UI
(doFor arg (reverse command.args) (doFor arg (reverse command.args)
(set lastCollector (_composeArgCollector collectedArgs arg lastCollector))) (set lastCollector (_composeArgCollector collectedArgs arg stream lastCollector)))
(lastCollector))) (lastCollector)))