XO.Console.Cli 5.0.42

dotnet add package XO.Console.Cli --version 5.0.42
NuGet\Install-Package XO.Console.Cli -Version 5.0.42
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="XO.Console.Cli" Version="5.0.42" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add XO.Console.Cli --version 5.0.42
#r "nuget: XO.Console.Cli, 5.0.42"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install XO.Console.Cli as a Cake Addin
#addin nuget:?package=XO.Console.Cli&version=5.0.42

// Install XO.Console.Cli as a Cake Tool
#tool nuget:?package=XO.Console.Cli&version=5.0.42

XO.Console.Cli

XO.Console.Cli is a command line parser and application framework.

Features

  • Simple programs are simple
  • Class or delegate command implementations
  • Default commands, nested sub-commands ("branches"), global options, greedy arguments, and more
  • Automatic help text
  • Explicit argument value separator (--) forces parsing remainder of the command line as argument values (not commands or options)
  • Built-in --cli-explain flag helps debug parsing
  • Console abstraction makes commands testable
  • Dependency free
  • Reflection free and trimmable via compile-time source generation of command and parameter type information

Getting Started

1. Add a reference to XO.Console.Cli

> dotnet add package XO.Console.Cli

2. Write a command

A command is defined by its implementation (usually a class, but delegate implementations are supported, too) and its parameters type.

// for an async implementation, derive from AsyncCommand<TParameters>
class GreetingCommand : Command<GreetingCommand.Parameters>
{
    // all parameters types must derive from CommandParameters
    public class Parameters : CommandParameters
    {
        // use CommandArgumentAttribute to declare a positional parameter
        [CommandArgument(0, "name", Description = "Name of the person to greet")]
        public required string Name { get; set; }

        // use CommandOptionAttribute to declare a named option
        [CommandOption("--greeting", Description = "A custom greeting (defaults to 'Hello')")]
        public string Greeting { get; set; } = "Hello";
    }

    public override int Execute(ICommandContext context, Parameters parameters, CancellationToken cancellationToken)
    {
        // 'context' provides an abstraction of the standard streams; using it for i/o makes automated testing easier!
        context.Console.Output.WriteLine($"{parameters.Greeting}, {parameters.Name}!");

        // return the desired process exit code (conventionally, 0 = success, and any non-zero exit code = failure)
        return 0;
    }
}

3. Create an instance of ICommandAppBuilder

For a typical application with several possible commands, simply use the public constructor new CommandAppBuilder().

return await new CommandAppBuilder()
    .ExecuteAsync(args);

If you want your application to have a default command — to do something useful when invoked without additional arguments — call the static factory method CommandAppBuilder.WithDefaultCommand:

// there are overloads that accept a parameters class or a class command implementation, too!
return await CommandAppBuilder.WithDefaultCommand(
    async (context, cancellationToken) =>
    {
        await context.Console.Output.WriteLineAsync("Hello, world!");
        return 0;
    })
    .ExecuteAsync(args);

4. Add commands

Call the methods of ICommandAppBuilder to add commands to the application. Each command must have a unique "verb" that invokes it.

return await new CommandAppBuilder()
    .AddCommand<GreetingCommand>("greet")
    .ExecuteAsync(args);

5. Run it

> dotnet run
Use --help to see usage information

> dotnet run -- greet --help
XO.Console.Cli.Samples 1.0.0

USAGE
  XO.Console.Cli.Samples greet <name> [OPTIONS]

ARGUMENTS
  name    Name of the person to greet

OPTIONS
      --greeting    A custom greeting (defaults to 'Hello')

  -h, --help        Shows this help

> dotnet run -- greet John
Hello, John!

> dotnet run -- greet John --greeting Hey
Hey, John!

Declarative Configuration

By decorating command classes with CommandAttribute, you can configure your application's commands declaratively, without writing out the calls to ICommandBuilder.

The source generator outputs code that adds a command to every instance of CommandAppBuilder for each class decorated with CommandAttribute. If you want to build multiple instances of ICommandApp with different commands, stick to explicit, imperative configuration.

Using CommandAttribute

Apply the attribute to your command class, passing the verb that will invoke the command as the first argument. Use the attribute's keyword parameters to configure other properties of the command, such as its description. Each class may have only one instance of CommandAttribute.

[Command("greet", Description = "Prints a greeting")]
class GreetingCommand : Command<GreetingCommand.Parameters> { /* ... */ }

Declarative Branches

You can group commands into branches using attributes, too. To create a branch, declare a sub-class of CommandAttribute, then decorate it with CommandBranchAttribute. CommandBranchAttribute's positional parameter(s) define the "path" to the branch. A branch's "path" is the sequence of verbs that precede the final verb for each sub-command in the branch. In this example, the application has two commands:

  • get nameGetNameCommand
  • get addressGetAddressCommand
[CommandBranch("get", Description = "Get values")]
class GetCommandAttribute : CommandAttribute
{
    public GetCommandAttribute(string verb)
        : base(verb) { }
}

[GetCommand("name")]
class GetNameCommand : Command { /* ... */ }

[GetCommand("address")]
class GetAddressCommand : Command { /* ... */ }

Public constructors of your custom attribute(s) must have a first parameter of exactly string verb, and there must be at least one such constructor. The source generator reads the literal value of verb from your source code. An included analyzer will report an error if the constructor parameter is missing.

Declarative Branches and Commands

By itself, CommandBranchAttribute doesn't declare any implementation for the branch. In the above example, if you were to pass the argument get without a sub-command, the application would print the standard usage notice. To assign a command class to the branch, decorate it with the same verb as the branch.

[Command("get", Description = "Get values")]
class GetCommand : Command { /* ... */ }

Notice we used the base CommandAttribute and moved the description from the branch declaration. When you assign an implementation to a branch, any properties assigned to its CommandBranchAttribute are ignored, and the properties of the CommandAttribute applied to the implementation class are used instead.

Nested Declarative Branches

Passing multiple path segments to CommandBranchAttribute creates additional "levels" of sub-commands. For example, we could add a command that gets only part of the address.

[CommandBranch("get", "address")]
class GetAddressCommandAttribute : CommandAttribute
{
    public GetAddressCommandAttribute(string verb)
        : base(verb) { }
}

// invoke this command with the args "get address state"
[GetAddressCommand("state")]
class GetAddressStateCommand : Command { /* ... */ }
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net6.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on XO.Console.Cli:

Package Downloads
XO.Console.Cli.Extensions

Integrates XO.Console.Cli with Microsoft.Extensions.DependencyInjection and Microsoft.Extensions.Hosting

XO.Console.Cli.Instrumentation

OpenTelemetry instrumentation for XO.Console.Cli

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
5.0.42 96 6/11/2024
4.0.3 200 6/22/2023
3.0.7 527 8/29/2022
2.0.10 559 7/19/2022
2.0.9 480 6/15/2022
2.0.8 488 6/15/2022