Skip to content
Siy Williams edited this page Jun 10, 2015 · 8 revisions

v1.4.2

app.exe --boolean on   // boolean is set to true
app.exe --boolean off  // boolean is set to false
  • Added support for parsing URI type

app.exe --uri https://github.com/fclp/fluent-command-line-parser

Uri actual;

var parser = new FluentCommandLineParser();

parser.Setup<Uri>('u', "uri")
      .Callback(val => actual = val);

parser.Parse(args);

Assert.IsNotNull(actual);
Assert.AreEqual("https://github.com/fclp/fluent-command-line-parser", actual.AbsoluteUri);

v1.4

Enum Flag Support

With thanks to @alexruzzarin enum flags are now supported.

[Flags]
enum Direction
{
	North = 1,
	East = 2,
	South = 4,
	West = 8,
}
dosomething.exe --direction South East
dosomething.exe --direction 4 2
static void Main(string[] args)
{
  var p = new FluentCommandLineParser();

  Direction direction;

  p.Setup<Direction>("direction")
   .Callback(d => direction= d);

  p.Parse(args);

  Assert.IsFalse(direction.HasFlag(Direction.North));
  Assert.IsTrue(direction.HasFlag(Direction.East));
  Assert.IsTrue(direction.HasFlag(Direction.South));
  Assert.IsFalse(direction.HasFlag(Direction.West));
}

v1.3

Enum Support

Thanks to the initial work from @pchalamet enums are now supported out of the box.

public enum Direction
{
	Left = 0,
	Right = 1,
	Up = 3,
	Down = 4
}
p.Setup<Direction>('d', "direction")
 .Callback(d => direction = d);

To specify 'Right' direction either the text can be provided or the enum integer.

dosomething.exe --direction Right
dosomething.exe --direction 1

You can also collect multiple Enum values into a List

List<Direction> direction;

p.Setup<List<Direction>>('d', "direction")
 .Callback(d => direction = d);

For example, specifiying 'Right' and 'Up' values

dosomething.exe --direction Right Up
dosomething.exe --direction 1 3

And the generic FluentCommandLineParser (previously known as FluentCommandLineBuilder) also supports enums.

public class Args
{
   public Direction Direction { get;set; }
   public List<Direction> Directions { get;set; }
}
var p = new FluentCommandLineParser<Args>();

p.Setup(args => args.Direction)
 .As('d', "direction");

p.Setup(args => args.Directions)
 .As("directions");

Api Changes (!!)

FluentCommandLineBuilder<T> has been renamed to FluentCommandLineParser<T>. FluentCommandLineBuilder has been made obsolete but will not cause a compiler error in this release. Please replace any usage of with FluentCommandLineParser<T>.

v1.2

Fluent Command Line Builder

Instead of assigning parsed values to variables you can use the Fluent Command Line Builder to automatically create a defined object type and setup individual Options for each strongly-typed property. Because the builder is simply a wrapper around the parser you can still use the Fluent Command Line Parser Api to define the behaviour for each Option.

The Fluent Command Line Builder can build a type and populate the properties with parsed values such as in the following example:

public class ApplicationArguments
{
   public int RecordId { get; set; }
   public bool Silent { get; set; }
   public string NewValue { get; set; }
}

static void Main(string[] args)
{
   // create a builder for the ApplicationArguments type
   var b = new FluentCommandLineBuilder<ApplicationArguments>();

   // specify which property the value will be assigned too.
   b.Setup(arg => arg.RecordId)
    .As('r', "record") // define the short and long option name
    .Required(); // using the standard fluent Api to declare this Option as required.

   b.Setup(arg => arg.NewValue)
    .As('v', "value")
    .Required();

   b.Setup(arg => arg.Silent)
    .As('s', "silent")
    .SetDefault(false); // use the standard fluent Api to define a default value if non is specified in the arguments

   var result = b.Parse(args);

   if(result.HasErrors == false)
   {
      // use the instantiated ApplicationArguments object from the Object property on the builder.
      application.Run(b.Object);
   }
}

Setup Option by specifying long name only

In v1.1 and earlier, to setup an Option a short name must always be supplied. This has now been changed so Options with just long names can also be created.

Better Option Validation

The validation invoked when setting up new Options has been re-factored and improved. More meaningful error message will now be thrown when called with invalid data.

Functional Changes (!)

Some functional changes have been made which may impact existing behaviour.

A InvalidOptionNameException is now thrown when setting up an Option if:

  • A specified long Option name is a single char in length.
  • A specified long Option name contains : or = characters anywhere within it.

Short, long and help Options are now case sensitive. This means that -s and -S are considered different, also long Options --long and --LONG are considered different. This behaviour can be disabled and case ignored by doing parser.IsCaseSensitive = false.

Breaking Api Changes (!!)

Changes have been kept to a minimal with the following changes made:

  • Setup<T>(string, string) has been made obsolete, being replaced instead with Setup<T>(char, string). This is to better reflect through the Api that short Options should be a single character only.
  • Setup<T>(string) is no longer used to setup an Option with only a short name. Instead it is used to setup an Option with only a long name. This will initially result in an InvalidOptionNameException raised when the method is invoked as long names must now be longer than a single character in length. If you require to setup an option with a short name only you should use the Setup<T>(char) overload instead.

v1.1

New improved parsing engine

A number of different improvement have been made to the parsing engine.

Support collections

Many arguments can now be collected as part of a list. Types supported are string, int, double and bool

For example arguments such as

--filenames C:\file1.txt C:\file2.txt C:\file3.txt

can be parsed to a list using

static void Main(string[] args)
{
   var parser = new FluentCommandLineParser();

   var filenames = new List<string>();

   parser.Setup<List<string>>("f", "filenames")
         .Callback(items => filenames = items);

   parser.Parse(args);

   Console.WriteLine("Input file names:");

   foreach (var filename in filenames)
   {
      Console.WriteLine(filename);
   }
}

output:

Input file names
C:\file1.txt
C:\file2.txt
C:\file3.txt

Combined short options

Options x, y and z can be combined which applies any specified argument to them all.

-xyz value

static void Main(string[] args)
{
   var parser = new FluentCommandLineParser();

   string xVal = null;
   string yVal = null;
   string zVal = null;

   parser.Setup<string>("x").Callback(x => xVal = x);
   parser.Setup<string>("y").Callback(y => yVal = y);
   parser.Setup<string>("z").Callback(z => zVal = z);
   
   parser.Parse(args);

   Console.WriteLine("x is " + xVal);
   Console.WriteLine("y is " + yVal);
   Console.WriteLine("z is " + zVal);
}

output:

x is value
y is value
z is value

As such -xyz value can be described as shorthand for

-x value -y value -z value

More commonly this feature is used to handle multiple boolean options

-xyz enable option x, y and z

-xyz+ enable option x, y and z

-xyz- disable option x, y and z

Setup Help & Empty Arguments

static void Main(string[] args)
{
   var parser = new FluentCommandLineParser();

   parser.SetupHelp("h", "help", "?")
         .Callback(text => Console.WriteLine(text);

   var result = parser.Parse(args);
   
   if(result.HelpCalled)
   {
      // help
   }

   if(result.EmptyArgs)
   {
      // empty
   }
}

The following are available from the .SetupHelp() method to define its behaviour:

.Callback<string>(text => Console.WriteLine(text)) Specified the delegate to be invoked with any setup options formatted for the console.

.Callback(() => Environment.Exit(1)) Specified the delegate to be invoked without any arguments. This can be in addition to the delegate with arguments and in this case is always called last.

.WithCustomFormatter(new CustomOptionFormatter()) Specifies a custom formatter to use.

.UseForEmptyArgs() Specifies that empty arguments should be handled the same way as the setup help arguments; that is for example, if empty arguments are provided then the same help text can be printed to the console.

Parser Error Handling

To determine if any errors occurred during the parsing process use the HasErrors bool property on the result object.

var p = new FluentCommandLineParser();

p.Setup<int>("n", "number")
 .Callback(n => Console.WriteLine(n.ToString()));

p.Setup<string>("f", "filename")
 .Callback(f => Console.WriteLine(f)));
 .Required();

var result = p.Parse(args);

if(result.HasErrors)
{
  Console.WriteLine(result.ErrorText);
}

Option Parse Error

This error occurs when a the argument value could not be parsed into the correct type for the Option.

For example specifying a string argument for the number Option which is an integer...

example.exe --number "one"`

...would generate the following error message in the console:

Option '--number' parse error: could not parse 'one' to 'System.Int32'

Expected Option Not Found Error

This error occurs when a required option does not exist in the specified arguments.

In the code example above the filename Option is explicitly required, therefore if it is not specified in the arguments the following error message would be generated for the console:

Option 'f:filename' parse error: Option is required but was not specified.

Error messages are generated by the ICommandLineParserErrorFormatter.

Functional Changes (!)

Some functional changes have been made which may impact existing behaviour.

  • Short options must be exactly a single character. Attempting to define anything else will result in an error. This change was made to allow combining short options.
  • Short options are defined using the - prefix only. Other prefixes such as -- and / denote long options and thus have different behaviour in the parser (does not attempt to combined options).
  • String arguments that contain whitespace but are not wrapped in double quotes cannot be parsed and are returned as errors from the parse operation.

--filename "C:\My Documents\file1.txt" is valid (filename with whitespace wrapped in double quotes)

--filename C:\My Documents\file1.txt is NOT valid (filename with whitespace NOT wrapped in double quotes)

--filename C:\DirWithNoWhiteSpace\file1.txt is valid (filename without whitespace not wrapped in double quotes)

Breaking Api Changes (!!)

Changes have been kept to a minimal with the following changes made:

  • The CommandLineOptionFormatter.ShowHeader property is no longer public and therefore not settable. The header will always be unseen by default. If you would like a header to be displayed you should instead use the new WithHeader(string) method when setting up the help. e.g.

.SetupHelp("?").WithHeader("text to display at the top")

  • Although not visible to through the main Api, the internals have been modified to provide more extendable behaviour.
  • The parser.CreateShowUsageText() method has been dropped to simplify the Api. You can either use the .SetupHelp() method to get the usage text or use the OptionFormatter property on the parser itself.

v1.0.2 - Setup Help

Fluent interface supports the setup of help arguments.

static void Main(string[] args)
{
   var parser = new FluentCommandLineParser();

   parser.SetupHelp("h", "help", "?")
         .Callback(Console.WriteLine);

   var result = parser.Parse(args);
   
   if(result.HelpCalled) return;
}

v1.0.0 - Initial Release