Skip to content
NebelFox edited this page Feb 18, 2022 · 1 revision

Type matching

Each argument is matched by the corresponding parameter type.
Mismatched input aborts the command execution:

new BoxBuilder()
   .Type<int>("int", int.TryParse)
   .Command(new Command("plus-one", "...")
           .Parameters("value:int")
           .Action(context => 
           {
               var value = (int)context["value"];
               Console.WriteLine(value+1);
           }))
   .Build()
   .Execute("plus-one 10") // prints "11"
   .Execute("plus-one text") // aborts execution and prints an error

If a parameter got its minimum number of required arguments (0 for optional, 1 for collective),
but not the maximum, and the next argument is mismatched, the parameter ends parsing, and lets the next one try to parse this argument.

new BoxBuilder()
   .Type<int>("int", int.TryParse)
   .Command(new Command("demo", "...")
           .Parameters("values:int...",
                       "tail")
           .Action(context => 
           {
               var values = string.Join(',', (object[])context["values"]);
               Console.WriteLine($"Values: {values}; Tail: {context["tail"]}");
           }))
   .Build()
   .Execute("demo 1 tail") // outputs "Values: 1; Tail: tail"
   .Execute("demo 1 2 3 tail") // outputs "Values: 1, 2, 3; Tail: tail"

Note. The default string type matches everything.
So it would capture all the arguments until the input end or an option.
Consider the example above, but with modified Parameters:
.Parameters("values...", "[tail:int]")
The call "demo 1 tail" would output "Values: 1, tail; Tail: "
The "demo 1 2 3 tail" - "Values: 1, 2, 3, tail; Tail: "


Adding types

ParseFunction

A ParseFunction accepts a string (called 'token')
and returns an object on success, otherwise null

new BoxBuilder()
   .Type("ten", token => token == "10" ? 10 : null)

TryParse

Accepts a token, assigns the result to the out parameter of specified generic type. Returns a bool indicating success

new BoxBuilder()
   .Type<bool>("bool-using-built-in", bool.TryParse)
   .Type("ten-with-custom-function",
        (string token, out int value) =>
        {
            if (token == "10")
            {
                value = 10;
                return true;
            }
            value = 0;
            return false;
        })

Note. Explicit generic type specification is not mandatory, and may be omitted in most cases,
like in the ten-with-custom-function example.


Enum

public enum Age
{
    Young,
    Mature,
    Old
}
/*...*/
new BoxBuilder()
   .Type<Age>() // the name is "age"
   // or
   .Type<Age>("your-custom-name")

Note. Generated name is the original name of the enum,
converted to dash-case, e.g. LogLevel becomes log-level.
Generated function expects tokens to be strings in dash-case notation,
as it converts the arguments to PascalCase,
before parsing to the Enum values.
Case-conversion examples for clarity:
Word - word, SeveralWords - several-words.


Clone this wiki locally