add Numbers arg type
This commit is contained in:
@@ -21,6 +21,8 @@ enum CommandArgType {
|
||||
VarText(maxLength:Null<Float>);
|
||||
// Numerical input, can be forced to align with a fixed step from the minimum
|
||||
Number(min:Null<Float>, max:Null<Float>, inStepsOf:Null<Float>);
|
||||
// Any number of numerical inputs, can be forced to align with a fixed step from the minimum
|
||||
Numbers(min:Null<Float>, max:Null<Float>, inStepsOf:Null<Float>);
|
||||
// Make the user select Entry(s) when called interactively
|
||||
OneEntry; // This constructor must be disambiguated from the typedef "Entry"
|
||||
Entries(min:Null<Int>, max:Null<Int>);
|
||||
|
@@ -86,7 +86,46 @@
|
||||
max
|
||||
inStepsOf)
|
||||
(trySubmit (readNumber stream)))))
|
||||
((Numbers min max inStepsOf)
|
||||
(unless min (set min Math.NEGATIVE_INFINITY))
|
||||
(unless max (set max Math.POSITIVE_INFINITY))
|
||||
(stream.dropWhitespace)
|
||||
(let [&mut prompt "${arg.name} (${min}-${max}"
|
||||
collectedNumbers []]
|
||||
(when inStepsOf
|
||||
(+= prompt " in steps of ${inStepsOf}"))
|
||||
(+= prompt "):")
|
||||
(localFunction :Void enterNumAgain []
|
||||
(localFunction :Void trySubmit [number]
|
||||
(stream.dropWhitespace)
|
||||
(let [minMaxError
|
||||
"The requested command expected numbers between $min and $max"
|
||||
stepError
|
||||
"$minMaxError in steps of $inStepsOf"
|
||||
youEntered
|
||||
". You entered: $number"]
|
||||
(if (Math.isNaN number)
|
||||
(continuation collectedNumbers)
|
||||
(if (or
|
||||
!(<= min number max)
|
||||
(and inStepsOf !(= 0 (% (- number min) inStepsOf))))
|
||||
(if inStepsOf
|
||||
(ui.reportError "${stepError}$youEntered")
|
||||
(ui.reportError "${minMaxError}$youEntered"))
|
||||
{(collectedNumbers.push number)
|
||||
(enterNumAgain)}))))
|
||||
|
||||
(if (or (stream.isEmpty) (stream.dropStringIf "_"))
|
||||
// If no vartext argument was pre-supplied, use the ui for it
|
||||
(ui.enterNumber
|
||||
prompt
|
||||
trySubmit
|
||||
min
|
||||
max
|
||||
inStepsOf
|
||||
true)
|
||||
(trySubmit (readNumber stream))))
|
||||
(enterNumAgain)))
|
||||
(OneEntry
|
||||
(ui.chooseEntry
|
||||
"${arg.name}:"
|
||||
@@ -220,6 +259,7 @@
|
||||
(TagsFromAll `:Array<String> ,name)
|
||||
(TagsFromSelected `:Array<String> ,name)
|
||||
((Number _ _ _) `:Float ,name)
|
||||
((Numbers _ _ _) `:Array<Float> ,name)
|
||||
(Position `:Position ,name)))
|
||||
commandArgs
|
||||
(for [name type] argPairs
|
||||
|
@@ -34,7 +34,7 @@ interface ArchiveUI {
|
||||
/**
|
||||
* Prompt the user to enter a number
|
||||
*/
|
||||
function enterNumber(prompt:String, resolve:(Float) -> Void, min:Float, max:Float, ?inStepsOf:Float):Void;
|
||||
function enterNumber(prompt:String, resolve:(Float) -> Void, min:Float, max:Float, ?inStepsOf:Float, ?allowNaN:Bool):Void;
|
||||
|
||||
/**
|
||||
* Prompt the user to choose a single Entry
|
||||
|
@@ -27,34 +27,35 @@
|
||||
{(resolve entered)
|
||||
(break)}))))
|
||||
|
||||
(method :Void enterNumber [prompt :Float->Void resolve :Float min :Float max &opt :Float inStepsOf]
|
||||
(method :Void enterNumber [prompt :Float->Void resolve :Float min :Float max &opt :Float inStepsOf :Bool allowNaN]
|
||||
(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)}))))
|
||||
(and (or !allowNaN !(Math.isNaN entered))
|
||||
(or
|
||||
!(<= min entered max)
|
||||
(and inStepsOf !(= 0 (% (- entered min) inStepsOf)))))
|
||||
(Sys.print "Try again? ")
|
||||
{(resolve entered)
|
||||
(break)}))))
|
||||
|
||||
(method :Void chooseEntry [prompt :Archive archive :Entry->Void resolve]
|
||||
(_chooseEntry prompt archive resolve ->(chooseEntry "empty name doesn't match any entries. Try again?" archive resolve)))
|
||||
(method :Void chooseEntry [prompt :Archive archive :Entry->Void resolve]
|
||||
(_chooseEntry prompt archive resolve ->(chooseEntry "empty name doesn't match any entries. Try again?" archive resolve)))
|
||||
|
||||
(method :Void _chooseEntry [prompt :Archive archive :Entry->Void resolve :Void->Void onEmptyString]
|
||||
// TODO allow narrowing down with a tag string
|
||||
(enterText "entry name for $prompt"
|
||||
->:Void name {
|
||||
(if !name
|
||||
(onEmptyString)
|
||||
(let [matchingEntries (controller.nameSystem.getEntries name)]
|
||||
(case (the Array<Entry> matchingEntries)
|
||||
([e] (resolve e))
|
||||
([] (chooseEntry "name $name doesn't match any entries. Try again?" archive resolve))
|
||||
// TODO disambiguate entries with the same names by listing stringified versions of them and using enterNumber
|
||||
(multipleEntries (throw "ambiguous between multiple entries"))
|
||||
(otherwise))))}
|
||||
(method :Void _chooseEntry [prompt :Archive archive :Entry->Void resolve :Void->Void onEmptyString]
|
||||
// TODO allow narrowing down with a tag string
|
||||
(enterText "entry name for $prompt"
|
||||
->:Void name {
|
||||
(if !name
|
||||
(onEmptyString)
|
||||
(let [matchingEntries (controller.nameSystem.getEntries name)]
|
||||
(case (the Array<Entry> matchingEntries)
|
||||
([e] (resolve e))
|
||||
([] (chooseEntry "name $name doesn't match any entries. Try again?" archive resolve))
|
||||
// TODO disambiguate entries with the same names by listing stringified versions of them and using enterNumber
|
||||
(multipleEntries (throw "ambiguous between multiple entries"))
|
||||
(otherwise))))}
|
||||
Math.POSITIVE_INFINITY))
|
||||
|
||||
(method :Void chooseEntries [prompt archive :Array<nat.Entry>->Void resolve min max]
|
||||
|
@@ -149,14 +149,13 @@
|
||||
(otherwise {}))))
|
||||
(uiWindow.addControl textInput))
|
||||
|
||||
(method :Void enterNumber [prompt resolve min max &opt inStepsOf]
|
||||
(method :Void enterNumber [prompt resolve min max &opt inStepsOf allowNaN]
|
||||
(enterText prompt
|
||||
->:Void [numberStr]
|
||||
(let [number
|
||||
(try (Std.parseFloat numberStr)
|
||||
(catch [e]
|
||||
(reportError "Not a number: $numberStr")
|
||||
(return)))]
|
||||
(let [number (Std.parseFloat numberStr)]
|
||||
(when (and !allowNaN (Math.isNaN number))
|
||||
(reportError "Not a number: $numberStr")
|
||||
(return))
|
||||
(resolve number))
|
||||
Math.POSITIVE_INFINITY))
|
||||
|
||||
|
Reference in New Issue
Block a user