diff --git a/README.md b/README.md index beacdf7..56e0cca 100644 --- a/README.md +++ b/README.md @@ -47,11 +47,11 @@ main = Task.err (Exit 1 "") cliParser = - Cli.weave { - alpha: <- Opt.u64 { short: "a", help: "Set the alpha level." }, - force: <- Opt.flag { short: "f", help: "Force the task to complete." }, - file: <- Param.maybeStr { name: "file", help: "The file to process." }, - files: <- Param.strList { name: "files", help: "The rest of the files." }, + { Cli.weave <- + alpha: Opt.u64 { short: "a", help: "Set the alpha level." }, + force: Opt.flag { short: "f", help: "Force the task to complete." }, + file: Param.maybeStr { name: "file", help: "The file to process." }, + files: Param.strList { name: "files", help: "The rest of the files." }, } |> Cli.finish { name: "basic", diff --git a/examples/basic.roc b/examples/basic.roc index 0e5cac5..e17e039 100644 --- a/examples/basic.roc +++ b/examples/basic.roc @@ -25,11 +25,11 @@ main = Task.err (Exit 1 "") cliParser = - Cli.weave { - alpha: <- Opt.u64 { short: "a", help: "Set the alpha level." }, - force: <- Opt.flag { short: "f", help: "Force the task to complete." }, - file: <- Param.maybeStr { name: "file", help: "The file to process." }, - files: <- Param.strList { name: "files", help: "The rest of the files." }, + { Cli.weave <- + alpha: Opt.u64 { short: "a", help: "Set the alpha level." }, + force: Opt.flag { short: "f", help: "Force the task to complete." }, + file: Param.maybeStr { name: "file", help: "The file to process." }, + files: Param.strList { name: "files", help: "The rest of the files." }, } |> Cli.finish { name: "basic", diff --git a/examples/default-values.roc b/examples/default-values.roc new file mode 100644 index 0000000..19c30c6 --- /dev/null +++ b/examples/default-values.roc @@ -0,0 +1,38 @@ +app [main] { + pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br", + weaver: "../package/main.roc", +} + +import pf.Stdout +import pf.Arg +import pf.Task exposing [Task] +import weaver.Opt +import weaver.Cli +import weaver.Param + +main = + args = Arg.list! + + when Cli.parseOrDisplayMessage cliParser args is + Ok data -> + Stdout.line! "Successfully parsed! Here's what I got:" + Stdout.line! "" + Stdout.line! (Inspect.toStr data) + + Err message -> + Stdout.line! message + + Task.err (Exit 1 "") + +cliParser = + { Cli.weave <- + alpha: Opt.maybeU64 { short: "a", long: "alpha", help: "Set the alpha level. [default: 123]" } + |> Cli.map \a -> Result.withDefault a 123,, + file: Param.maybeStr { name: "file", help: "The file to process. [default: NONE]" } + |> Cli.map \f -> Result.withDefault f "NONE", + } + |> Cli.finish { + name: "default-values", + version: "v0.0.1", + } + |> Cli.assertValid diff --git a/examples/single-arg.roc b/examples/single-arg.roc new file mode 100644 index 0000000..df17d06 --- /dev/null +++ b/examples/single-arg.roc @@ -0,0 +1,33 @@ +app [main] { + pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br", + weaver: "../package/main.roc", +} + +import pf.Stdout +import pf.Arg +import pf.Task exposing [Task] +import weaver.Opt +import weaver.Cli + +main = + args = Arg.list! + + when Cli.parseOrDisplayMessage cliParser args is + Ok data -> + Stdout.line! "Successfully parsed! Here's what I got:" + Stdout.line! "" + Stdout.line! (Inspect.toStr data) + + Err message -> + Stdout.line! message + + Task.err (Exit 1 "") + +cliParser = + Opt.u64 { short: "a", long: "alpha", help: "Set the alpha level." } + |> Cli.map Alpha + |> Cli.finish { + name: "single-arg", + version: "v0.0.1", + } + |> Cli.assertValid diff --git a/examples/subcommands.roc b/examples/subcommands.roc index bd81641..c3cffb7 100644 --- a/examples/subcommands.roc +++ b/examples/subcommands.roc @@ -26,11 +26,11 @@ main = Task.err (Exit 1 "") cliParser = - Cli.weave { - force: <- Opt.flag { short: "f", help: "Force the task to complete." }, - sc: <- Subcommand.optional [subcommandParser1, subcommandParser2], - file: <- Param.maybeStr { name: "file", help: "The file to process." }, - files: <- Param.strList { name: "files", help: "The rest of the files." }, + { Cli.weave <- + force: Opt.flag { short: "f", help: "Force the task to complete." }, + sc: Subcommand.optional [subcommandParser1, subcommandParser2], + file: Param.maybeStr { name: "file", help: "The file to process." }, + files: Param.strList { name: "files", help: "The rest of the files." }, } |> Cli.finish { name: "subcommands", @@ -41,17 +41,16 @@ cliParser = |> Cli.assertValid subcommandParser1 = - Cli.weave { - d: <- Opt.maybeU64 { short: "d", help: "A non-overlapping subcommand flag with s2." }, - volume: <- Opt.maybeU64 { short: "v", long: "volume", help: "How loud to grind the gears." }, - sc: <- Subcommand.optional [subSubcommandParser1, subSubcommandParser2], + { Cli.weave <- + d: Opt.maybeU64 { short: "d", help: "A non-overlapping subcommand flag with s2." }, + volume: Opt.maybeU64 { short: "v", long: "volume", help: "How loud to grind the gears." }, + sc: Subcommand.optional [subSubcommandParser1, subSubcommandParser2], } |> Subcommand.finish { name: "s1", description: "A first subcommand.", mapper: S1 } subcommandParser2 = - Cli.weave { - d: <- Opt.maybeU64 { short: "d", help: "This doesn't overlap with s1's -d flag." }, - } + Opt.maybeU64 { short: "d", help: "This doesn't overlap with s1's -d flag." } + |> Cli.map DFlag |> Subcommand.finish { name: "s2", description: "Another subcommand.", @@ -59,16 +58,16 @@ subcommandParser2 = } subSubcommandParser1 = - Cli.weave { - a: <- Opt.u64 { short: "a", help: "An example short flag for a sub-subcommand." }, - b: <- Opt.u64 { short: "b", help: "Another example short flag for a sub-subcommand." }, + { Cli.weave <- + a: Opt.u64 { short: "a", help: "An example short flag for a sub-subcommand." }, + b: Opt.u64 { short: "b", help: "Another example short flag for a sub-subcommand." }, } |> Subcommand.finish { name: "ss1", description: "A sub-subcommand.", mapper: SS1 } subSubcommandParser2 = - Cli.weave { - a: <- Opt.u64 { short: "a", help: "Set the alpha level." }, - c: <- Opt.u64 { short: "c", long: "create", help: "Create a doohickey." }, - data: <- Param.str { name: "data", help: "Data to manipulate." }, + { Cli.weave <- + a: Opt.u64 { short: "a", help: "Set the alpha level." }, + c: Opt.u64 { short: "c", long: "create", help: "Create a doohickey." }, + data: Param.str { name: "data", help: "Data to manipulate." }, } |> Subcommand.finish { name: "ss2", description: "Another sub-subcommand.", mapper: SS2 } diff --git a/package/Builder.roc b/package/Builder.roc index f99093c..1731c0a 100644 --- a/package/Builder.roc +++ b/package/Builder.roc @@ -3,12 +3,15 @@ module [ GetParamsAction, StopCollectingAction, CliBuilder, - fromState, - addOptions, - addParameters, + fromArgParser, + fromFullParser, + addOption, + addParameter, addSubcommands, updateParser, bindParser, + map, + combine, intoParts, checkForHelpAndVersion, ] @@ -18,6 +21,7 @@ import Base exposing [ ArgParserState, ArgParserResult, onSuccessfulArgParse, + mapSuccessfullyParsed, ArgExtractErr, OptionConfig, helpOption, @@ -31,35 +35,49 @@ GetOptionsAction : { getOptions : {} } GetParamsAction : { getParams : {} } StopCollectingAction : [] -CliBuilder state action := { - parser : ArgParser state, +CliBuilder data fromAction toAction := { + parser : ArgParser data, options : List OptionConfig, parameters : List ParameterConfig, subcommands : Dict Str SubcommandConfig, } -fromState : base -> CliBuilder base GetOptionsAction -fromState = \base -> +fromArgParser : (List Arg -> Result { data : data, remainingArgs : List Arg } ArgExtractErr) -> CliBuilder data fromAction toAction +fromArgParser = \parser -> + newParser = \{ args, subcommandPath } -> + when parser args is + Ok { data, remainingArgs } -> SuccessfullyParsed { data, remainingArgs, subcommandPath } + Err err -> IncorrectUsage err { subcommandPath } + + @CliBuilder { + parser: newParser, + options: [], + parameters: [], + subcommands: Dict.empty {}, + } + +fromFullParser : ArgParser data -> CliBuilder data fromAction toAction +fromFullParser = \parser -> @CliBuilder { - parser: \{ args, subcommandPath } -> SuccessfullyParsed { data: base, remainingArgs: args, subcommandPath }, + parser, options: [], parameters: [], subcommands: Dict.empty {}, } -addOptions : CliBuilder state action, List OptionConfig -> CliBuilder state action -addOptions = \@CliBuilder builder, newOptions -> - @CliBuilder { builder & options: List.concat builder.options newOptions } +addOption : CliBuilder state fromAction toAction, OptionConfig -> CliBuilder state fromAction toAction +addOption = \@CliBuilder builder, newOption -> + @CliBuilder { builder & options: List.append builder.options newOption } -addParameters : CliBuilder state action, List ParameterConfig -> CliBuilder state action -addParameters = \@CliBuilder builder, newParameters -> - @CliBuilder { builder & parameters: List.concat builder.parameters newParameters } +addParameter : CliBuilder state fromAction toAction, ParameterConfig -> CliBuilder state fromAction toAction +addParameter = \@CliBuilder builder, newParameter -> + @CliBuilder { builder & parameters: List.append builder.parameters newParameter } -addSubcommands : CliBuilder state action, Dict Str SubcommandConfig -> CliBuilder state action +addSubcommands : CliBuilder state fromAction toAction, Dict Str SubcommandConfig -> CliBuilder state fromAction toAction addSubcommands = \@CliBuilder builder, newSubcommands -> @CliBuilder { builder & subcommands: Dict.insertAll builder.subcommands newSubcommands } -setParser : CliBuilder state action, ArgParser nextState -> CliBuilder nextState nextAction +setParser : CliBuilder state fromAction toAction, ArgParser nextState -> CliBuilder nextState fromAction toAction setParser = \@CliBuilder builder, parser -> @CliBuilder { options: builder.options, @@ -68,7 +86,7 @@ setParser = \@CliBuilder builder, parser -> parser, } -updateParser : CliBuilder state action, ({ data : state, remainingArgs : List Arg } -> Result { data : nextState, remainingArgs : List Arg } ArgExtractErr) -> CliBuilder nextState nextAction +updateParser : CliBuilder state fromAction toAction, ({ data : state, remainingArgs : List Arg } -> Result { data : nextState, remainingArgs : List Arg } ArgExtractErr) -> CliBuilder nextState fromAction toAction updateParser = \@CliBuilder builder, updater -> newParser = { data, remainingArgs, subcommandPath } <- onSuccessfulArgParse builder.parser @@ -79,7 +97,7 @@ updateParser = \@CliBuilder builder, updater -> setParser (@CliBuilder builder) newParser -bindParser : CliBuilder state action, (ArgParserState state -> ArgParserResult (ArgParserState nextState)) -> CliBuilder nextState nextAction +bindParser : CliBuilder state fromAction toAction, (ArgParserState state -> ArgParserResult (ArgParserState nextState)) -> CliBuilder nextState fromAction toAction bindParser = \@CliBuilder builder, updater -> newParser : ArgParser nextState newParser = @@ -89,7 +107,7 @@ bindParser = \@CliBuilder builder, updater -> setParser (@CliBuilder builder) newParser intoParts : - CliBuilder state action + CliBuilder state fromAction toAction -> { parser : ArgParser state, options : List OptionConfig, @@ -98,6 +116,42 @@ intoParts : } intoParts = \@CliBuilder builder -> builder +map : CliBuilder a fromAction toAction, (a -> b) -> CliBuilder b fromAction toAction +map = \@CliBuilder builder, mapper -> + combinedParser = \input -> + builder.parser input + |> mapSuccessfullyParsed \{ data, remainingArgs, subcommandPath } -> + { data: mapper data, remainingArgs, subcommandPath } + + @CliBuilder { + parser: combinedParser, + options: builder.options, + parameters: builder.parameters, + subcommands: builder.subcommands, + } + +combine : CliBuilder a action1 action2, CliBuilder b action2 action3, (a, b -> c) -> CliBuilder c action1 action3 +combine = \@CliBuilder left, @CliBuilder right, combiner -> + combinedParser = \input -> + when left.parser input is + ShowVersion -> ShowVersion + ShowHelp sp -> ShowHelp sp + IncorrectUsage argExtractErr sp -> IncorrectUsage argExtractErr sp + SuccessfullyParsed { data, remainingArgs, subcommandPath } -> + when right.parser { args: remainingArgs, subcommandPath } is + ShowVersion -> ShowVersion + ShowHelp sp -> ShowHelp sp + IncorrectUsage argExtractErr sp -> IncorrectUsage argExtractErr sp + SuccessfullyParsed { data: data2, remainingArgs: restOfArgs, subcommandPath: nextSp } -> + SuccessfullyParsed { data: combiner data data2, remainingArgs: restOfArgs, subcommandPath: nextSp } + + @CliBuilder { + parser: combinedParser, + options: List.concat left.options right.options, + parameters: List.concat left.parameters right.parameters, + subcommands: Dict.insertAll left.subcommands right.subcommands, + } + flagWasPassed : OptionConfig, List Arg -> Bool flagWasPassed = \option, args -> List.any args \arg -> @@ -107,7 +161,7 @@ flagWasPassed = \option, args -> Long long -> long.name == option.long Parameter _p -> Bool.false -checkForHelpAndVersion : CliBuilder state action -> CliBuilder state action +checkForHelpAndVersion : CliBuilder state fromAction toAction -> CliBuilder state fromAction toAction checkForHelpAndVersion = \@CliBuilder builder -> newParser = \{ args, subcommandPath } -> when builder.parser { args, subcommandPath } is @@ -130,15 +184,15 @@ checkForHelpAndVersion = \@CliBuilder builder -> expect { parser } = - fromState (\x -> { x }) - |> updateParser \{ data, remainingArgs } -> Ok { data: data (Inspect.toStr remainingArgs), remainingArgs: [] } + fromArgParser \args -> Ok { data: Inspect.toStr args, remainingArgs: [] } + |> map Inspected |> intoParts out = parser { args: [Parameter "123"], subcommandPath: [] } out == SuccessfullyParsed { - data: { x: "[(Parameter \"123\")]" }, + data: Inspected "[(Parameter \"123\")]", remainingArgs: [], subcommandPath: [], } diff --git a/package/Cli.roc b/package/Cli.roc index 5aa5708..663ea47 100644 --- a/package/Cli.roc +++ b/package/Cli.roc @@ -1,4 +1,4 @@ -## Weave together a CLI parser using the `: <- ` builder notation! +## Weave together a CLI parser using the `<- ` builder notation! ## ## This module is the entry point for creating CLIs using Weaver. ## To get started, call the [weave] method and pass a @@ -9,10 +9,10 @@ ## you set. ## ## ```roc -## Cli.weave { -## alpha: <- Opt.u64 { short: "a", help: "Set the alpha level" }, -## verbosity: <- Opt.count { short: "v", long: "verbose", help: "How loud we should be." }, -## files: <- Param.strList { name: "files", help: "The files to process." }, +## { Cli.weave <- +## alpha: Opt.u64 { short: "a", help: "Set the alpha level" }, +## verbosity: Opt.count { short: "v", long: "verbose", help: "How loud we should be." }, +## files: Param.strList { name: "files", help: "The files to process." }, ## } ## |> Cli.finish { ## name: "example", @@ -27,12 +27,7 @@ ## ## ```roc ## fooSubcommand = -## Cli.weave { -## alpha: <- Opt.u64 { -## short: "a", -## help: "Set the alpha level", -## }, -## } +## Opt.u64 { short: "a", help: "Set the alpha level" } ## |> Subcommand.finish { ## name: "foo", ## description: "Foo some stuff." @@ -40,22 +35,18 @@ ## } ## ## barSubcommand = -## Cli.weave { -## # We allow two subcommands of the same parent to have overlapping -## # fields since only one can ever be parsed at a time. -## alpha: <- Opt.u64 { -## short: "a", -## help: "Set the alpha level", -## }, -## } +## # We allow two subcommands of the same parent to have overlapping +## # fields since only one can ever be parsed at a time. +## Opt.u64 { short: "a", help: "Set the alpha level" } ## |> Subcommand.finish { ## name: "bar", ## description: "Bar some stuff." ## mapper: Bar, ## } ## -## Cli.weave { -## sc: <- Subcommand.optional [fooSubcommand, barSubcommand], +## { Cli.weave <- +## verbosity: Opt.count { short: "v", long: "verbose" }, +## sc: Subcommand.optional [fooSubcommand, barSubcommand], ## } ## ``` ## @@ -70,10 +61,10 @@ ## ## ```roc ## cliParser = -## Cli.weave { -## alpha: <- Opt.u64 { short: "a", help: "Set the alpha level" }, -## verbosity: <- Opt.count { short: "v", long: "verbose", help: "How loud we should be." }, -## files: <- Param.strList { name: "files", help: "The files to process." }, +## { Cli.weave <- +## alpha: Opt.u64 { short: "a", help: "Set the alpha level" }, +## verbosity: Opt.count { short: "v", long: "verbose", help: "How loud we should be." }, +## files: Param.strList { name: "files", help: "The files to process." }, ## } ## |> Cli.finish { ## name: "example", @@ -101,6 +92,7 @@ ## _right order. Luckily, all of this is ensured at the type level._ module [ CliParser, + map, weave, finish, finishWithoutValidating, @@ -109,6 +101,7 @@ module [ ] import Opt +import Param import Base exposing [ TextStyle, ArgParserResult, @@ -118,7 +111,7 @@ import Base exposing [ mapSuccessfullyParsed, ] import Parser exposing [Arg, parseArgs] -import Builder exposing [CliBuilder, GetOptionsAction] +import Builder exposing [CliBuilder] import Validate exposing [validateCli, CliValidationErr] import ErrorFormatter exposing [ formatArgExtractErr, @@ -133,24 +126,49 @@ CliParser state : { textStyle : TextStyle, } -## Begin weaving together a CLI builder using the `: <- ` builder notation. +## Map over the parsed value of a Weaver field. ## -## Check the module-level documentation for general usage instructions. +## Useful for naming bare fields, or handling default values. ## ## ```roc ## expect ## { parser } = -## Cli.weave { -## verbosity: <- Opt.count { short: "v", long: "verbose" }, +## { Cli.weave <- +## verbosity: Opt.count { short: "v", long: "verbose" } +## |> Cli.map Verbosity, +## file: Param.maybeStr { name: "file" } +## |> Cli.map \f -> Result.withDefault f "NO_FILE", ## } ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-vvv"] -## == SuccessfullyParsed { verbosity: 3 } +## == SuccessfullyParsed { verbosity: Verbosity 3, file: "NO_FILE" } +## ``` +map : CliBuilder a fromAction toAction, (a -> b) -> CliBuilder b fromAction toAction +map = \builder, mapper -> + Builder.map builder mapper + +## Begin weaving together a CLI builder using the `<- ` builder notation. +## +## Check the module-level documentation for general usage instructions. +## +## ```roc +## expect +## { parser } = +## { Cli.weave <- +## verbosity: Opt.count { short: "v", long: "verbose" }, +## file: Param.str { name: "file" }, +## } +## |> Cli.finish { name: "example" } +## |> Cli.assertValid +## +## parser ["example", "file.txt", "-vvv"] +## == SuccessfullyParsed { verbosity: 3, file: "file.txt" } ## ``` -weave : base -> CliBuilder base GetOptionsAction -weave = \base -> Builder.fromState base +weave : CliBuilder a action1 action2, CliBuilder b action2 action3, (a, b -> c) -> CliBuilder c action1 action3 +weave = \left, right, combiner -> + Builder.combine left right combiner ## Fail the parsing process if any arguments are left over after parsing. ensureAllArgsWereParsed : List Arg -> Result {} ArgExtractErr @@ -198,20 +216,22 @@ ensureAllArgsWereParsed = \remainingArgs -> ## ## ```roc ## expect -## Cli.weave { -## verbosity: <- Opt.count { short: "v", long: "verbose" }, +## { Cli.weave <- +## verbosity: Opt.count { short: "v", long: "verbose" }, +## file: Param.str { name: "file" }, ## } ## |> Cli.finish { name: "example" } ## |> Result.isOk ## ## expect -## Cli.weave { -## verbosity: <- Opt.count { short: "" }, +## { Cli.weave <- +## verbosity: Opt.count { short: "" }, +## file: Param.str { name: "" }, ## } ## |> Cli.finish { name: "example" } ## |> Result.isErr ## ``` -finish : CliBuilder state action, CliConfigParams -> Result (CliParser state) CliValidationErr +finish : CliBuilder data fromAction toAction, CliConfigParams -> Result (CliParser data) CliValidationErr finish = \builder, params -> { parser, config, textStyle } = finishWithoutValidating builder params @@ -228,15 +248,16 @@ finish = \builder, params -> ## ```roc ## expect ## { parser } = -## Cli.weave { -## verbosity: <- Opt.count { short: "v", long: "verbose" }, +## { Cli.weave <- +## verbosity: Opt.count { short: "v", long: "verbose" }, +## file: Param.maybeStr { name: "file" }, ## } ## |> Cli.finishWithoutValidating { name: "example" } ## ## parser ["example", "-v", "-v"] -## == SuccessfullyParsed { verbosity: 2 } +## == SuccessfullyParsed { verbosity: 2, file: Err NoValue } ## ``` -finishWithoutValidating : CliBuilder state action, CliConfigParams -> CliParser state +finishWithoutValidating : CliBuilder data fromAction toAction, CliConfigParams -> CliParser data finishWithoutValidating = \builder, { name, authors ? [], version ? "", description ? "", textStyle ? Color } -> { options, parameters, subcommands, parser } = builder @@ -277,13 +298,11 @@ finishWithoutValidating = \builder, { name, authors ? [], version ? "", descript ## for correct parsing. ## ## ```roc -## Cli.weave { -## a: <- Opt.num { short: "a" } -## } +## Opt.num { short: "a" } ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ``` -assertValid : Result (CliParser state) CliValidationErr -> CliParser state +assertValid : Result (CliParser data) CliValidationErr -> CliParser data assertValid = \result -> when result is Ok cli -> cli @@ -304,8 +323,9 @@ assertValid = \result -> ## ## ```roc ## exampleCli = -## Cli.weave { -## verbosity: <- Opt.count { short: "v", help: "How verbose our logs should be." }, +## { Cli.weave <- +## verbosity: Opt.count { short: "v", long: "verbose" }, +## alpha: Opt.maybeNum { short: "a", long: "alpha" }, ## } ## |> Cli.finish { ## name: "example", @@ -328,6 +348,7 @@ assertValid = \result -> ## ## Options: ## -v How verbose our logs should be. +## -a, --alpha Set the alpha level. ## -h, --help Show this help page. ## -V, --version Show the version. ## """ @@ -353,7 +374,7 @@ assertValid = \result -> ## example [OPTIONS] ## """ ## ``` -parseOrDisplayMessage : CliParser state, List Str -> Result state Str +parseOrDisplayMessage : CliParser data, List Str -> Result data Str parseOrDisplayMessage = \parser, args -> when parser.parser args is SuccessfullyParsed data -> Ok data @@ -371,15 +392,21 @@ parseOrDisplayMessage = \parser, args -> Err incorrectUsageStr expect - Cli.weave { - verbosity: <- Opt.count { short: "v" }, - } + Opt.count { short: "v" } + |> Cli.map Verbosity |> Cli.finish { name: "empty" } |> Result.isOk expect - Cli.weave { - verbosity: <- Opt.count { short: "" }, - } + Opt.count { short: "" } + |> Cli.map Verbosity |> Cli.finish { name: "example" } |> Result.isErr + +expect + { Cli.weave <- + verbosity: Opt.count { short: "v" }, + points: Param.str { name: "points" }, + } + |> Cli.finish { name: "test" } + |> Result.isOk diff --git a/package/CliTest.roc b/package/CliTest.roc index f5628a9..ef38ba1 100644 --- a/package/CliTest.roc +++ b/package/CliTest.roc @@ -4,16 +4,15 @@ import Opt import Cli basicCli = - Cli.weave { - a: <- Opt.u64 { short: "a", help: "Set the alpha level." }, - } + Opt.u64 { short: "a", help: "Set the alpha level." } + |> Cli.map Alpha |> Cli.finish { name: "basic-cli", version: "v1.0.0", textStyle: Plain } |> Cli.assertValid expect basicCli |> Cli.parseOrDisplayMessage ["basic-cli", "-a", "123"] - == Ok { a: 123 } + == Ok (Alpha 123) expect helpMessage = diff --git a/package/Help.roc b/package/Help.roc index 991da63..aebd0bc 100644 --- a/package/Help.roc +++ b/package/Help.roc @@ -64,9 +64,7 @@ findSubcommand = \command, path -> ## ## ```roc ## exampleCli = -## Cli.weave { -## verbosity: <- Opt.count { short: "v", help: "How verbose our logs should be." }, -## } +## Opt.count { short: "v", help: "How verbose our logs should be." } ## |> Cli.finish { ## name: "example", ## version: "v0.1.0", @@ -160,9 +158,7 @@ helpText = \baseConfig, path, textStyle -> ## ## ```roc ## exampleCli = -## Cli.weave { -## verbosity: <- Opt.count { short: "v", help: "How verbose our logs should be." }, -## } +## Opt.count { short: "v", help: "How verbose our logs should be." } ## |> Cli.finish { ## name: "example", ## version: "v0.1.0", diff --git a/package/Opt.roc b/package/Opt.roc index a2d1148..5724ae9 100644 --- a/package/Opt.roc +++ b/package/Opt.roc @@ -61,17 +61,18 @@ import Base exposing [ import Extract exposing [extractOptionValues] import Parser exposing [ArgValue] -updateBuilderWithOptionParser : CliBuilder (a -> state) action, OptionConfig, (List ArgValue -> Result a ArgExtractErr) -> CliBuilder state nextAction -updateBuilderWithOptionParser = \builder, option, valueParser -> - builder - |> Builder.addOptions [option] - |> Builder.updateParser \{ data, remainingArgs } -> - { values, remainingArgs: restOfArgs } <- extractOptionValues { args: remainingArgs, option } +builderWithOptionParser : OptionConfig, (List ArgValue -> Result data ArgExtractErr) -> CliBuilder data fromAction toAction +builderWithOptionParser = \option, valueParser -> + argParser = \args -> + { values, remainingArgs } <- extractOptionValues { args, option } |> Result.try - value <- valueParser values + data <- valueParser values |> Result.try - Ok { data: data value, remainingArgs: restOfArgs } + Ok { data, remainingArgs } + + Builder.fromArgParser argParser + |> Builder.addOption option getSingleValue : List ArgValue, OptionConfig -> Result ArgValue ArgExtractErr getSingleValue = \values, option -> @@ -110,29 +111,28 @@ getMaybeValue = \values, option -> ## other -> Err (InvalidValue "'$(other)' is not a valid color, must be green, red, or blue") ## ## { parser } = -## Cli.weave { -## color: <- Opt.single { short: "c", parser: parseColor, type: "color" }, -## } +## Opt.single { short: "c", parser: parseColor, type: "color" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-c", "green"] -## == SuccessfullyParsed { answer: Green } +## == SuccessfullyParsed Green ## ``` -single : OptionConfigParams a -> (CliBuilder (a -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +single : OptionConfigParams a -> CliBuilder a GetOptionsAction GetOptionsAction single = \{ parser, type, short ? "", long ? "", help ? "" } -> option = { expectedValue: ExpectsValue type, plurality: One, short, long, help } - \builder -> - updateBuilderWithOptionParser builder option \values -> - argValue <- getSingleValue values option - |> Result.try - value <- argValue - |> Result.mapErr \NoValue -> NoValueProvidedForOption option - |> Result.try + valueParser = \values -> + argValue <- getSingleValue values option + |> Result.try + value <- argValue + |> Result.mapErr \NoValue -> NoValueProvidedForOption option + |> Result.try - parser value - |> Result.mapErr \err -> InvalidOptionValue err option + parser value + |> Result.mapErr \err -> InvalidOptionValue err option + + builderWithOptionParser option valueParser ## Add an optional option that takes a custom type to your CLI builder. ## @@ -158,21 +158,18 @@ single = \{ parser, type, short ? "", long ? "", help ? "" } -> ## other -> Err (InvalidValue "'$(other)' is not a valid color, must be green, red, or blue") ## ## { parser } = -## Cli.weave { -## color: <- Opt.maybe { short: "c", type: "color", parser: parseColor }, -## } +## Opt.maybe { short: "c", type: "color", parser: parseColor }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybe : OptionConfigParams a -> (CliBuilder (Result a [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybe : OptionConfigParams data -> CliBuilder (Result data [NoValue]) GetOptionsAction GetOptionsAction maybe = \{ parser, type, short ? "", long ? "", help ? "" } -> option = { expectedValue: ExpectsValue type, plurality: Optional, short, long, help } - \builder -> - values <- updateBuilderWithOptionParser builder option + valueParser = \values -> value <- getMaybeValue values option |> Result.try @@ -184,6 +181,8 @@ maybe = \{ parser, type, short ? "", long ? "", help ? "" } -> |> Result.map Ok |> Result.mapErr \err -> InvalidOptionValue err option + builderWithOptionParser option valueParser + ## Add an option that takes a custom type and can be given multiple times ## to your CLI builder. ## @@ -208,29 +207,27 @@ maybe = \{ parser, type, short ? "", long ? "", help ? "" } -> ## other -> Err (InvalidValue "'$(other)' is not a valid color, must be green, red, or blue") ## ## { parser } = -## Cli.weave { -## color: <- Opt.list { short: "c", type: "color", parser: parseColor }, -## } +## Opt.list { short: "c", type: "color", parser: parseColor }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-c", "green", "--color=red"] -## == SuccessfullyParsed { answer: [Green, Red] } +## == SuccessfullyParsed [Green, Red] ## ``` -list : OptionConfigParams a -> (CliBuilder (List a -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +list : OptionConfigParams data -> CliBuilder (List data) GetOptionsAction GetOptionsAction list = \{ parser, type, short ? "", long ? "", help ? "" } -> option = { expectedValue: ExpectsValue type, plurality: Many, short, long, help } - \builder -> - values <- updateBuilderWithOptionParser builder option - values - |> List.mapTry \value -> + valueParser = \values -> + List.mapTry values \value -> when value is Err NoValue -> Err (NoValueProvidedForOption option) Ok val -> parser val |> Result.mapErr \err -> InvalidOptionValue err option + builderWithOptionParser option valueParser + ## Add an optional flag to your CLI builder. ## ## Parsing arguments will fail if the flag is given more than once @@ -239,21 +236,18 @@ list = \{ parser, type, short ? "", long ? "", help ? "" } -> ## ```roc ## expect ## { parser } = -## Cli.weave { -## force: <- Opt.flag { short: "f", long: "force" }, -## } +## Opt.flag { short: "f", long: "force" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-f"] -## == SuccessfullyParsed { force: Bool.true } +## == SuccessfullyParsed Bool.true ## ``` -flag : OptionConfigBaseParams -> (CliBuilder (Bool -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +flag : OptionConfigBaseParams -> CliBuilder Bool GetOptionsAction GetOptionsAction flag = \{ short ? "", long ? "", help ? "" } -> option = { expectedValue: NothingExpected, plurality: Optional, short, long, help } - \builder -> - values <- updateBuilderWithOptionParser builder option + valueParser = \values -> value <- getMaybeValue values option |> Result.try @@ -262,6 +256,8 @@ flag = \{ short ? "", long ? "", help ? "" } -> Ok (Err NoValue) -> Ok Bool.true Ok (Ok _val) -> Err (OptionDoesNotExpectValue option) + builderWithOptionParser option valueParser + ## Add a flag that can be given multiple times to your CLI builder. ## ## Parsing arguments will fail if this flag is ever given a value, @@ -270,27 +266,25 @@ flag = \{ short ? "", long ? "", help ? "" } -> ## ```roc ## expect ## { parser } = -## Cli.weave { -## force: <- Opt.count { short: "f", long: "force" }, -## } +## Opt.count { short: "f", long: "force" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-f", "--force", "-fff"] -## == SuccessfullyParsed { force: 5 } +## == SuccessfullyParsed 5 ## ``` -count : OptionConfigBaseParams -> (CliBuilder (U64 -> state) GetOptionsAction -> CliBuilder state action) +count : OptionConfigBaseParams -> CliBuilder U64 GetOptionsAction GetOptionsAction count = \{ short ? "", long ? "", help ? "" } -> option = { expectedValue: NothingExpected, plurality: Many, short, long, help } - \builder -> - values <- updateBuilderWithOptionParser builder option - + valueParser = \values -> if values |> List.any Result.isOk then Err (OptionDoesNotExpectValue option) else Ok (List.len values) + builderWithOptionParser option valueParser + ## Add a required option that takes a string to your CLI builder. ## ## Parsing arguments will fail if the option is not given as an argument @@ -299,16 +293,14 @@ count = \{ short ? "", long ? "", help ? "" } -> ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.str { long: "answer" }, -## } +## Opt.str { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=abc"] -## == SuccessfullyParsed { answer: "abc" } +## == SuccessfullyParsed "abc" ## ``` -str : OptionConfigBaseParams -> (CliBuilder (Str -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +str : OptionConfigBaseParams -> CliBuilder Str GetOptionsAction GetOptionsAction str = \{ short ? "", long ? "", help ? "" } -> single { parser: Ok, type: strTypeName, short, long, help } ## Add an optional option that takes a string to your CLI builder. @@ -319,16 +311,14 @@ str = \{ short ? "", long ? "", help ? "" } -> single { parser: Ok, type: strTyp ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeStr { long: "answer" }, -## } +## Opt.maybeStr { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeStr : OptionConfigBaseParams -> (CliBuilder (Result Str [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeStr : OptionConfigBaseParams -> CliBuilder (Result Str [NoValue]) GetOptionsAction GetOptionsAction maybeStr = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Ok, type: strTypeName, short, long, help } ## Add an option that takes a string and can be given multiple times @@ -340,16 +330,14 @@ maybeStr = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Ok, type: st ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.strList { long: "answer" }, -## } +## Opt.strList { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "abc", "--answer", "def", "--answer=ghi"] -## == SuccessfullyParsed { answer: ["abc", "def", "ghi"] } +## == SuccessfullyParsed ["abc", "def", "ghi"] ## ``` -strList : OptionConfigBaseParams -> (CliBuilder (List Str -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +strList : OptionConfigBaseParams -> CliBuilder (List Str) GetOptionsAction GetOptionsAction strList = \{ short ? "", long ? "", help ? "" } -> list { parser: Ok, type: strTypeName, short, long, help } ## Add a required option that takes a `Dec` to your CLI builder. @@ -360,16 +348,14 @@ strList = \{ short ? "", long ? "", help ? "" } -> list { parser: Ok, type: strT ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.dec { long: "answer" }, -## } +## Opt.dec { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42.5"] -## == SuccessfullyParsed { answer: 42.5 } +## == SuccessfullyParsed 42.5 ## ``` -dec : OptionConfigBaseParams -> (CliBuilder (Dec -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +dec : OptionConfigBaseParams -> CliBuilder Dec GetOptionsAction GetOptionsAction dec = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toDec, type: numTypeName, short, long, help } ## Add an optional option that takes a `Dec` to your CLI builder. @@ -380,16 +366,14 @@ dec = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toDec, type: ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeDec { long: "answer" }, -## } +## Opt.maybeDec { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeDec : OptionConfigBaseParams -> (CliBuilder (Result Dec [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeDec : OptionConfigBaseParams -> CliBuilder (Result Dec [NoValue]) GetOptionsAction GetOptionsAction maybeDec = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toDec, type: numTypeName, short, long, help } ## Add an option that takes a `Dec` and can be given multiple times @@ -401,16 +385,14 @@ maybeDec = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toDec, t ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.decList { long: "answer" }, -## } +## Opt.decList { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "-3.0"] -## == SuccessfullyParsed { answer: [1.0, 2.0, -3.0] } +## == SuccessfullyParsed [1.0, 2.0, -3.0] ## ``` -decList : OptionConfigBaseParams -> (CliBuilder (List Dec -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +decList : OptionConfigBaseParams -> CliBuilder (List Dec) GetOptionsAction GetOptionsAction decList = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toDec, type: numTypeName, short, long, help } ## Add a required option that takes a `F32` to your CLI builder. @@ -421,16 +403,14 @@ decList = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toDec, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.f32 { long: "answer" }, -## } +## Opt.f32 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42.5"] -## == SuccessfullyParsed { answer: 42.5 } +## == SuccessfullyParsed 42.5 ## ``` -f32 : OptionConfigBaseParams -> (CliBuilder (F32 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +f32 : OptionConfigBaseParams -> CliBuilder F32 GetOptionsAction GetOptionsAction f32 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toF32, type: numTypeName, short, long, help } ## Add an optional option that takes a `F32` to your CLI builder. @@ -441,16 +421,14 @@ f32 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toF32, type: ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeF32 { long: "answer" }, -## } +## Opt.maybeF32 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeF32 : OptionConfigBaseParams -> (CliBuilder (Result F32 [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeF32 : OptionConfigBaseParams -> CliBuilder (Result F32 [NoValue]) GetOptionsAction GetOptionsAction maybeF32 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toF32, type: numTypeName, short, long, help } ## Add an option that takes a `F32` and can be given multiple times @@ -462,16 +440,14 @@ maybeF32 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toF32, t ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.f32List { long: "answer" }, -## } +## Opt.f32List { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "-3.0"] -## == SuccessfullyParsed { answer: [1.0, 2.0, -3.0] } +## == SuccessfullyParsed [1.0, 2.0, -3.0] ## ``` -f32List : OptionConfigBaseParams -> (CliBuilder (List F32 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +f32List : OptionConfigBaseParams -> CliBuilder (List F32) GetOptionsAction GetOptionsAction f32List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toF32, type: numTypeName, short, long, help } ## Add a required option that takes a `F64` to your CLI builder. @@ -482,16 +458,14 @@ f32List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toF32, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.f64 { long: "answer" }, -## } +## Opt.f64 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42.5"] -## == SuccessfullyParsed { answer: 42.5 } +## == SuccessfullyParsed 42.5 ## ``` -f64 : OptionConfigBaseParams -> (CliBuilder (F64 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +f64 : OptionConfigBaseParams -> CliBuilder F64 GetOptionsAction GetOptionsAction f64 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toF64, type: numTypeName, short, long, help } ## Add an optional option that takes a `F64` to your CLI builder. @@ -502,16 +476,14 @@ f64 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toF64, type: ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeF64 { long: "answer" }, -## } +## Opt.maybeF64 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeF64 : OptionConfigBaseParams -> (CliBuilder (Result F64 [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeF64 : OptionConfigBaseParams -> CliBuilder (Result F64 [NoValue]) GetOptionsAction GetOptionsAction maybeF64 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toF64, type: numTypeName, short, long, help } ## Add an option that takes a `F64` and can be given multiple times @@ -523,16 +495,14 @@ maybeF64 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toF64, t ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.f64List { long: "answer" }, -## } +## Opt.f64List { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "-3.0"] -## == SuccessfullyParsed { answer: [1.0, 2.0, -3.0] } +## == SuccessfullyParsed [1.0, 2.0, -3.0] ## ``` -f64List : OptionConfigBaseParams -> (CliBuilder (List F64 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +f64List : OptionConfigBaseParams -> CliBuilder (List F64) GetOptionsAction GetOptionsAction f64List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toF64, type: numTypeName, short, long, help } ## Add a required option that takes a `U8` to your CLI builder. @@ -543,16 +513,14 @@ f64List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toF64, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.u8 { long: "answer" }, -## } +## Opt.u8 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -u8 : OptionConfigBaseParams -> (CliBuilder (U8 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +u8 : OptionConfigBaseParams -> CliBuilder U8 GetOptionsAction GetOptionsAction u8 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toU8, type: numTypeName, short, long, help } ## Add an optional option that takes a `U8` to your CLI builder. @@ -563,16 +531,14 @@ u8 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toU8, type: n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeU8 { long: "answer" }, -## } +## Opt.maybeU8 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeU8 : OptionConfigBaseParams -> (CliBuilder (Result U8 [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeU8 : OptionConfigBaseParams -> CliBuilder (Result U8 [NoValue]) GetOptionsAction GetOptionsAction maybeU8 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toU8, type: numTypeName, short, long, help } ## Add an option that takes a `U8` and can be given multiple times @@ -584,16 +550,14 @@ maybeU8 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toU8, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.u8List { long: "answer" }, -## } +## Opt.u8List { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "3"] -## == SuccessfullyParsed { answer: [1, 2, 3] } +## == SuccessfullyParsed [1, 2, 3] ## ``` -u8List : OptionConfigBaseParams -> (CliBuilder (List U8 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +u8List : OptionConfigBaseParams -> CliBuilder (List U8) GetOptionsAction GetOptionsAction u8List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toU8, type: numTypeName, short, long, help } ## Add a required option that takes a `U16` to your CLI builder. @@ -604,16 +568,14 @@ u8List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toU8, type: ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.u16 { long: "answer" }, -## } +## Opt.u16 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -u16 : OptionConfigBaseParams -> (CliBuilder (U16 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +u16 : OptionConfigBaseParams -> CliBuilder U16 GetOptionsAction GetOptionsAction u16 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toU16, type: numTypeName, short, long, help } ## Add an optional option that takes a `U16` to your CLI builder. @@ -624,16 +586,14 @@ u16 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toU16, type: ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeU16 { long: "answer" }, -## } +## Opt.maybeU16 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeU16 : OptionConfigBaseParams -> (CliBuilder (Result U16 [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeU16 : OptionConfigBaseParams -> CliBuilder (Result U16 [NoValue]) GetOptionsAction GetOptionsAction maybeU16 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toU16, type: numTypeName, short, long, help } ## Add an option that takes a `U16` and can be given multiple times @@ -645,16 +605,14 @@ maybeU16 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toU16, t ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.u16List { long: "answer" }, -## } +## Opt.u16List { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "3"] -## == SuccessfullyParsed { answer: [1, 2, 3] } +## == SuccessfullyParsed [1, 2, 3] ## ``` -u16List : OptionConfigBaseParams -> (CliBuilder (List U16 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +u16List : OptionConfigBaseParams -> CliBuilder (List U16) GetOptionsAction GetOptionsAction u16List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toU16, type: numTypeName, short, long, help } ## Add a required option that takes a `U32` to your CLI builder. @@ -665,16 +623,14 @@ u16List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toU16, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.u32 { long: "answer" }, -## } +## Opt.u32 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -u32 : OptionConfigBaseParams -> (CliBuilder (U32 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +u32 : OptionConfigBaseParams -> CliBuilder U32 GetOptionsAction GetOptionsAction u32 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toU32, type: numTypeName, short, long, help } ## Add an optional option that takes a `U32` to your CLI builder. @@ -685,16 +641,14 @@ u32 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toU32, type: ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeU32 { long: "answer" }, -## } +## Opt.maybeU32 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeU32 : OptionConfigBaseParams -> (CliBuilder (Result U32 [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeU32 : OptionConfigBaseParams -> CliBuilder (Result U32 [NoValue]) GetOptionsAction GetOptionsAction maybeU32 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toU32, type: numTypeName, short, long, help } ## Add an option that takes a `U32` and can be given multiple times @@ -706,16 +660,14 @@ maybeU32 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toU32, t ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.u32List { long: "answer" }, -## } +## Opt.u32List { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "3"] -## == SuccessfullyParsed { answer: [1, 2, 3] } +## == SuccessfullyParsed [1, 2, 3] ## ``` -u32List : OptionConfigBaseParams -> (CliBuilder (List U32 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +u32List : OptionConfigBaseParams -> CliBuilder (List U32) GetOptionsAction GetOptionsAction u32List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toU32, type: numTypeName, short, long, help } ## Add a required option that takes a `U64` to your CLI builder. @@ -726,16 +678,14 @@ u32List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toU32, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.u64 { long: "answer" }, -## } +## Opt.u64 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -u64 : OptionConfigBaseParams -> (CliBuilder (U64 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +u64 : OptionConfigBaseParams -> CliBuilder U64 GetOptionsAction GetOptionsAction u64 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toU64, type: numTypeName, short, long, help } ## Add an optional option that takes a `U64` to your CLI builder. @@ -746,16 +696,14 @@ u64 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toU64, type: ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeU64 { long: "answer" }, -## } +## Opt.maybeU64 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeU64 : OptionConfigBaseParams -> (CliBuilder (Result U64 [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeU64 : OptionConfigBaseParams -> CliBuilder (Result U64 [NoValue]) GetOptionsAction GetOptionsAction maybeU64 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toU64, type: numTypeName, short, long, help } ## Add an option that takes a `U64` and can be given multiple times @@ -767,16 +715,14 @@ maybeU64 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toU64, t ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.u64List { long: "answer" }, -## } +## Opt.u64List { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "3"] -## == SuccessfullyParsed { answer: [1, 2, 3] } +## == SuccessfullyParsed [1, 2, 3] ## ``` -u64List : OptionConfigBaseParams -> (CliBuilder (List U64 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +u64List : OptionConfigBaseParams -> CliBuilder (List U64) GetOptionsAction GetOptionsAction u64List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toU64, type: numTypeName, short, long, help } ## Add a required option that takes a `U128` to your CLI builder. @@ -787,16 +733,14 @@ u64List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toU64, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.u128 { long: "answer" }, -## } +## Opt.u128 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -u128 : OptionConfigBaseParams -> (CliBuilder (U128 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +u128 : OptionConfigBaseParams -> CliBuilder U128 GetOptionsAction GetOptionsAction u128 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toU128, type: numTypeName, short, long, help } ## Add an optional option that takes a `U128` to your CLI builder. @@ -807,16 +751,14 @@ u128 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toU128, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeU128 { long: "answer" }, -## } +## Opt.maybeU128 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeU128 : OptionConfigBaseParams -> (CliBuilder (Result U128 [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeU128 : OptionConfigBaseParams -> CliBuilder (Result U128 [NoValue]) GetOptionsAction GetOptionsAction maybeU128 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toU128, type: numTypeName, short, long, help } ## Add an option that takes a `U128` and can be given multiple times @@ -828,16 +770,14 @@ maybeU128 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toU128, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.u128List { long: "answer" }, -## } +## Opt.u128List { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "3"] -## == SuccessfullyParsed { answer: [1, 2, 3] } +## == SuccessfullyParsed [1, 2, 3] ## ``` -u128List : OptionConfigBaseParams -> (CliBuilder (List U128 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +u128List : OptionConfigBaseParams -> CliBuilder (List U128) GetOptionsAction GetOptionsAction u128List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toU128, type: numTypeName, short, long, help } ## Add a required option that takes an `I8` to your CLI builder. @@ -848,16 +788,14 @@ u128List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toU128, t ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.i8 { long: "answer" }, -## } +## Opt.i8 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -i8 : OptionConfigBaseParams -> (CliBuilder (I8 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +i8 : OptionConfigBaseParams -> CliBuilder I8 GetOptionsAction GetOptionsAction i8 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toI8, type: numTypeName, short, long, help } ## Add an optional option that takes an `I8` to your CLI builder. @@ -868,16 +806,14 @@ i8 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toI8, type: n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeI8 { long: "answer" }, -## } +## Opt.maybeI8 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeI8 : OptionConfigBaseParams -> (CliBuilder (Result I8 [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeI8 : OptionConfigBaseParams -> CliBuilder (Result I8 [NoValue]) GetOptionsAction GetOptionsAction maybeI8 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toI8, type: numTypeName, short, long, help } ## Add an option that takes an `I8` and can be given multiple times @@ -889,16 +825,14 @@ maybeI8 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toI8, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.i8List { long: "answer" }, -## } +## Opt.i8List { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "3"] -## == SuccessfullyParsed { answer: [1, 2, 3] } +## == SuccessfullyParsed [1, 2, 3] ## ``` -i8List : OptionConfigBaseParams -> (CliBuilder (List I8 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +i8List : OptionConfigBaseParams -> CliBuilder (List I8) GetOptionsAction GetOptionsAction i8List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toI8, type: numTypeName, short, long, help } ## Add a required option that takes an `I16` to your CLI builder. @@ -909,16 +843,14 @@ i8List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toI8, type: ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.i16 { long: "answer" }, -## } +## Opt.i16 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -i16 : OptionConfigBaseParams -> (CliBuilder (I16 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +i16 : OptionConfigBaseParams -> CliBuilder I16 GetOptionsAction GetOptionsAction i16 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toI16, type: numTypeName, short, long, help } ## Add an optional option that takes an `I16` to your CLI builder. @@ -929,16 +861,14 @@ i16 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toI16, type: ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeI16 { long: "answer" }, -## } +## Opt.maybeI16 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeI16 : OptionConfigBaseParams -> (CliBuilder (Result I16 [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeI16 : OptionConfigBaseParams -> CliBuilder (Result I16 [NoValue]) GetOptionsAction GetOptionsAction maybeI16 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toI16, type: numTypeName, short, long, help } ## Add an option that takes an `I16` and can be given multiple times @@ -950,16 +880,14 @@ maybeI16 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toI16, t ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.i16List { long: "answer" }, -## } +## Opt.i16List { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "3"] -## == SuccessfullyParsed { answer: [1, 2, 3] } +## == SuccessfullyParsed [1, 2, 3] ## ``` -i16List : OptionConfigBaseParams -> (CliBuilder (List I16 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +i16List : OptionConfigBaseParams -> CliBuilder (List I16) GetOptionsAction GetOptionsAction i16List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toI16, type: numTypeName, short, long, help } ## Add a required option that takes an `I32` to your CLI builder. @@ -970,16 +898,14 @@ i16List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toI16, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.i32 { long: "answer" }, -## } +## Opt.i32 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -i32 : OptionConfigBaseParams -> (CliBuilder (I32 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +i32 : OptionConfigBaseParams -> CliBuilder I32 GetOptionsAction GetOptionsAction i32 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toI32, type: numTypeName, short, long, help } ## Add an optional option that takes an `I32` to your CLI builder. @@ -990,16 +916,14 @@ i32 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toI32, type: ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeI32 { long: "answer" }, -## } +## Opt.maybeI32 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeI32 : OptionConfigBaseParams -> (CliBuilder (Result I32 [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeI32 : OptionConfigBaseParams -> CliBuilder (Result I32 [NoValue]) GetOptionsAction GetOptionsAction maybeI32 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toI32, type: numTypeName, short, long, help } ## Add an option that takes an `I32` and can be given multiple times @@ -1011,16 +935,14 @@ maybeI32 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toI32, t ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.i32List { long: "answer" }, -## } +## Opt.i32List { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "3"] -## == SuccessfullyParsed { answer: [1, 2, 3] } +## == SuccessfullyParsed [1, 2, 3] ## ``` -i32List : OptionConfigBaseParams -> (CliBuilder (List I32 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +i32List : OptionConfigBaseParams -> CliBuilder (List I32) GetOptionsAction GetOptionsAction i32List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toI32, type: numTypeName, short, long, help } ## Add a required option that takes an `I64` to your CLI builder. @@ -1031,16 +953,14 @@ i32List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toI32, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.i64 { long: "answer" }, -## } +## Opt.i64 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -i64 : OptionConfigBaseParams -> (CliBuilder (I64 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +i64 : OptionConfigBaseParams -> CliBuilder I64 GetOptionsAction GetOptionsAction i64 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toI64, type: numTypeName, short, long, help } ## Add an optional option that takes an `I64` to your CLI builder. @@ -1051,16 +971,14 @@ i64 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toI64, type: ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeI64 { long: "answer" }, -## } +## Opt.maybeI64 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeI64 : OptionConfigBaseParams -> (CliBuilder (Result I64 [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeI64 : OptionConfigBaseParams -> CliBuilder (Result I64 [NoValue]) GetOptionsAction GetOptionsAction maybeI64 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toI64, type: numTypeName, short, long, help } ## Add an option that takes an `I64` and can be given multiple times @@ -1072,16 +990,14 @@ maybeI64 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toI64, t ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.i64List { long: "answer" }, -## } +## Opt.i64List { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "3"] -## == SuccessfullyParsed { answer: [1, 2, 3] } +## == SuccessfullyParsed [1, 2, 3] ## ``` -i64List : OptionConfigBaseParams -> (CliBuilder (List I64 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +i64List : OptionConfigBaseParams -> CliBuilder (List I64) GetOptionsAction GetOptionsAction i64List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toI64, type: numTypeName, short, long, help } ## Add a required option that takes an `I128` to your CLI builder. @@ -1092,16 +1008,14 @@ i64List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toI64, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.i128 { long: "answer" }, -## } +## Opt.i128 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "--answer=42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -i128 : OptionConfigBaseParams -> (CliBuilder (I128 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +i128 : OptionConfigBaseParams -> CliBuilder I128 GetOptionsAction GetOptionsAction i128 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toI128, type: numTypeName, short, long, help } ## Add an optional option that takes an `I128` to your CLI builder. @@ -1112,16 +1026,14 @@ i128 = \{ short ? "", long ? "", help ? "" } -> single { parser: Str.toI128, typ ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.maybeI128 { long: "answer" }, -## } +## Opt.maybeI128 { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeI128 : OptionConfigBaseParams -> (CliBuilder (Result I128 [NoValue] -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +maybeI128 : OptionConfigBaseParams -> CliBuilder (Result I128 [NoValue]) GetOptionsAction GetOptionsAction maybeI128 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toI128, type: numTypeName, short, long, help } ## Add an option that takes an `I128` and can be given multiple times @@ -1133,14 +1045,12 @@ maybeI128 = \{ short ? "", long ? "", help ? "" } -> maybe { parser: Str.toI128, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Opt.i128List { long: "answer" }, -## } +## Opt.i128List { long: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "-a", "1", "--answer=2", "--answer", "3"] -## == SuccessfullyParsed { answer: [1, 2, 3] } +## == SuccessfullyParsed [1, 2, 3] ## ``` -i128List : OptionConfigBaseParams -> (CliBuilder (List I128 -> state) GetOptionsAction -> CliBuilder state GetOptionsAction) +i128List : OptionConfigBaseParams -> CliBuilder (List I128) GetOptionsAction GetOptionsAction i128List = \{ short ? "", long ? "", help ? "" } -> list { parser: Str.toI128, type: numTypeName, short, long, help } diff --git a/package/Param.roc b/package/Param.roc index 27ac69e..28fd31c 100644 --- a/package/Param.roc +++ b/package/Param.roc @@ -62,17 +62,18 @@ import Base exposing [ import Parser exposing [ArgValue] import Extract exposing [extractParamValues] -updateBuilderWithParameterParser : CliBuilder (a -> state) action, ParameterConfig, (List Str -> Result a ArgExtractErr) -> CliBuilder state nextAction -updateBuilderWithParameterParser = \builder, param, valueParser -> - builder - |> Builder.addParameters [param] - |> Builder.updateParser \{ data, remainingArgs } -> - { values, remainingArgs: restOfArgs } <- extractParamValues { args: remainingArgs, param } +builderWithParameterParser : ParameterConfig, (List Str -> Result data ArgExtractErr) -> CliBuilder data fromAction toAction +builderWithParameterParser = \param, valueParser -> + argParser = \args -> + { values, remainingArgs } <- extractParamValues { args, param } |> Result.try - value <- valueParser values + data <- valueParser values |> Result.try - Ok { data: data value, remainingArgs: restOfArgs } + Ok { data, remainingArgs } + + Builder.fromArgParser argParser + |> Builder.addParameter param ## Add a required parameter of a custom type to your CLI builder. ## @@ -104,27 +105,26 @@ updateBuilderWithParameterParser = \builder, param, valueParser -> ## other -> Err (InvalidValue "'$(other)' is not a valid color, must be green, red, or blue") ## ## { parser } = -## Cli.weave { -## answer: <- Param.single { name: "answer", type: "color", parser: parseColor }, -## } +## Param.single { name: "answer", type: "color", parser: parseColor }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "blue"] -## == SuccessfullyParsed { answer: Blue } +## == SuccessfullyParsed Blue ## ``` -single : ParameterConfigParams a -> (CliBuilder (a -> state) {}action -> CliBuilder state GetParamsAction) +single : ParameterConfigParams state -> CliBuilder state {}action GetParamsAction single = \{ parser, type, name, help ? "" } -> param = { name, type, help, plurality: One } - \builder -> - values <- updateBuilderWithParameterParser builder param + valueParser = \values -> when List.first values is Err ListWasEmpty -> Err (MissingParam param) Ok singleValue -> parser singleValue |> Result.mapErr \err -> InvalidParamValue err param + builderWithParameterParser param valueParser + ## Add an optional parameter of a custom type to your CLI builder. ## ## You need to provide a kebab-case type name for your help messages as well as a @@ -154,21 +154,18 @@ single = \{ parser, type, name, help ? "" } -> ## other -> Err (InvalidValue "'$(other)' is not a valid color, must be green, red, or blue") ## ## { parser } = -## Cli.weave { -## answer: <- Param.maybe { name: "answer", type: "color", parser: parseColor }, -## } +## Param.maybe { name: "answer", type: "color", parser: parseColor }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybe : ParameterConfigParams a -> (CliBuilder (Result a [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybe : ParameterConfigParams data -> CliBuilder (Result data [NoValue]) {}action GetParamsAction maybe = \{ parser, type, name, help ? "" } -> param = { name, type, help, plurality: Optional } - \builder -> - values <- updateBuilderWithParameterParser builder param + valueParser = \values -> when List.first values is Err ListWasEmpty -> Ok (Err NoValue) Ok singleValue -> @@ -176,6 +173,8 @@ maybe = \{ parser, type, name, help ? "" } -> |> Result.map Ok |> Result.mapErr \err -> InvalidParamValue err param + builderWithParameterParser param valueParser + ## Add a parameter of a custom type that can be provided ## multiple times to your CLI builder. ## @@ -206,25 +205,23 @@ maybe = \{ parser, type, name, help ? "" } -> ## other -> Err (InvalidValue "'$(other)' is not a valid color, must be green, red, or blue") ## ## { parser } = -## Cli.weave { -## answer: <- Param.list { name: "answer", type: "color", parser: parseColor }, -## } +## Param.list { name: "answer", type: "color", parser: parseColor }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "blue", "red", "green"] -## == SuccessfullyParsed { answer: [Blue, Red, Green] } +## == SuccessfullyParsed [Blue, Red, Green] ## ``` -list : ParameterConfigParams a -> (CliBuilder (List a -> state) {}action -> CliBuilder state StopCollectingAction) +list : ParameterConfigParams data -> CliBuilder (List data) {}action StopCollectingAction list = \{ parser, type, name, help ? "" } -> param = { name, type, help, plurality: Many } - \builder -> - values <- updateBuilderWithParameterParser builder param - values - |> List.mapTry parser + valueParser = \values -> + List.mapTry values parser |> Result.mapErr \err -> InvalidParamValue err param + builderWithParameterParser param valueParser + ## Add a required string parameter to your CLI builder. ## ## Parsing arguments will fail if the parameter is not provided. @@ -232,16 +229,14 @@ list = \{ parser, type, name, help ? "" } -> ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.str { name: "answer" }, -## } +## Param.str { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "abc"] -## == SuccessfullyParsed { answer: "abc" } +## == SuccessfullyParsed "abc" ## ``` -str : ParameterConfigBaseParams -> (CliBuilder (Str -> state) {}action -> CliBuilder state GetParamsAction) +str : ParameterConfigBaseParams -> CliBuilder Str {}action GetParamsAction str = \{ name, help ? "" } -> single { parser: Ok, type: strTypeName, name, help } ## Add an optional string parameter to your CLI builder. @@ -251,16 +246,14 @@ str = \{ name, help ? "" } -> single { parser: Ok, type: strTypeName, name, help ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeStr { name: "answer" }, -## } +## Param.maybeStr { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeStr : ParameterConfigBaseParams -> (CliBuilder (ArgValue -> state) {}action -> CliBuilder state GetParamsAction) +maybeStr : ParameterConfigBaseParams -> CliBuilder ArgValue {}action GetParamsAction maybeStr = \{ name, help ? "" } -> maybe { parser: Ok, type: strTypeName, name, help } ## Add a string parameter that can be provided multiple times @@ -271,16 +264,14 @@ maybeStr = \{ name, help ? "" } -> maybe { parser: Ok, type: strTypeName, name, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.strList { name: "answer" }, -## } +## Param.strList { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "abc", "def", "ghi"] -## == SuccessfullyParsed { answer: ["abc", "def", "ghi"] } +## == SuccessfullyParsed ["abc", "def", "ghi"] ## ``` -strList : ParameterConfigBaseParams -> (CliBuilder (List Str -> state) {}action -> CliBuilder state StopCollectingAction) +strList : ParameterConfigBaseParams -> CliBuilder (List Str) {}action StopCollectingAction strList = \{ name, help ? "" } -> list { parser: Ok, type: strTypeName, name, help } ## Add a required `Dec` parameter to your CLI builder. @@ -291,16 +282,14 @@ strList = \{ name, help ? "" } -> list { parser: Ok, type: strTypeName, name, he ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.dec { name: "answer" }, -## } +## Param.dec { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42.5"] -## == SuccessfullyParsed { answer: 42.5 } +## == SuccessfullyParsed 42.5 ## ``` -dec : ParameterConfigBaseParams -> (CliBuilder (Dec -> state) {}action -> CliBuilder state GetParamsAction) +dec : ParameterConfigBaseParams -> CliBuilder Dec {}action GetParamsAction dec = \{ name, help ? "" } -> single { parser: Str.toDec, type: numTypeName, name, help } ## Add an optional `Dec` parameter to your CLI builder. @@ -310,16 +299,14 @@ dec = \{ name, help ? "" } -> single { parser: Str.toDec, type: numTypeName, nam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeDec { name: "answer" }, -## } +## Param.maybeDec { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeDec : ParameterConfigBaseParams -> (CliBuilder (Result Dec [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeDec : ParameterConfigBaseParams -> CliBuilder (Result Dec [NoValue]) {}action GetParamsAction maybeDec = \{ name, help ? "" } -> maybe { parser: Str.toDec, type: numTypeName, name, help } ## Add a `Dec` parameter that can be provided multiple times @@ -331,16 +318,14 @@ maybeDec = \{ name, help ? "" } -> maybe { parser: Str.toDec, type: numTypeName, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.decList { name: "answer" }, -## } +## Param.decList { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "--", "-56.0"] -## == SuccessfullyParsed { answer: [12.0, 34.0, -56.0] } +## == SuccessfullyParsed [12.0, 34.0, -56.0] ## ``` -decList : ParameterConfigBaseParams -> (CliBuilder (List Dec -> state) {}action -> CliBuilder state StopCollectingAction) +decList : ParameterConfigBaseParams -> CliBuilder (List Dec) {}action StopCollectingAction decList = \{ name, help ? "" } -> list { parser: Str.toDec, type: numTypeName, name, help } ## Add a required `F32` parameter to your CLI builder. @@ -351,16 +336,14 @@ decList = \{ name, help ? "" } -> list { parser: Str.toDec, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.f32 { name: "answer" }, -## } +## Param.f32 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42.5"] -## == SuccessfullyParsed { answer: 42.5 } +## == SuccessfullyParsed 42.5 ## ``` -f32 : ParameterConfigBaseParams -> (CliBuilder (F32 -> state) {}action -> CliBuilder state GetParamsAction) +f32 : ParameterConfigBaseParams -> CliBuilder F32 {}action GetParamsAction f32 = \{ name, help ? "" } -> single { parser: Str.toF32, type: numTypeName, name, help } ## Add an optional `F32` parameter to your CLI builder. @@ -370,16 +353,14 @@ f32 = \{ name, help ? "" } -> single { parser: Str.toF32, type: numTypeName, nam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeF32 { name: "answer" }, -## } +## Param.maybeF32 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeF32 : ParameterConfigBaseParams -> (CliBuilder (Result F32 [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeF32 : ParameterConfigBaseParams -> CliBuilder (Result F32 [NoValue]) {}action GetParamsAction maybeF32 = \{ name, help ? "" } -> maybe { parser: Str.toF32, type: numTypeName, name, help } ## Add a `F32` parameter that can be provided multiple times @@ -391,16 +372,14 @@ maybeF32 = \{ name, help ? "" } -> maybe { parser: Str.toF32, type: numTypeName, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.f32List { name: "answer" }, -## } +## Param.f32List { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "--", "-56.0"] -## == SuccessfullyParsed { answer: [12.0, 34.0, -56.0] } +## == SuccessfullyParsed [12.0, 34.0, -56.0] ## ``` -f32List : ParameterConfigBaseParams -> (CliBuilder (List F32 -> state) {}action -> CliBuilder state StopCollectingAction) +f32List : ParameterConfigBaseParams -> CliBuilder (List F32) {}action StopCollectingAction f32List = \{ name, help ? "" } -> list { parser: Str.toF32, type: numTypeName, name, help } ## Add a required `F64` parameter to your CLI builder. @@ -411,16 +390,14 @@ f32List = \{ name, help ? "" } -> list { parser: Str.toF32, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.f64 { name: "answer" }, -## } +## Param.f64 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42.5"] -## == SuccessfullyParsed { answer: 42.5 } +## == SuccessfullyParsed 42.5 ## ``` -f64 : ParameterConfigBaseParams -> (CliBuilder (F64 -> state) {}action -> CliBuilder state GetParamsAction) +f64 : ParameterConfigBaseParams -> CliBuilder F64 {}action GetParamsAction f64 = \{ name, help ? "" } -> single { parser: Str.toF64, type: numTypeName, name, help } ## Add an optional `F64` parameter to your CLI builder. @@ -430,16 +407,14 @@ f64 = \{ name, help ? "" } -> single { parser: Str.toF64, type: numTypeName, nam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeF64 { name: "answer" }, -## } +## Param.maybeF64 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeF64 : ParameterConfigBaseParams -> (CliBuilder (Result F64 [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeF64 : ParameterConfigBaseParams -> CliBuilder (Result F64 [NoValue]) {}action GetParamsAction maybeF64 = \{ name, help ? "" } -> maybe { parser: Str.toF64, type: numTypeName, name, help } ## Add a `F64` parameter that can be provided multiple times @@ -451,16 +426,14 @@ maybeF64 = \{ name, help ? "" } -> maybe { parser: Str.toF64, type: numTypeName, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.f64List { name: "answer" }, -## } +## Param.f64List { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "--", "-56.0"] -## == SuccessfullyParsed { answer: [12, 34, -56.0] } +## == SuccessfullyParsed [12, 34, -56.0] ## ``` -f64List : ParameterConfigBaseParams -> (CliBuilder (List F64 -> state) {}action -> CliBuilder state StopCollectingAction) +f64List : ParameterConfigBaseParams -> CliBuilder (List F64) {}action StopCollectingAction f64List = \{ name, help ? "" } -> list { parser: Str.toF64, type: numTypeName, name, help } ## Add a required `U8` parameter to your CLI builder. @@ -471,16 +444,14 @@ f64List = \{ name, help ? "" } -> list { parser: Str.toF64, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.u8 { name: "answer" }, -## } +## Param.u8 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -u8 : ParameterConfigBaseParams -> (CliBuilder (U8 -> state) {}action -> CliBuilder state GetParamsAction) +u8 : ParameterConfigBaseParams -> CliBuilder U8 {}action GetParamsAction u8 = \{ name, help ? "" } -> single { parser: Str.toU8, type: numTypeName, name, help } ## Add an optional `U8` parameter to your CLI builder. @@ -490,16 +461,14 @@ u8 = \{ name, help ? "" } -> single { parser: Str.toU8, type: numTypeName, name, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeU8 { name: "answer" }, -## } +## Param.maybeU8 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeU8 : ParameterConfigBaseParams -> (CliBuilder (Result U8 [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeU8 : ParameterConfigBaseParams -> CliBuilder (Result U8 [NoValue]) {}action GetParamsAction maybeU8 = \{ name, help ? "" } -> maybe { parser: Str.toU8, type: numTypeName, name, help } ## Add a `U8` parameter that can be provided multiple times @@ -511,16 +480,14 @@ maybeU8 = \{ name, help ? "" } -> maybe { parser: Str.toU8, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.u8List { name: "answer" }, -## } +## Param.u8List { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "56"] -## == SuccessfullyParsed { answer: [12, 34, 56] } +## == SuccessfullyParsed [12, 34, 56] ## ``` -u8List : ParameterConfigBaseParams -> (CliBuilder (List U8 -> state) {}action -> CliBuilder state StopCollectingAction) +u8List : ParameterConfigBaseParams -> CliBuilder (List U8) {}action StopCollectingAction u8List = \{ name, help ? "" } -> list { parser: Str.toU8, type: numTypeName, name, help } ## Add a required `U16` parameter to your CLI builder. @@ -531,16 +498,14 @@ u8List = \{ name, help ? "" } -> list { parser: Str.toU8, type: numTypeName, nam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.u16 { name: "answer" }, -## } +## Param.u16 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -u16 : ParameterConfigBaseParams -> (CliBuilder (U16 -> state) {}action -> CliBuilder state GetParamsAction) +u16 : ParameterConfigBaseParams -> CliBuilder U16 {}action GetParamsAction u16 = \{ name, help ? "" } -> single { parser: Str.toU16, type: numTypeName, name, help } ## Add an optional `U16` parameter to your CLI builder. @@ -550,16 +515,14 @@ u16 = \{ name, help ? "" } -> single { parser: Str.toU16, type: numTypeName, nam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeU16 { name: "answer" }, -## } +## Param.maybeU16 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeU16 : ParameterConfigBaseParams -> (CliBuilder (Result U16 [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeU16 : ParameterConfigBaseParams -> CliBuilder (Result U16 [NoValue]) {}action GetParamsAction maybeU16 = \{ name, help ? "" } -> maybe { parser: Str.toU16, type: numTypeName, name, help } ## Add a `U16` parameter that can be provided multiple times @@ -571,16 +534,14 @@ maybeU16 = \{ name, help ? "" } -> maybe { parser: Str.toU16, type: numTypeName, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.u16List { name: "answer" }, -## } +## Param.u16List { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "56"] -## == SuccessfullyParsed { answer: [12, 34, 56] } +## == SuccessfullyParsed [12, 34, 56] ## ``` -u16List : ParameterConfigBaseParams -> (CliBuilder (List U16 -> state) {}action -> CliBuilder state StopCollectingAction) +u16List : ParameterConfigBaseParams -> CliBuilder (List U16) {}action StopCollectingAction u16List = \{ name, help ? "" } -> list { parser: Str.toU16, type: numTypeName, name, help } ## Add a required `U32` parameter to your CLI builder. @@ -591,16 +552,14 @@ u16List = \{ name, help ? "" } -> list { parser: Str.toU16, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.u32 { name: "answer" }, -## } +## Param.u32 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -u32 : ParameterConfigBaseParams -> (CliBuilder (U32 -> state) {}action -> CliBuilder state GetParamsAction) +u32 : ParameterConfigBaseParams -> CliBuilder U32 {}action GetParamsAction u32 = \{ name, help ? "" } -> single { parser: Str.toU32, type: numTypeName, name, help } ## Add an optional `U32` parameter to your CLI builder. @@ -610,16 +569,14 @@ u32 = \{ name, help ? "" } -> single { parser: Str.toU32, type: numTypeName, nam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeU32 { name: "answer" }, -## } +## Param.maybeU32 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeU32 : ParameterConfigBaseParams -> (CliBuilder (Result U32 [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeU32 : ParameterConfigBaseParams -> CliBuilder (Result U32 [NoValue]) {}action GetParamsAction maybeU32 = \{ name, help ? "" } -> maybe { parser: Str.toU32, type: numTypeName, name, help } ## Add a `U32` parameter that can be provided multiple times @@ -631,16 +588,14 @@ maybeU32 = \{ name, help ? "" } -> maybe { parser: Str.toU32, type: numTypeName, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.u32List { name: "answer" }, -## } +## Param.u32List { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "56"] -## == SuccessfullyParsed { answer: [12, 34, 56] } +## == SuccessfullyParsed [12, 34, 56] ## ``` -u32List : ParameterConfigBaseParams -> (CliBuilder (List U32 -> state) {}action -> CliBuilder state StopCollectingAction) +u32List : ParameterConfigBaseParams -> CliBuilder (List U32) {}action StopCollectingAction u32List = \{ name, help ? "" } -> list { parser: Str.toU32, type: numTypeName, name, help } ## Add a required `U64` parameter to your CLI builder. @@ -651,16 +606,14 @@ u32List = \{ name, help ? "" } -> list { parser: Str.toU32, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.u64 { name: "answer" }, -## } +## Param.u64 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -u64 : ParameterConfigBaseParams -> (CliBuilder (U64 -> state) {}action -> CliBuilder state GetParamsAction) +u64 : ParameterConfigBaseParams -> CliBuilder U64 {}action GetParamsAction u64 = \{ name, help ? "" } -> single { parser: Str.toU64, type: numTypeName, name, help } ## Add an optional `U64` parameter to your CLI builder. @@ -670,16 +623,14 @@ u64 = \{ name, help ? "" } -> single { parser: Str.toU64, type: numTypeName, nam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeU64 { name: "answer" }, -## } +## Param.maybeU64 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeU64 : ParameterConfigBaseParams -> (CliBuilder (Result U64 [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeU64 : ParameterConfigBaseParams -> CliBuilder (Result U64 [NoValue]) {}action GetParamsAction maybeU64 = \{ name, help ? "" } -> maybe { parser: Str.toU64, type: numTypeName, name, help } ## Add a `U64` parameter that can be provided multiple times @@ -691,16 +642,14 @@ maybeU64 = \{ name, help ? "" } -> maybe { parser: Str.toU64, type: numTypeName, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.u64List { name: "answer" }, -## } +## Param.u64List { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "56"] -## == SuccessfullyParsed { answer: [12, 34, 56] } +## == SuccessfullyParsed [12, 34, 56] ## ``` -u64List : ParameterConfigBaseParams -> (CliBuilder (List U64 -> state) {}action -> CliBuilder state StopCollectingAction) +u64List : ParameterConfigBaseParams -> CliBuilder (List U64) {}action StopCollectingAction u64List = \{ name, help ? "" } -> list { parser: Str.toU64, type: numTypeName, name, help } ## Add a required `U128` parameter to your CLI builder. @@ -711,16 +660,14 @@ u64List = \{ name, help ? "" } -> list { parser: Str.toU64, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.u128 { name: "answer" }, -## } +## Param.u128 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -u128 : ParameterConfigBaseParams -> (CliBuilder (U128 -> state) {}action -> CliBuilder state GetParamsAction) +u128 : ParameterConfigBaseParams -> CliBuilder U128 {}action GetParamsAction u128 = \{ name, help ? "" } -> single { parser: Str.toU128, type: numTypeName, name, help } ## Add an optional `U128` parameter to your CLI builder. @@ -730,16 +677,14 @@ u128 = \{ name, help ? "" } -> single { parser: Str.toU128, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeU128 { name: "answer" }, -## } +## Param.maybeU128 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeU128 : ParameterConfigBaseParams -> (CliBuilder (Result U128 [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeU128 : ParameterConfigBaseParams -> CliBuilder (Result U128 [NoValue]) {}action GetParamsAction maybeU128 = \{ name, help ? "" } -> maybe { parser: Str.toU128, type: numTypeName, name, help } ## Add a `U128` parameter that can be provided multiple times @@ -751,16 +696,14 @@ maybeU128 = \{ name, help ? "" } -> maybe { parser: Str.toU128, type: numTypeNam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.u128List { name: "answer" }, -## } +## Param.u128List { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "56"] -## == SuccessfullyParsed { answer: [12, 34, 56] } +## == SuccessfullyParsed [12, 34, 56] ## ``` -u128List : ParameterConfigBaseParams -> (CliBuilder (List U128 -> state) {}action -> CliBuilder state StopCollectingAction) +u128List : ParameterConfigBaseParams -> CliBuilder (List U128) {}action StopCollectingAction u128List = \{ name, help ? "" } -> list { parser: Str.toU128, type: numTypeName, name, help } ## Add a required `I8` parameter to your CLI builder. @@ -771,16 +714,14 @@ u128List = \{ name, help ? "" } -> list { parser: Str.toU128, type: numTypeName, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.i8 { name: "answer" }, -## } +## Param.i8 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -i8 : ParameterConfigBaseParams -> (CliBuilder (I8 -> state) {}action -> CliBuilder state GetParamsAction) +i8 : ParameterConfigBaseParams -> CliBuilder I8 {}action GetParamsAction i8 = \{ name, help ? "" } -> single { parser: Str.toI8, type: numTypeName, name, help } ## Add an optional `I8` parameter to your CLI builder. @@ -790,16 +731,14 @@ i8 = \{ name, help ? "" } -> single { parser: Str.toI8, type: numTypeName, name, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeI8 { name: "answer" }, -## } +## Param.maybeI8 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeI8 : ParameterConfigBaseParams -> (CliBuilder (Result I8 [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeI8 : ParameterConfigBaseParams -> CliBuilder (Result I8 [NoValue]) {}action GetParamsAction maybeI8 = \{ name, help ? "" } -> maybe { parser: Str.toI8, type: numTypeName, name, help } ## Add an `I8` parameter that can be provided multiple times @@ -811,16 +750,14 @@ maybeI8 = \{ name, help ? "" } -> maybe { parser: Str.toI8, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.i8List { name: "answer" }, -## } +## Param.i8List { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "--", "-56"] -## == SuccessfullyParsed { answer: [12, 34, -56] } +## == SuccessfullyParsed [12, 34, -56] ## ``` -i8List : ParameterConfigBaseParams -> (CliBuilder (List I8 -> state) {}action -> CliBuilder state StopCollectingAction) +i8List : ParameterConfigBaseParams -> CliBuilder (List I8) {}action StopCollectingAction i8List = \{ name, help ? "" } -> list { parser: Str.toI8, type: numTypeName, name, help } ## Add a required `I16` parameter to your CLI builder. @@ -831,16 +768,14 @@ i8List = \{ name, help ? "" } -> list { parser: Str.toI8, type: numTypeName, nam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.i16 { name: "answer" }, -## } +## Param.i16 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -i16 : ParameterConfigBaseParams -> (CliBuilder (I16 -> state) {}action -> CliBuilder state GetParamsAction) +i16 : ParameterConfigBaseParams -> CliBuilder I16 {}action GetParamsAction i16 = \{ name, help ? "" } -> single { parser: Str.toI16, type: numTypeName, name, help } ## Add an optional `I16` parameter to your CLI builder. @@ -850,16 +785,14 @@ i16 = \{ name, help ? "" } -> single { parser: Str.toI16, type: numTypeName, nam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeI16 { name: "answer" }, -## } +## Param.maybeI16 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeI16 : ParameterConfigBaseParams -> (CliBuilder (Result I16 [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeI16 : ParameterConfigBaseParams -> CliBuilder (Result I16 [NoValue]) {}action GetParamsAction maybeI16 = \{ name, help ? "" } -> maybe { parser: Str.toI16, type: numTypeName, name, help } ## Add an `I16` parameter that can be provided multiple times @@ -871,16 +804,14 @@ maybeI16 = \{ name, help ? "" } -> maybe { parser: Str.toI16, type: numTypeName, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.i16List { name: "answer" }, -## } +## Param.i16List { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "--", "-56"] -## == SuccessfullyParsed { answer: [12, 34, -56] } +## == SuccessfullyParsed [12, 34, -56] ## ``` -i16List : ParameterConfigBaseParams -> (CliBuilder (List I16 -> state) {}action -> CliBuilder state StopCollectingAction) +i16List : ParameterConfigBaseParams -> CliBuilder (List I16) {}action StopCollectingAction i16List = \{ name, help ? "" } -> list { parser: Str.toI16, type: numTypeName, name, help } ## Add a required `I32` parameter to your CLI builder. @@ -891,16 +822,14 @@ i16List = \{ name, help ? "" } -> list { parser: Str.toI16, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.i32 { name: "answer" }, -## } +## Param.i32 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -i32 : ParameterConfigBaseParams -> (CliBuilder (I32 -> state) {}action -> CliBuilder state GetParamsAction) +i32 : ParameterConfigBaseParams -> CliBuilder I32 {}action GetParamsAction i32 = \{ name, help ? "" } -> single { parser: Str.toI32, type: numTypeName, name, help } ## Add an optional `I32` parameter to your CLI builder. @@ -910,16 +839,14 @@ i32 = \{ name, help ? "" } -> single { parser: Str.toI32, type: numTypeName, nam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeI32 { name: "answer" }, -## } +## Param.maybeI32 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeI32 : ParameterConfigBaseParams -> (CliBuilder (Result I32 [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeI32 : ParameterConfigBaseParams -> CliBuilder (Result I32 [NoValue]) {}action GetParamsAction maybeI32 = \{ name, help ? "" } -> maybe { parser: Str.toI32, type: numTypeName, name, help } ## Add an `I32` parameter that can be provided multiple times @@ -931,16 +858,14 @@ maybeI32 = \{ name, help ? "" } -> maybe { parser: Str.toI32, type: numTypeName, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.i32List { name: "answer" }, -## } +## Param.i32List { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "--", "-56"] -## == SuccessfullyParsed { answer: [12, 34, -56] } +## == SuccessfullyParsed [12, 34, -56] ## ``` -i32List : ParameterConfigBaseParams -> (CliBuilder (List I32 -> state) {}action -> CliBuilder state StopCollectingAction) +i32List : ParameterConfigBaseParams -> CliBuilder (List I32) {}action StopCollectingAction i32List = \{ name, help ? "" } -> list { parser: Str.toI32, type: numTypeName, name, help } ## Add a required `I64` parameter to your CLI builder. @@ -951,16 +876,14 @@ i32List = \{ name, help ? "" } -> list { parser: Str.toI32, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.i64 { name: "answer" }, -## } +## Param.i64 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -i64 : ParameterConfigBaseParams -> (CliBuilder (I64 -> state) {}action -> CliBuilder state GetParamsAction) +i64 : ParameterConfigBaseParams -> CliBuilder I64 {}action GetParamsAction i64 = \{ name, help ? "" } -> single { parser: Str.toI64, type: numTypeName, name, help } ## Add an optional `I64` parameter to your CLI builder. @@ -970,16 +893,14 @@ i64 = \{ name, help ? "" } -> single { parser: Str.toI64, type: numTypeName, nam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeI64 { name: "answer" }, -## } +## Param.maybeI64 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeI64 : ParameterConfigBaseParams -> (CliBuilder (Result I64 [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeI64 : ParameterConfigBaseParams -> CliBuilder (Result I64 [NoValue]) {}action GetParamsAction maybeI64 = \{ name, help ? "" } -> maybe { parser: Str.toI64, type: numTypeName, name, help } ## Add an `I64` parameter that can be provided multiple times @@ -991,16 +912,14 @@ maybeI64 = \{ name, help ? "" } -> maybe { parser: Str.toI64, type: numTypeName, ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.i64List { name: "answer" }, -## } +## Param.i64List { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "--", "-56"] -## == SuccessfullyParsed { answer: [12, 34, -56] } +## == SuccessfullyParsed [12, 34, -56] ## ``` -i64List : ParameterConfigBaseParams -> (CliBuilder (List I64 -> state) {}action -> CliBuilder state StopCollectingAction) +i64List : ParameterConfigBaseParams -> CliBuilder (List I64) {}action StopCollectingAction i64List = \{ name, help ? "" } -> list { parser: Str.toI64, type: numTypeName, name, help } ## Add a required `I128` parameter to your CLI builder. @@ -1011,16 +930,14 @@ i64List = \{ name, help ? "" } -> list { parser: Str.toI64, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.i128 { name: "answer" }, -## } +## Param.i128 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "42"] -## == SuccessfullyParsed { answer: 42 } +## == SuccessfullyParsed 42 ## ``` -i128 : ParameterConfigBaseParams -> (CliBuilder (I128 -> state) {}action -> CliBuilder state GetParamsAction) +i128 : ParameterConfigBaseParams -> CliBuilder I128 {}action GetParamsAction i128 = \{ name, help ? "" } -> single { parser: Str.toI128, type: numTypeName, name, help } ## Add an optional `I128` parameter to your CLI builder. @@ -1030,16 +947,14 @@ i128 = \{ name, help ? "" } -> single { parser: Str.toI128, type: numTypeName, n ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.maybeI128 { name: "answer" }, -## } +## Param.maybeI128 { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example"] -## == SuccessfullyParsed { answer: Err NoValue } +## == SuccessfullyParsed (Err NoValue) ## ``` -maybeI128 : ParameterConfigBaseParams -> (CliBuilder (Result I128 [NoValue] -> state) {}action -> CliBuilder state GetParamsAction) +maybeI128 : ParameterConfigBaseParams -> CliBuilder (Result I128 [NoValue]) {}action GetParamsAction maybeI128 = \{ name, help ? "" } -> maybe { parser: Str.toI128, type: numTypeName, name, help } ## Add an `I128` parameter that can be provided multiple times @@ -1051,14 +966,12 @@ maybeI128 = \{ name, help ? "" } -> maybe { parser: Str.toI128, type: numTypeNam ## ```roc ## expect ## { parser } = -## Cli.weave { -## answer: <- Param.i128List { name: "answer" }, -## } +## Param.i128List { name: "answer" }, ## |> Cli.finish { name: "example" } ## |> Cli.assertValid ## ## parser ["example", "12", "34", "--", "-56"] -## == SuccessfullyParsed { answer: [12, 34, -56] } +## == SuccessfullyParsed [12, 34, -56] ## ``` -i128List : ParameterConfigBaseParams -> (CliBuilder (List I128 -> state) {}action -> CliBuilder state StopCollectingAction) +i128List : ParameterConfigBaseParams -> CliBuilder (List I128) {}action StopCollectingAction i128List = \{ name, help ? "" } -> list { parser: Str.toI128, type: numTypeName, name, help } diff --git a/package/Subcommand.roc b/package/Subcommand.roc index fe6ab17..dac4d16 100644 --- a/package/Subcommand.roc +++ b/package/Subcommand.roc @@ -32,12 +32,13 @@ SubcommandParserConfig subState : { ## ## ```roc ## fooSubcommand = -## Cli.weave { -## foo: <- Opt.str { short: "f" }, +## { Cli.weave <- +## foo: Opt.str { short: "f" }, +## bar: Opt.str { short: "b" }, ## } -## |> Subcommand.finish { name: "foo", description: "Foo subcommand", mapper: Foo } +## |> Subcommand.finish { name: "foobar", description: "Foo and bar subcommand", mapper: FooBar } ## ``` -finish : CliBuilder state action, { name : Str, description ? Str, mapper : state -> commonState } -> { name : Str, parser : ArgParser commonState, config : SubcommandConfig } +finish : CliBuilder state fromAction toAction, { name : Str, description ? Str, mapper : state -> commonState } -> { name : Str, parser : ArgParser commonState, config : SubcommandConfig } finish = \builder, { name, description ? "", mapper } -> { options, parameters, subcommands, parser } = builder @@ -57,7 +58,7 @@ finish = \builder, { name, description ? "", mapper } -> ## Check the first parameter passed to see if a subcommand was called. getFirstArgToCheckForSubcommandCall : - ArgParserState x, + ArgParserState *, List (SubcommandParserConfig subState), (Result (SubcommandParserConfig subState) [NotFound] -> ArgParserResult (ArgParserState state)) -> ArgParserResult (ArgParserState state) @@ -93,52 +94,47 @@ getFirstArgToCheckForSubcommandCall = \{ remainingArgs, subcommandPath }, subcom ## ```roc ## expect ## fooSubcommand = -## Cli.weave { -## foo: <- Opt.str { short: "f" }, -## } +## Opt.str { short: "f" } ## |> Subcommand.finish { name: "foo", description: "Foo subcommand", mapper: Foo } ## ## barSubcommand = -## Cli.weave { -## bar: <- Opt.str { short: "b" }, -## } +## Opt.str { short: "b" } ## |> Subcommand.finish { name: "bar", description: "Bar subcommand", mapper: Bar } ## -## Cli.weave { -## sc: <- Subcommand.optional [fooSubcommand, barSubcommand], -## } -## |> Cli.finish { name: "example" } -## |> Cli.assertValid -## |> Cli.parseOrDisplayMessage ["example", "bar", "-b", "abc"] -## == Ok { sc: Ok (Bar { b: "abc" }) } +## { parser } = +## Subcommand.optional [fooSubcommand, barSubcommand], +## |> Cli.finish { name: "example" } +## |> Cli.assertValid +## +## parser ["example", "bar", "-b", "abc"] +## == SuccessfullyParsed (Ok (Bar "abc")) ## ``` -optional : List (SubcommandParserConfig subState) -> (CliBuilder (Result subState [NoSubcommand] -> state) GetOptionsAction -> CliBuilder state GetParamsAction) +optional : List (SubcommandParserConfig subState) -> CliBuilder (Result subState [NoSubcommand]) GetOptionsAction GetParamsAction optional = \subcommandConfigs -> subcommands = subcommandConfigs |> List.map \{ name, config } -> (name, config) |> Dict.fromList - \builder -> - builder - |> Builder.addSubcommands subcommands - |> Builder.bindParser \{ data, remainingArgs, subcommandPath } -> - subcommandFound <- getFirstArgToCheckForSubcommandCall { data, remainingArgs, subcommandPath } subcommandConfigs - + fullParser = \{ args, subcommandPath } -> + getFirstArgToCheckForSubcommandCall { data: {}, remainingArgs: args, subcommandPath } subcommandConfigs \subcommandFound -> when subcommandFound is Err NotFound -> - SuccessfullyParsed { data: data (Err NoSubcommand), remainingArgs, subcommandPath } + SuccessfullyParsed { data: Err NoSubcommand, remainingArgs: args, subcommandPath } Ok subcommand -> subParser = - { data: subData, remainingArgs: subRemainingArgs, subcommandPath: subSubcommandPath } <- onSuccessfulArgParse subcommand.parser - SuccessfullyParsed { data: data (Ok subData), remainingArgs: subRemainingArgs, subcommandPath: subSubcommandPath } + onSuccessfulArgParse subcommand.parser \{ data: subData, remainingArgs: subRemainingArgs, subcommandPath: subSubcommandPath } -> + SuccessfullyParsed { data: Ok subData, remainingArgs: subRemainingArgs, subcommandPath: subSubcommandPath } subParser { - args: List.dropFirst remainingArgs 1, + args: args |> List.dropFirst 1, subcommandPath: subcommandPath |> List.append subcommand.name, } + Builder.fromFullParser fullParser + |> Builder.addSubcommands subcommands + ## Use previously defined subcommands as data in a parent CLI builder. ## ## Once all options have been parsed, we then check the first parameter @@ -157,48 +153,43 @@ optional = \subcommandConfigs -> ## ```roc ## expect ## fooSubcommand = -## Cli.weave { -## foo: <- Opt.str { short: "f" }, -## } +## Opt.str { short: "f" } ## |> Subcommand.finish { name: "foo", description: "Foo subcommand", mapper: Foo } ## ## barSubcommand = -## Cli.weave { -## bar: <- Opt.str { short: "b" }, -## } +## Opt.str { short: "b" } ## |> Subcommand.finish { name: "bar", description: "Bar subcommand", mapper: Bar } ## -## Cli.weave { -## sc: <- Subcommand.required [fooSubcommand, barSubcommand], -## } -## |> Cli.finish { name: "example" } -## |> Cli.assertValid -## |> Cli.parseOrDisplayMessage ["example", "bar", "-b", "abc"] -## == Ok { sc: Bar { b: "abc" } } +## { parser } = +## Subcommand.required [fooSubcommand, barSubcommand], +## |> Cli.finish { name: "example" } +## |> Cli.assertValid +## +## parser ["example", "bar", "-b", "abc"] +## == SuccessfullyParsed (Bar "abc") ## ``` -required : List (SubcommandParserConfig subState) -> (CliBuilder (subState -> state) GetOptionsAction -> CliBuilder state GetParamsAction) +required : List (SubcommandParserConfig subData) -> CliBuilder subData GetOptionsAction GetParamsAction required = \subcommandConfigs -> subcommands = subcommandConfigs |> List.map \{ name, config } -> (name, config) |> Dict.fromList - \builder -> - builder - |> Builder.addSubcommands subcommands - |> Builder.bindParser \{ data, remainingArgs, subcommandPath } -> - subcommandFound <- getFirstArgToCheckForSubcommandCall { data, remainingArgs, subcommandPath } subcommandConfigs - + fullParser = \{ args, subcommandPath } -> + getFirstArgToCheckForSubcommandCall { data: {}, remainingArgs: args, subcommandPath } subcommandConfigs \subcommandFound -> when subcommandFound is Err NotFound -> IncorrectUsage NoSubcommandCalled { subcommandPath } Ok subcommand -> subParser = - { data: subData, remainingArgs: subRemainingArgs, subcommandPath: subSubcommandPath } <- onSuccessfulArgParse subcommand.parser - SuccessfullyParsed { data: data subData, remainingArgs: subRemainingArgs, subcommandPath: subSubcommandPath } + onSuccessfulArgParse subcommand.parser \{ data: subData, remainingArgs: subRemainingArgs, subcommandPath: subSubcommandPath } -> + SuccessfullyParsed { data: subData, remainingArgs: subRemainingArgs, subcommandPath: subSubcommandPath } subParser { - args: List.dropFirst remainingArgs 1, + args: args |> List.dropFirst 1, subcommandPath: subcommandPath |> List.append subcommand.name, } + + Builder.fromFullParser fullParser + |> Builder.addSubcommands subcommands