Unlike arguments, options are not ordered (meaning you can specify them in any order) and are specified with two dashes (e.g. --yell). Options are always optional, and can be setup to accept a value (e.g. --dir=src) or simply as a boolean flag without a value (e.g. --yell).
You can also declare a one-letter shortcut that you can call with a single dash (e.g. -y).
Note that to comply with the docopt standard, long options can specify their values after a white space or an =
sign (e.g. --iterations 5 or --iterations=5), but short options can only use white spaces or no separation at all (e.g. -i 5 or -i5).
There are five option variants you can use:
- ValueNone
- Do not accept input for this option (e.g. --yell).
- ValueRequired
- This value is required (e.g. --iterations=5 or -i5), the option itself is still optional;
- ValueOptional
- This option may or may not have a value (e.g. --yell or --yell=loud).
- ValueIsArray
- This option accepts multiple values (e.g. --dir=/foo --dir=/bar)
- ValueRequiredArray
- This option accepts multiple not empty values (e.g. --dir=/foo --dir=/bar)
Or Global options
Are built-in options, which every command has. And they are parsed before other given arguments. They may even bypass other values.
- Help (
--help
,-h
)- If only
--help
option is passed, it will show overall help for console application. - You can get help information for any command, if you pass a command name and
--help
option (this would ignore any other options).
- If only
- Version (
--version
,-V
)- This will show current application name and version. (Default name is
Console Application
)
- This will show current application name and version. (Default name is
- NoInteraction (
--no-interaction
,-n
)- You can suppress any interactive questions from the command you are running with this option.
- Quiet (
--quiet
,-q
)- You can suppress output with this option.
- Verbose (
--verbose
,-v|vv|vvv
)- You can get more verbose message (if this is supported for a command).
- Number of given
v
determines a level of verbosity.
There are many ways how to access Options:
-
Through pattern matching
let (optionValue: OptionValue option) = // raw value could be null or None or empty list match input with | Input.Option.Has "optionName" optionValue -> Some optionValue | _ -> None let (optionValue: OptionValue option) = // raw value is neither null nor None nor empty list match input with | Input.Option.IsSet "optionName" optionValue -> Some optionValue | _ -> None
- All Input active patterns for matching Options
Active Pattern Description Input.Option.IsDefined Matched when given string is defined as option name. Input.Option.Has Matched when given string has any value in current Input (default or from args). Input.Option.IsSet Matched when input has option AND that value is not empty. - Active patterns for accessing a value
Active Pattern Description Value Input.Option.Value Matched when input has option. (Fail with exception when value is not set or it is a list.) string
Input.Option.OptionalValue Matched when input has option AND it has a single value. string
Input.Option.ListValue Matched when input has option. string list
-
Just get a value from
Input
let optionValue: OptionValue option = input |> Input.Option.get "optionName" let optionValue: string = input |> Input.Option.value "optionName" // or exception let optionValue: string option = input |> Input.Option.asString "optionName" let optionValue: int option = input |> Input.Option.asInt "optionName" // or exception let optionValue: int option = input |> Input.Option.tryValueAsInt "optionName" let optionValue: string list = input |> Input.Option.asList "optionName"
- All Input functions for accessing Options
Function Description Input.Option.tryGet Returns an OptionValue option
, when Input has option.Input.Option.get Returns an OptionValue
, when Input has option OR fail with exception.Input.Option.value Returns a string
value from OptionValue, when Input has option OR fail with exception.Input.Option.asString Returns a string option
value from OptionValue, when Input has option.Input.Option.asInt Returns an int option
value from OptionValue, when Input has option. (It fails with an exception when string value is not int.)Input.Option.asList Returns an string list
value from OptionValue, when Input has option. (It returns a list even for single values.)Input.Option.tryAsInt Returns an int option
value from OptionValue, when Input has option. (It returns None when string value is not int.)Input.Option.isValueSet Checks whether option has a value AND that value is not empty. Note: All functions above will fail with an exception when given "option" is not defined.
-
Directly
Input.Options
- it isMap<string, OptionValue>
let optionValue: OptionValue = input.Options.["optionName"] // or exception
ValueDefinition | Has Default | In args | OptionValue |
---|---|---|---|
ValueNone | - | Yes | true |
- | No | false | |
ValueRequired | Yes | Yes | from Args |
Yes | No | default | |
ValueOptional | Yes | Yes | Some from Args |
Yes | No | Some default | |
No | Yes | Some from Args | |
No | No | None | |
ValueIsArray | Yes | Yes | [from Args] |
Yes | No | [default] | |
No | Yes | [from Args] | |
No | No | [] | |
ValueRequiredArray | Yes | Yes | [from Args] |
Yes | No | [default] | |
No | Yes | [from Args] |
You can use OptionValue
functions for all OptionValue
cases, but some of them may fail, see next table to clarify possibilities
// you may match value for "raw value"
// this might be unnecessary since you should know how option is defined (value corresponds)
match optionValue with
| OptionValue.ValueNone -> // ...
| OptionValue.ValueRequired rawValue -> // ...
| OptionValue.ValueOptional rawValueOption -> // ...
| OptionValue.ValueIsArray rawValues -> // ...
| OptionValue.ValueRequiredArray rawValues -> // ...
Or access OptionValue
with function by OptionValue definition
// for ValueNone use:
let (rawValue: bool) = optionValue |> OptionValue.isSet
// for ValueRequired use:
let (rawValue: string) = optionValue |> OptionValue.value
// for ValueOptional use:
let (rawValue: string option) = optionValue |> OptionValue.stringValue
// for ValueIsArray use:
let (rawValue: string list) = optionValue |> OptionValue.listValue
// for ValueRequiredArray use:
let (rawValue: string list) = optionValue |> OptionValue.listValue
Function | Value Definition | Value | Result |
---|---|---|---|
value | ValueNone | Yes | Exception |
No | Exception | ||
ValueRequired | Yes | string | |
ValueOptional | Yes | string | |
No | Exception | ||
ValueIsArray | Yes | Exception | |
No | Exception | ||
ValueRequiredArray | Yes | Exception | |
No | Exception | ||
stringValue | ValueNone | Yes | None |
No | None | ||
ValueRequired | Yes | Some string | |
ValueOptional | Yes | Some string | |
No | None | ||
ValueIsArray | Yes | None | |
No | None | ||
ValueRequiredArray | Yes | None | |
No | None | ||
intValue | ValueNone | Yes | None |
No | None | ||
ValueRequired | Yes | Some int or Exception | |
ValueOptional | Yes | Some int or Exception | |
No | None | ||
ValueIsArray | Yes | None | |
No | None | ||
ValueRequiredArray | Yes | None | |
No | None | ||
tryIntValue | ValueNone | Yes | None |
No | None | ||
ValueRequired | Yes | int option | |
ValueOptional | Yes | int option | |
No | None | ||
ValueIsArray | Yes | None | |
No | None | ||
ValueRequiredArray | Yes | None | |
No | None | ||
listValue | ValueNone | Yes | [] |
No | [] | ||
ValueRequired | Yes | [string] | |
ValueOptional | Yes | [string] | |
No | [] | ||
ValueIsArray | Yes | string list | |
No | [] | ||
ValueRequiredArray | Yes | string list | |
No | [] | ||
isSet | ValueNone | Yes | true |
No | false | ||
ValueRequired | Yes | true (unless value is null) | |
ValueOptional | Yes | true (unless value is null) | |
No | false | ||
ValueIsArray | Yes | true | |
No | false | ||
ValueRequiredArray | Yes | true | |
No | false |
How to handle edge-cases when the commands define options with required values, without values, etc.
Let's have a command, which define three options:
Options = [
Option.noValue "foo" (Some "f") ""
Option.required "bar" (Some "b") "" None
Option.optional "cat" (Some "c") "" None
]
Since the foo
option doesn't accept a value, it will be either false
(when it is not passed to the command) or true
(when --foo
was passed by the user). The value of the bar
option (and its b
shortcut respectively) is required. It can be separated from the option name either by spaces or = characters. The cat
option (and its c
shortcut) behaves similar except that it doesn't require a value. Have a look at the following table to get an overview of the possible ways to pass options:
Input | foo | bar | cat |
---|---|---|---|
--bar=Hello |
false |
"Hello" |
null |
--bar Hello |
false |
"Hello" |
null |
-b=Hello |
false |
"=Hello" |
null |
-b Hello |
false |
"Hello" |
null |
-bHello |
false |
"Hello" |
null |
-fcWorld -b Hello |
true |
"Hello" |
"World" |
-cfWorld -b Hello |
false |
"Hello" |
"fWorld" |
-cbWorld |
false |
null |
"bWorld" |
Things get a little bit more tricky when the command also accepts an optional argument:
Arguments = [
Argument.optional "arg" "Optional argument" None
]
You might have to use the special --
separator to separate options from arguments. Have a look at the fifth example in the following table where it is used to tell the command that World is the value for arg
and not the value of the optional cat
option:
Input | bar | cat | arg |
---|---|---|---|
--bar Hello |
"Hello" |
null |
null |
--bar Hello World |
"Hello" |
null |
"World" |
--bar "Hello World" |
"Hello World" |
null |
null |
--bar Hello --cat World |
"Hello" |
"World" |
null |
--bar Hello --cat -- World |
"Hello" |
null |
"World" |
-b Hello -c World |
"Hello" |
"World" |
null |