spectre.console/docs/input/cli/commandApp.md
Phil Scott 223642b797
Add blog to docs (#484)
* Adding social card infrastructure
* Upgrades doc project to .NET 6
* Adds Playwright
* Changes the console to a web project for Playwright
* Adds social card template
* Added blog content
* Parallelized social image processing
* Updating CI to use .NET 6 for docs build
2021-07-15 19:53:01 +02:00

4.4 KiB

Title: CommandApp Order: 2 Description: "CommandApp is the entry point for a Spectre.Console.Cli command line application. It is used to configure the settings and commands used for execution of the application."

CommandApp is the entry point for a Spectre.Console.Cli command line application. It is used to configure the settings and commands used for execution of the application. Most Spectre.Console.Cli applications will need to specify a custom configuration using the Configure method.

For example, the following configuration might be used to change the default behavior indicate that for DEBUG configuration's full exception stack traces should be outputted to the screen, and any examples defined for our commands will also be validated.

var app = new CommandApp<FileSizeCommand>();
app.Configure(config =>
{
#if DEBUG
    config.PropagateExceptions();
    config.ValidateExamples();
#endif
});

Multiple Commands

In the previous example we have a single command that is configured. For complex command line applications, it is common for them to have multiple commands (or verbs) defined. Examples of applications like this are git, dotnet and gh. For example, git would have an commit command and along with other commits like add or rebase. Each with their own settings and validation. With Spectre.Console.Cli we use the Configure method to add these commands.

For example, to add three different commands to the application:

var app = new CommandApp();
app.Configure(config =>
{
    config.AddCommand<AddCommand>("add");
    config.AddCommand<CommitCommand>("commit");
    config.AddCommand<RebaseCommand>("rebase");
});

This configuration would allow users to run app.exe add, app.exe commit, or app.exe rebase and have the settings routed the appropriate command.

For more complex command hierarchical configurations, they can also be composed via inheritance and branching. See Composing Commands.

Customizing Command Configurations

The Configure method is also used to change how help for the commands is generated. This configuration will give our command an additional alias of file-size and a description to be used when displaying the help. Additional, an example is specified that will be parsed and displayed for users asking for help. Multiple examples can be provided. Commands can also be marked as hidden. With this option they are still executable, but will not be displayed in help screens.

var app = new CommandApp();
app.Configure(config =>
{
    config.AddCommand<FileSizeCommand>("size")
        .IsHidden()
        .WithAlias("file-size")
        .WithDescription("Gets the file size for a directory.")
        .WithExample(new[] {"c:\\windows", "--pattern", "*.dll"});
});

Dependency Injection

CommandApp takes care of instantiating commands upon execution. If given a custom type registrar, it will use that to resolve services defined in the command constructor.

var registrations = new ServiceCollection();
registrations.AddSingleton<IGreeter, HelloWorldGreeter>();

// Create a type registrar and register any dependencies.
// A type registrar is an adapter for a DI framework.
var registrar = new TypeRegistrar(registrations);

// Create a new command app with the registrar
// and run it with the provided arguments.
var app = new CommandApp<DefaultCommand>(registrar);
return app.Run(args);

TypeRegistrar is a custom class that must be created by the user. This example using Microsoft.Extensions.DependencyInjection as the container provides an example TypeRegistrar and TypeResolver that can be added to your application with small adjustments for your DI container.

Interception

CommandApp also provides a SetInterceptor configuration. An interceptor is ran before all commands are executed. This is typically used for configuring logging or other infrastructure concerns.

All interceptors must implement ICommandInterceptor. Upon execution of a command, an instance of your interceptor will be called with the parsed settings. This provides an opportunity for configuring any infrastructure or modifying the settings.

For an example of using the interceptor to configure logging, see the Serilog demo.