An OptionsParser
represents one possible way to interpret command line arguments.
A Cli.Program.Config
can be built up using one or more OptionsParser
s. It will
try each parser in order until one succeeds. If none succeed, it will print
an error message with information for the user of the Command-Line Interface.
You build up an OptionsParser
similarly to the way you build a decoder using the
elm-decode-pipeline
pattern. That is, you start the pipeline by giving it a constructor function,
and then for each argument of your constructor function, you have a corresponding
|> with (Option.someKindOfOption)
in the exact same order.
For example, if we define a type alias for a record with two attributes,
Elm generates a 2-argument constructor function for that record type. Here
Elm gives us a GreetOptions
function of the type String -> Maybe String -> GreetOptions
(this is just a core Elm language feature). That is, if we pass in a String
and
a Maybe String
as the 1st and 2nd arguments to the GreetOptions
function,
it will build up a record of that type.
So in this example, we call OptionsParser.build
with our GreetOptions
constructor function. Then we chain on with
once for each of those two arguments.
Note that the first with
will give us a String
, and the second will give us
a Maybe String
, so it matches up perfectly with the order of our constructor's
arguments.
import Cli.Option as Option
import Cli.OptionsParser as OptionsParser exposing (with)
import Cli.Program as Program
type alias GreetOptions =
{ name : String
, maybeGreeting : Maybe String
}
programConfig : Program.Config GreetOptions
programConfig =
Program.config
|> Program.add
(OptionsParser.build GreetOptions
|> with (Option.requiredKeywordArg "name")
|> with (Option.optionalKeywordArg "greeting")
)
build : cliOptions -> OptionsParser cliOptions BuilderState.AnyOptions
Start an OptionsParser
pipeline with no sub-command (see
the OptionsParser terminilogy legend).
buildSubCommand : String -> cliOptions -> OptionsParser cliOptions BuilderState.AnyOptions
Start an OptionsParser
pipeline with a sub-command (see
the OptionsParser terminilogy legend).
Cli.Option.Option
s To The PipelineMost options can be chained on using with
. There are two exceptions,
restArgs
and optionalPositionalArg
s. elm-cli-options-parser
enforces that
they are added in an unambiguous order (see the Cli.OptionsParser.BuilderState
docs).
So instead of using with
, you add them with their corresponding with...
functions.
import Cli.Option
import Cli.OptionsParser as OptionsParser exposing (with)
type GitOptionsParser
= Init
| Log LogOptions -- ...
type alias LogOptions =
{ maybeAuthorPattern : Maybe String
, maybeNumberToDisplay : Maybe Int
}
logOptionsParser =
OptionsParser.buildSubCommand "log" LogOptions
|> with (Option.optionalKeywordArg "author")
|> with
(Option.optionalKeywordArg "max-count"
|> Option.validateMapIfPresent String.toInt
)
|> with (Option.flag "stat")
|> OptionsParser.withOptionalPositionalArg
(Option.optionalPositionalArg "revision range")
|> OptionsParser.withRestArgs
(Option.restArgs "rest args")
The User of the Command-Line Interface will get an error message if there is no
OptionsParser
that succeeds. And an OptionsParser
will only succeed if
a valid number of positional arguments is passed in, as defined by these rules:
restArgs
with : Cli.Option.Option from to Cli.Option.BeginningOption -> OptionsParser (to -> cliOptions) BuilderState.AnyOptions -> OptionsParser cliOptions BuilderState.AnyOptions
For chaining on any Cli.Option.Option
besides a restArg
or an optionalPositionalArg
.
See the Cli.Option
module.
withOptionalPositionalArg : Cli.Option.Option from to Cli.Option.OptionalPositionalArgOption -> OptionsParser (to -> cliOptions) BuilderState.AnyOptions -> OptionsParser cliOptions BuilderState.NoBeginningOptions
For chaining on Cli.Option.optionalPositionalArg
s.
withRestArgs : Cli.Option.Option from to Cli.Option.RestArgsOption -> OptionsParser (to -> cliOptions) startingBuilderState -> OptionsParser cliOptions BuilderState.NoMoreOptions
For chaining on Cli.Option.restArgs
.
expectFlag : String -> OptionsParser cliOptions BuilderState.AnyOptions -> OptionsParser cliOptions BuilderState.AnyOptions
The OptionsParser
will only match if the given flag is present. Often its
best to use a subcommand in these cases.
map : (cliOptions -> mappedCliOptions) -> OptionsParser cliOptions builderState -> OptionsParser mappedCliOptions builderState
Map the CLI options returned in the OptionsParser
using the supplied map function.
This is very handy when you want a type alias for a record with options for a
a given OptionsParser
, but you need all of your OptionsParser
to map into
a single union type.
import Cli.Option as Option
import Cli.OptionsParser as OptionsParser
import Cli.Program as Program
import Ports
type CliOptions
= Hello HelloOptions
| Goodbye GoodbyeOptions
type alias HelloOptions =
{ name : String
, maybeHello : Maybe String
}
type alias GoodbyeOptions =
{ name : String
, maybeGoodbye : Maybe String
}
programConfig : Program.Config CliOptions
programConfig =
Program.config
|> Program.add
(OptionsParser.buildSubCommand "hello" HelloOptions
|> OptionsParser.with (Option.requiredKeywordArg "name")
|> OptionsParser.with (Option.optionalKeywordArg "greeting")
|> OptionsParser.map Hello
)
|> Program.add
(OptionsParser.buildSubCommand "goodbye" GoodbyeOptions
|> OptionsParser.with (Option.requiredKeywordArg "name")
|> OptionsParser.with (Option.optionalKeywordArg "goodbye")
|> OptionsParser.map Goodbye
)
hardcoded : value -> OptionsParser (value -> cliOptions) BuilderState.AnyOptions -> OptionsParser cliOptions BuilderState.AnyOptions
Use a fixed value for the next step in the pipeline. This doesn't use any input from the user, it just passes the supplied value through in the chain.
import Cli.Option as Option
import Cli.OptionsParser as OptionsParser
import Cli.Program as Program
type alias GreetOptions =
{ name : String
, maybeGreeting : Maybe String
, hardcodedValue : String
}
programConfig : Program.Config GreetOptions
programConfig =
Program.config
|> Program.add
(OptionsParser.build GreetOptions
|> OptionsParser.with (Option.requiredKeywordArg "name")
|> OptionsParser.with (Option.optionalKeywordArg "greeting")
|> OptionsParser.hardcoded "any hardcoded value"
)
withDoc : String -> OptionsParser cliOptions anything -> OptionsParser cliOptions anything
Add documentation for the optionsParser.
The output shows up after a #
in the help output:
$ git --help
git init # initialize a git repository
...
import Cli.OptionsParser as OptionsParser exposing (OptionsParser, with)
type GitOptionsParser =
Init
| Clone String
gitInitOptionsParser : OptionsParser GitOptionsParser
gitInitOptionsParser =
OptionsParser.build Init
|> OptionsParser.end
|> OptionsParser.withDoc "initialize a git repository"
You shouldn't need to use these functions to build a command line utility.
getSubCommand : OptionsParser cliOptions builderState -> Maybe String
Low-level function, for internal use.
getUsageSpecs : OptionsParser decodesTo builderState -> List Cli.UsageSpec.UsageSpec
Low-level function, for internal use.
synopsis : String -> OptionsParser decodesTo builderState -> String
Low-level function, for internal use.
tryMatch : List String -> OptionsParser cliOptions builderState -> MatchResult cliOptions
Low-level function, for internal use.
end : OptionsParser cliOptions builderState -> OptionsParser cliOptions BuilderState.NoMoreOptions
Low-level function, for internal use.