Argx 0.0.2
See the version list below for details.
dotnet add package Argx --version 0.0.2
NuGet\Install-Package Argx -Version 0.0.2
<PackageReference Include="Argx" Version="0.0.2" />
<PackageVersion Include="Argx" Version="0.0.2" />
<PackageReference Include="Argx" />
paket add Argx --version 0.0.2
#r "nuget: Argx, 0.0.2"
#:package Argx@0.0.2
#addin nuget:?package=Argx&version=0.0.2
#tool nuget:?package=Argx&version=0.0.2
Argx
A modern command-line argument parsing library for .NET
How it works
The application should define the arguments it requires and the library will figure out how to parse them. It will automatically generate help and usage messages, as well as errors when the user input is not valid.
Getting started
The ArgumentParser contains the core functionality of this library in order to define, parse and manage arguments. An in-dept documentation of its public API is available below.
var parser = new ArgumentParser(
app: "myapp",
description: "A simple example application");
// Add a required positional argument
parser.AddArgument("echo", usage: "The string to be echoed back");
// Add an option
parser.AddOption<string>("--prefix", ["-p"], usage: "A prefix to add before the echoed string");
// Add an optional flag
parser.AddOption<int>("--count", ["-c"], usage: "Number of times to echo the string");
// Parse the arguments
var argx = parser.Parse(args);
// Access the values
// Required: will throw if not present
var echo = argx.GetRequired<string>("echo");
// Optional: returns default if not found
var prefix = argx.GetValue<string>("prefix") ?? string.Empty;
// TryGetValue pattern
if (!argx.TryGetValue<int>("count", out var count))
count = 1;
for (int i = 0; i < count; i++)
{
Console.WriteLine($"{prefix}{echo}");
}
$ ./echo.cs "World" -p "Hello, " -c 3
Hello, World
Hello, World
Hello, World
By default, the parser parses and stores all the argument values, however this behavior can be changed using actions. For example, if we need to introduce a verbosity counted flag, we can decorate the above code with the following:
parser.AddOption<int>("-v",
action: ArgumentActions.Count,
usage: "Increase verbosity level",
dest: "verbosity");
var argx = parser.Parse(args);
var verbosity = argx.GetValue<int>("verbosity");
Console.WriteLine($"Verbosity level: {verbosity}");
$ ./echo.cs "World" -p "Hello, " -vvv
Verbosity level: 3
Hello, World
Help text and errors
Help (--help, -h) argument is added by default and the help text is generated by the parser:
$ ./echo.cs -h
myapp
A simple example application
Usage
myapp [--help] [--prefix PREFIX] [--count COUNT] [-v] echo
Positional arguments
echo The string to be echoed back
Options
--count, -c Number of times to echo the string
--help, -h Print help message
--prefix, -p A prefix to add before the echoed string
-v Increase verbosity level
Parsing errors are handled by the parser:
$ ./echo.cs
Error: argument echo: expected value
Usage
myapp [--help] [--prefix PREFIX] [--count COUNT] [-v] echo
Multiple values
Using actions and arity we can parse collection arguments:
var parser = new ArgumentParser();
parser.AddArgument<string[]>("files",
arity: Arity.AtLeastOne,
usage: "One or more files to process");
var argx = parser.Parse(args);
var files = argx.GetRequired<string[]>("files");
foreach (var file in files)
{
Console.WriteLine($"Processing {file}");
}
$ ./process.cs a.txt b.txt c.txt
Processing a.txt
Processing b.txt
Processing c.txt
Subcommands
Many programs split their functionality into subcommands, for example, git has subcommands like pull, push, status, etc. Argx support subcommands via CommandLineApplication, which is similar to WebApplication in minimal APIs.
var app = new CommandLineApplication(
name: "git",
description: "a fast, scalable, distributed revision control system with an unusually rich command set that provides both high-level operations and full access to internals.");
app.AddSubcommand("push", args =>
{
var parser = new ArgumentParser(app: app.Name);
parser.AddArgument("remote");
parser.AddArgument("refspec");
var pargs = parser.Parse(args);
var remote = pargs.GetRequired<string>("remote");
var refspec = pargs.GetRequired<string>("refspec");
Console.WriteLine($"Pushing to {remote} {refspec}..");
Console.WriteLine($"Done");
})
.WithUsage("Update remote refs along with associated objects");
app.AddSubcommand("pull", async args =>
{
var parser = new ArgumentParser(app: app.Name);
parser.AddArgument("remote");
parser.AddArgument("refspec");
var pargs = parser.Parse(args);
var remote = pargs.GetRequired<string>("remote");
var refspec = pargs.GetRequired<string>("refspec");
Console.WriteLine($"Pulling from {remote} {refspec}..");
await Task.Delay(1000);
Console.WriteLine("Done");
})
.WithUsage("Fetch from and integrate with another repository or a local branch");
app.AddSubcommand("status", async args =>
{
var parser = new ArgumentParser(app: app.Name);
var pargs = parser.Parse(args);
await Task.Delay(1000);
Console.WriteLine($"Up to date with remote branch..");
})
.WithUsage("Show the working tree status");
await app.RunAsync(args);
$ ./git.cs status origin main
Up to date with remote branch..
$ ./git.cs pull origin main
Pulling from origin main..
Done
A help subcommand is added by default:
$ ./git.cs help
git
a fast, scalable, distributed revision control system with an unusually rich
command set that provides both high-level operations and full access to
internals.
Usage
git <command> [<arguments>]
Available commands
help Display help information about this application
pull Fetch from and integrate with another repository or a local branch
push Update remote refs along with associated objects
status Show the working tree status
Use '<command> --help' to get more information about a specific command.
Parsing errors are handled by the CommandLineApplication:
$ ./git.cs satus
git: Unknown subcommand: satus. See 'help' for a list of available commands.
ArgumentParser
The argument parsing is done via ArgumentParser, which provides functionality for defining, parsing, and managing command-line arguments.
var parser = new ArgumentParser(
app: "app_name",
description: "What the application does",
epilogue: "Text at the bottom of the help message",
configuration: ArgumentParserConfiguration.Default());
NOTE All parameters are optional. By default:
- app, description, and epilogue (used to print help text and usage) are null and will not be printed.
- The default
ArgumentParserConfigurationis used. - If app is null, the usage output will use
argv[0](Environment.GetCommandLineArgs()[0]) as the application name.
Defining arguments
The Add method is used to add individual argument specifications to the parser. It supports positional arguments, options and flags.
parser.Add("file"); // positional argument
parser.Add<int>("--level"); // option of type int
parser.Add<bool>("--debug", ["-d"], // flag
usage: "enable debug mode",
action: ArgumentActions.StoreTrue);
However, it’s recommended to use the dedicated methods for each argument type: AddArgument, AddOption, and AddFlag. These methods accept only the parameters relevant to their specific type.
All the add methods have a generic overload for specifying the argument’s value type, see supported types.
AddArgument
Positional arguments are identified by their position in the command line, rather than by a flag or option name, their meaning depends on where they appear in the command line. This means the positional arguments will be parsed in the order they were added.
Use AddArgument to add a positional argument
var parser = new ArgumentParser();
parser.AddArgument<int>("x");
parser.AddArgument<int>("y");
var argx = parser.Parse(["2", "3"]);
var x = argx.GetValue<int>("x");
var y = argx.GetValue<int>("y");
Console.WriteLine(x + y); // Outputs: 5
AddOption
Options are identified by name. They must start with - or --.
var parser = new ArgumentParser();
parser.AddArgument("echo", usage: "The string to be echoed back");
parser.AddOption<string>("--prefix", ["-p"], usage: "A prefix to add before the echoed string");
parser.AddOption<int>("--count", ["-c"], usage: "Number of times to echo the string");
var argx = parser.Parse(args);
var echo = argx.GetRequired<string>("echo");
var prefix = argx.GetValue<string>("prefix") ?? string.Empty;
if (!argx.TryGetValue<int>("count", out var count))
count = 1;
for (int i = 0; i < count; i++)
{
Console.WriteLine($"{prefix}{echo}");
}
$ dotnet run -- world --prefix "hello " -c 3
hello world
hello world
hello world
NOTE: -- is used to separate the application arguments from the dotnet run arguments.
AddFlag
A flag is an option that represents a boolean value, it’s either present (true) or absent (false). They are options, so they must start with -, or --.
parser.AddFlag("--verbose", ["-v"], "Enable verbose output");
var argx = parser.Parse(["-v"]);
Console.WriteLine(argx.GetValue<bool>("verbose")); // Outputs: True
Parsing arguments
Once all arguments are defined, the next step is to parse the input provided by the user. This is done using the Parse() method on the ArgumentParser instance.
var parsedArgs = parser.Parse(args);
The Parse() method processes the command-line arguments, validates them against the defined schema, applies conversions, executes actions, and returns an IArguments instance.
Accessing parsed arguments
IArguments returned by Parse() provides type-safe methods to retrieve the values of the added arguments by their key.
Extras: Contains any arguments not matched by the parser.Indexer (args["key"]): Retrieves the string value of an argument by its key or null if it doesn’t exist.GetValue<T>: Retrieves the value, or default(T) if the argument is missing.GetRequired<T>: Retrieves the value, throwing an InvalidOperationException if the argument is missing.TryGetValue<T>: Attempts to get the value; returns true if found, false otherwise. The out parameter receives the value if it exists, otherwise default(T).
NOTE: The key used to access an argument value corresponds to the dest parameter specified in Add/AddOption. If not provided, it is inferred automatically:
- Options: leading dashes are removed(e.g.
--verbosebecomesverbose). - Positional arguments: the argument name itself is used.
AddArgumentdoes not have adestparameter.
Actions
Actions define what happens when an argument is encountered during parsing.
Built-in actions
store: Stores the argument’s value(s). This is the default action when no action is explicitly specified.
parser.Add("foo");
var argx = parser.Parse(["bar"]);
Console.WriteLine(argx["foo"]); // output: "bar"
NOTE: if not specified, the type will be inferred from the action (each action has a default type, e.g. string for store, bool for store_true, int for count).
store_const: Stores the predefined constValue when the option is encountered.
parser.Add<int>("--foo", action: ArgumentActions.StoreConst, constValue: 6);
var argx = parser.Parse(["--foo"]);
Console.WriteLine(argx.GetValue<int>("foo")); // Outputs: 6
store_true: Stores true when the option is encountered.
parser.Add<bool>("--foo", action: ArgumentActions.StoreTrue);
var argx = parser.Parse(["--foo"]);
Console.WriteLine(argx.GetValue<bool>("foo")); // Outputs: True
store_false: Stores false when the option is encountered.
parser.Add("--foo", action: ArgumentActions.StoreFalse);
var argx = parser.Parse(["--foo"]);
Console.WriteLine(argx.GetValue<bool?>("foo")); // Outputs: False
NOTE: nullable is used because GetValue<T> returns default(T) if the key doesn't exist, which is false for bool. Using TryGetValue would also work.
count: Stores the number of times the argument is encountered.
parser.Add<int>("-v",
action: ArgumentActions.Count,
usage: "Increase verbosity level",
dest: "verbosity");
var argx = parser.Parse(["-vvv"]);
Console.WriteLine(argx.GetValue<int>("verbosity")); // Outputs: 3
append: Appends each value to a list. Useful when an option can appear multiple times.
The type must be an enumerable.
parser.Add<int[]>("--foo", action: ArgumentActions.Append, arity: Arity.AtLeastOne);
var argx = parser.Parse(["--foo", "0", "--foo", "1", "2", "--bar", "10", "--foo", "3"]);
Console.WriteLine(string.Join(", ", argx.GetValue<int[]>("foo"))); // Outputs: 0, 1, 2, 3
NOTE: Arity.AtLeastOne reads all the following values until another option is encountered or end is reached. This means we can append both individual values and collections of values. If arity was 1, then it would append only the following value. Arity.Any works in a similar way but it needs a constValue when no value is provided. See arity for more details.
Custom actions
To register a custom action, use the ArgumentParser.AddAction method. It takes an action name and an ArgumentAction instance. Once added, you can use the action by specifying its name in the action parameter of any add method.
ArgumentAction is the base type for all actions. Every action implementation derives from it and must define two methods:
Validate
Called when a new argument specification is added to the parser. It ensures that the action is valid and can be performed. Each action has its own validation rules and throws an exception if they are not met. This helps catch configuration errors at startup, rather than at runtime during parsing.
Execute
Called when the argument is encountered during parsing. This method performs the action’s logic, such as storing values, it receives the argument definition, the token that triggered it, any associated value tokens (identified by arity), and the argument store where parsed results are stored.
Each action overrides this method to implement its specific behavior.
The base implementation validates that the invocation is not null or empty.
Arity
Defines the arity (number of values) an argument can accept. This can be either a fixed number or a keyword.
Keywords
? (Arity.Optional): An optional value, one argument will be consumed from the command line if possible, and produced as a single item. This should be used along constValue, which will be used if no value is provided.
parser.Add("--foo", arity: Arity.Optional, constValue: "0");
parser.Add("--bar", arity: Arity.Optional, constValue: "0");
var result = parser.Parse(["--foo", "--bar", "baz"]);
Console.WriteLine(result.GetValue("foo")); // Outputs: 0
Console.WriteLine(result.GetValue("bar")); // Outputs: baz
* (Any): Any number of values. The argument can be provided with zero or more values. The argument type must be a collection type. This will consume all the following values until another known option is encountered or reaches the end of the command line.
parser.Add<int[]>("--foo", arity: Arity.Any, constValue: Array.Empty<int>());
parser.Add<int[]>("--bar", arity: Arity.Any, constValue: Array.Empty<int>());
var result = parser.Parse(["--foo", "--bar", "0", "1", "2"]);
Console.WriteLine($"foo: {string.Join(", ", result.GetValue<int[]>("foo"))}"); // Outputs: foo:
Console.WriteLine($"bar: {string.Join(", ", result.GetValue<int[]>("bar"))}"); // Outputs: bar: 0, 1, 2, 3
+ (AtLeastOne): At least one value, same as any, but throws if no value is provided.
parser.Add<int[]>("--foo", action: ArgumentActions.Append, arity: Arity.AtLeastOne);
var argx = parser.Parse(["--foo", "0", "--foo", "1", "2", "--bar", "10", "--foo", "3"]);
Console.WriteLine(string.Join(", ", argx.GetValue<int[]>("foo"))); // Outputs: 0, 1, 2, 3
If no value is provided:
parser.Add<int[]>("--foo", action: ArgumentActions.Append, arity: Arity.AtLeastOne);
parser.Add<int[]>("--bar", action: ArgumentActions.Append, arity: Arity.AtLeastOne);
var argx = parser.Parse(["--foo", "--bar", "10"]);
Error: argument --foo: requires at least one value
Usage:
Argx.Console.dll [--help] [--foo [FOO ...]] [--bar [BAR ...]]
Help text
When ArgumentParserConfiguration.AddHelpArgument is enabled in the configuration (by default it is), the parser automatically adds a built-in help option (-h / --help).
If this argument is provided on the command line, the parser prints the help text and exits with code 0.
var parser = new ArgumentParser();
parser.Add("file");
parser.Add<int>("--level");
parser.Add<bool>("--debug", ["-d"],
usage: "enable debug mode",
action: ArgumentActions.StoreTrue);
var argx = parser.Parse(args);
If the application is run with --help or -h, it will output:
Usage:
Argx.Console.dll [--help] [--level LEVEL] [--debug] file
Positional arguments:
file
Options:
--debug, -d enable debug mode
--help, -h Print help message
--level
NOTE: The Usage, Positional arguments, and Options blocks are referred to as sections.
The formatting can be customized via HelpConfiguration.
Parser Configuration
ArgumentParser constructor takes an instance of ArgumentParserConfiguration as a parameter, which defines the parser’s behavior and customization options.
var config = new ArgumentParserConfiguration
{
AddHelpArgument = true,
ExitOnError = true,
ErrorExitCode = 1,
HelpConfiguration = HelpConfiguration.Default()
};
Options:
AddHelpArgument: Automatically adds a built-in help argument (-h/--help). (Default:true)ExitOnError: Determines whether the parser should exit automatically when an error occurs. (Default:true)ErrorExitCode: The exit code used when an error occurs and ExitOnError is enabled. (Default:1)HelpConfiguration: Specifies how help messages are formatted and displayed. (Default:HelpConfiguration.Default()). See help configuration
Help configuration
The HelpConfiguration class defines how help and usage text is formatted and displayed.
var helpConfig = new HelpConfiguration
{
SectionSpacing = Environment.NewLine + Environment.NewLine,
IndentSize = 2,
MaxLineWidth = 80,
UseAliasInUsageText = false
};
Options:
SectionSpacing: Spacing between sections in the help output. (Default: two new lines)IndentSize: Number of spaces used to indent help text. (Default: 2)MaxLineWidth: Maximum width of help text before wrapping occurs. (Default: 80)UseAliasInUsageText: Whether to show argument aliases instead of primary names in usage text. (Default: false)
Argument type parsing configuration
ArgumentConversionDefaults defines the default configuration for converting string tokens into typed values, such as numbers, dates, and time spans.
- NumberStyles: Defines parsing behavior for each numeric type. These are passed directly to their respective
.TryParse()call.
Default: A new instance with the default values used by .NET. - FormatProvider: Specifies the culture or formatting conventions used during parsing. Passed to all numeric
.TryParse()calls and allTryParseExact()calls. Default:CultureInfo.InvariantCulture. - DateTimeFormat: Optional format string used when converting to
DateTime. If null,DateTime.TryParse()is used; elseDateTime.TryParseExact()Default:null. - TimeSpanFormat: Optional format string used when converting to
TimeSpan. If null,TimeSpan.TryParse()is used; elseTimeSpan.TryParseExact().
Default:null.
All options are static and affect conversions globally.
ArgumentConversionDefaults.DateTimeFormat = "dd.MM.yyyy";
ArgumentConversionDefaults.TimeSpanFormat = @"hh\:mm\:ss"
ArgumentConversionDefaults.FormatProvider = CultureInfo.GetCultureInfo("de-DE");
ArgumentConversionDefaults.NumberStyles.Double = NumberStyles.Currency;
Add parameters
- T: The expected type of the value.
- name: The primary name of the option. Positional arguments should be specified without prefixes, while optional arguments should start with dashes.
- alias: Optional alternative names for the option. Usually used for short options. Use null for no alias. Must be null for positional arguments.
- usage: A short description of the argument’s purpose, displayed in help output.
- dest: The key used to retrieve the value from the parsed result. If null, the parser infers it from the name.
- metavar: The placeholder name displayed in help messages for the argument’s value. Displayed only for arguments that expect values.
- constValue: A constant value assigned when the argument is used without an explicit value. Relevant mainly for certain actions.
- action: The action to perform when the argument is encountered, see actions.
- arity: Specifies how many values the argument expects, use null to reply on defaults inferred from the action. see arity for more details.
- choices: A set of allowed values for the argument. If specified, the argument's value must be one of these choices.
Supported types
- string
- bool
- numerics (short, int, long, decimal, double, float, ushort, uint, ulong)
- Guid
- DateTime
- TimeSpan
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- No dependencies.
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.