Argopt

Command line argument parsing in .NET

Argopt is a library for parsing command line arguments in .NET. Shut up, the name is awesome.

Download

Example

using System;
using Argopt;

public class MyContract {
	[ValueProperty]
	[Description("The greeting to display")]
	public string Greeting { get; set; }
	
	[Alias("r")]
	[Description("The number of times to repeat the greeting", ValueName = "times")]
	public int Repeat { get; set; }
	
	[Delimited(","), Alias("n")]
	[Description("The names of the people to greet", Required = true, ValueName = "name1,name2...")]
	public string[] Names { get; set; }
}

class Program {
	static void Main(string[] args) {
		var result = OptionParser.Parse<MyContract>(args);
		if (!result.IsValid) {
			foreach (var error in result.Errors) {
				Console.WriteLine(error.ThrownException);
			}
			
			return;
		}
		
		var contract = result.Contract; //this is an instance of MyContract
		
		if (contract.Names.Length == 0 || string.IsNullOrEmpty(contract.Greeting)) {
			//print usage
			Console.WriteLine(OptionParser.GetDescription<MyContract>());
			return;
		}
		
		foreach (var name in contract.Names) {
			for (var i = 0; i < contract.Repeat; i++) {
				Console.WriteLine(string.Format("{0}, {1}!", contract.Greeting, name));
			}
		}
	}
}

Information

Argopt operates on a contract class: a user-defined class that gets populated with the parsed command line arguments by the library. Within the contract class are properties that are annotated with various attributes, which are described below.

Argopt does not differentiate between long and short options, e.g. --foo and -foo are treated the same.

Argopt supports two types of value passing: as part of the option (e.g. the value comes after the equals sign) and as the next command line argument. For example, these are equivalent: --foo=bar and --foo bar.

Argopt can automatically parse all primitive types (strings, ints, doubles, bools, etc.), arrays of primitive types (e.g. int[]) and enums.

Argopt has two syntax modes: Unix (prefixed by dashes) and Windows (prefixed by forward slashes). The default is Unix. This can be changed by passing in an optional parameter to OptionParser.Parse() identifying the mode.

Argopt also supports boolean switches, which are mostly used in Windows apps (for example, csc, the C# compiler). Those options look like this: /warnaserror+:1400,1560, where the + and - turn the switch on or off. See the description of ComplexFlagAttribute.

Argopt can generate prettily formatted documentation based on the contract class.

Attributes

Argopt.NameAttribute

The name of each command line option is the name of the property in the contract class. This can be overridden using the Name attribute.

//--new-name will match this property, --TerribleName will not
[Name("new-name")]
public string TerribleName { get; set; }
Argopt.AliasAttribute

Use this attribute to define a variable number of aliases for each option.

//--AliasMe, --a, --alias, --zuzu will all match this property
[Alias("a", "alias", "zuzu")]
public string AliasMe { get; set; }
Argopt.CaseSensitiveAttribute

Decorating a property with this attribute disables case insensitivity.

//only --ForTheLulz matches this property, --forthelulz no longer will
[CaseSensitive]
public string ForTheLulz { get; set; }
Argopt.ComplexFlagAttribute

This attribute provides support for Windows-style flag options that look something like this: /warnaserror+:1500. The + and - turn the switch on or off, but different from a flag, they also allow a value to be passed.

For these properties, it stores the boolean flag in the property, so it should be of type bool. It stores the value in another property, which you must specify in the constructor of the attribute. That other property should probably not be configured as an option.

//passing /warnaserror+:1500,1400 will set WarnAsError to true, and 
//ErrorPragmas will be set to int[] { 1500, 1400 }
[ComplexFlag("ErrorPragmas")]
public bool WarnAsError { get; set; }

[NotAnOption]
public int[] ErrorPragmas { get; set; }
Argopt.FlagAttribute

This attribute indicates that the property is a boolean and does not require a value. If this option is present in the argument list, it is set to true.

//passing --disablewarnings will set this property to true
[Flag]
public bool DisableWarnings { get; set; }
Argopt.NotAnOptionAttribute

By default, all public non-static properties in the contract class are considered options. You can annotate them with this attribute to signify that they should not be considered as options.

//passing --DoNotUseMe=foo will do nothing
[NotAnOption]
public string DoNotUseMe { get; set; }
Argopt.DelimitedAttribute

To make Argopt parse arrays, you can use this attribute to specify a delimiter. The passed value will be split on the delimiter.

//passing --doubles 1.0|2.6|7|-412 will set Doubles to double[] { 1, 2.6, 7, -412 }
[Delimited("|")]
public double[] Doubles { get; set; }
Argopt.ValuePropertyAttribute

A property decorated with this attribute will hold the actual command line arguments (as opposed to the options). For example, in the command cp -R /my/file /my/newfile, the options would be -R and the arguments would be /my/file and /my/new/file.

Argopt only allows one value property per contract, and will just use the first if there are more than one.

Also note that all values passed on the command line are considered arguments if there is no matching option. Value properties are never considered options.

//this emulates a subset of the cp command on unix
[Name("recursive"), Alias("R", "r"), Flag, CaseSensitive]
public bool Recursive { get; set; }

//Files.Last() will hold the name of the file to copy to
[ValueProperty]
public string[] Files { get; set; }
Argopt.DescriptionAttribute

This attribute provides a way to document each option. The OptionParser.GetDescription() method uses this attribute to generate the formatted usage summary for a contract class.

It has several properties. The ValueName property indicates that this option accepts a value. The value of this property will be printed next to the option.

The Required property indicates that this option must always be passed. Note that this only affects the generated documentation; it has no bearing on validation (Argopt does not perform validation).

//will print something like:
//--ErrorLevel=debug|info|warn|error   Specifies the global, application-wide error level

[Description("Specifies the global, application-wide error level", ValueName = "debug|info|warn|error")]
public string ErrorLevel { get; set; }

Here’s an example of the documentation it can generate.

usage

Feedback

Argopt was written by Tommy Montgomery. You can send feedback, bugs, suggestions, death threats to t.montg@gmail.com.