Cli Class
Definition
- Namespace
- DotMake.CommandLine
- Assembly
- DotMake.CommandLine.dll
Provides methods for parsing command line input and running an indicated command.
public static class Cli
- Inheritance
-
Cli
Examples
//Delegate-based model
//In Program.cs, add this simple code:
Cli.Run(([CliArgument] string argument1, bool option1) =>
{
Console.WriteLine($@"Value for {nameof(argument1)} parameter is '{argument1}'");
Console.WriteLine($@"Value for {nameof(option1)} parameter is '{option1}'");
});
//Or:
Cli.Run(Method);
void Method([CliArgument] string argument2, bool option2)
{
Console.WriteLine($@"Value for {nameof(argument2)} parameter is '{argument2}'");
Console.WriteLine($@"Value for {nameof(option2)} parameter is '{option2}'");
}
// Class-based model
// Create a simple class like this:
[CliCommand(Description = "A root cli command")]
public class RootCliCommand
{
[CliOption(Description = "Description for Option1")]
public string Option1 { get; set; } = "DefaultForOption1";
[CliArgument(Description = "Description for Argument1")]
public string Argument1 { get; set; }
public void Run()
{
Console.WriteLine($@"Handler for '{GetType().FullName}' is run:");
Console.WriteLine($@"Value for {nameof(Option1)} property is '{Option1}'");
Console.WriteLine($@"Value for {nameof(Argument1)} property is '{Argument1}'");
Console.WriteLine();
}
}
//In Program.cs, add this single line:
Cli.Run<RootCliCommand>(args);
//If you need to simply parse the command-line arguments without invocation, use this:
var result = Cli.Parse<RootCliCommand>(args);
var rootCliCommand = result.Bind<RootCliCommand>();
// A root cli command which shows help if command is empty, i.e. no arguments or options are passed.
// Arguments and options should be optional, if they are required (no default values),
// then handler will not run and missing error message will be shown.
[CliCommand(Description = "A root cli command")]
public class RootHelpOnEmptyCliCommand
{
[CliOption(Description = "Description for Option1")]
public string Option1 { get; set; } = "DefaultForOption1";
[CliArgument(Description = "Description for Argument1")]
public string Argument1 { get; set; } = "DefaultForArgument1";
public void Run(CliContext context)
{
if (context.IsEmptyCommand())
context.ShowHelp();
else
context.ShowValues();
}
}
//In Program.cs, add this single line for returning exit code:
return Cli.Run<RootCliCommand>(args);
//In Program.cs, to go async, add this single line:
await Cli.RunAsync<RootCliCommand>(args);
//In Program.cs, to go async, add this single line for returning exit code:
return await Cli.RunAsync<RootCliCommand>(args);
//If you need to examine the parse result, such as errors:
var result = Cli.Parse<RootCliCommand>(args);
if (result.ParseResult.Errors.Count > 0)
{
}
//To handle exceptions, you just use a try-catch block:
try
{
Cli.Run<RootCliCommand>(args);
}
catch (Exception e)
{
Console.WriteLine(@"Exception in main: {0}", e.Message);
}
//System.CommandLine, by default overtakes your exceptions that are thrown in command handlers
//(even if you don't set an exception handler explicitly) but DotMake.CommandLine, by default allows
//the exceptions to pass through. However if you wish, you can easily use the default exception handler
//by passing a `CliSettings` instance like below. Default exception handler prints the exception in red color to console:
Cli.Run<RootCliCommand>(args, new CliSettings { EnableDefaultExceptionHandler = true });
using DotMake.CommandLine;
using Microsoft.Extensions.DependencyInjection;
// When the source generator detects that your project has reference to `Microsoft.Extensions.DependencyInjection`,
// it will generate extension methods for supporting dependency injection.
// For example, you can now add your services with the extension method `Cli.Ext.ConfigureServices`:
Cli.Ext.ConfigureServices(services =>
{
services.AddTransient<TransientClass>();
services.AddScoped<ScopedClass>();
services.AddSingleton<SingletonClass>();
});
Cli.Run<RootCliCommand>();
//Then let them be injected to your command class automatically by providing a constructor with the required services:
[CliCommand(Description = "A root cli command with dependency injection")]
public class RootCliCommand
{
private readonly TransientClass transientDisposable;
private readonly ScopedClass scopedDisposable;
private readonly SingletonClass singletonDisposable;
public RootCliCommand(
TransientClass transientDisposable,
ScopedClass scopedDisposable,
SingletonClass singletonDisposable
)
{
this.transientDisposable = transientDisposable;
this.scopedDisposable = scopedDisposable;
this.singletonDisposable = singletonDisposable;
}
[CliOption(Description = "Description for Option1")]
public string Option1 { get; set; } = "DefaultForOption1";
[CliArgument(Description = "Description for Argument1")]
public string Argument1 { get; set; } = "DefaultForArgument1";
public void Run()
{
Console.WriteLine($@"Handler for '{GetType().FullName}' is run:");
Console.WriteLine($@"Value for {nameof(Option1)} property is '{Option1}'");
Console.WriteLine($@"Value for {nameof(Argument1)} property is '{Argument1}'");
Console.WriteLine();
Console.WriteLine($"Instance for {transientDisposable.Name} is available");
Console.WriteLine($"Instance for {scopedDisposable.Name} is available");
Console.WriteLine($"Instance for {singletonDisposable.Name} is available");
Console.WriteLine();
}
}
public sealed class TransientClass : IDisposable
{
public string Name => nameof(TransientClass);
public void Dispose() => Console.WriteLine($"{nameof(TransientClass)}.Dispose()");
}
public sealed class ScopedClass : IDisposable
{
public string Name => nameof(ScopedClass);
public void Dispose() => Console.WriteLine($"{nameof(ScopedClass)}.Dispose()");
}
public sealed class SingletonClass : IDisposable
{
public string Name => nameof(SingletonClass);
public void Dispose() => Console.WriteLine($"{nameof(SingletonClass)}.Dispose()");
}
Properties
| Ext |
Provides extension methods for Cli. These are usually automatically generated by the source generator
when current project supports a specific feature through a dependency,
e.g. when you add package |
Methods
| GetArgs() |
Returns a string array containing the command-line arguments for the current process.
Uses GetCommandLineArgs()but skips the first element which is the executable file name,
so the following zero or more elements that contain the remaining command-line arguments are returned,
i.e. returns the same as the special variable Also on Windows platform, backslash + double quote ( |
| GetParser(Type, CliSettings) |
Gets a CLI parser configured for the indicated command. |
| GetParser<TDefinition>(CliSettings) |
Gets a CLI parser configured for the indicated command. |
| Parse<TDefinition>(string, CliSettings) |
Parses a command line string and returns the parse result for the indicated command. |
| Parse<TDefinition>(string[], CliSettings) |
Parses a command line string array and returns the parse result for the indicated command. |
| Run(Delegate, CliSettings) |
Parses the command line arguments and runs the indicated command as delegate. |
| Run<TDefinition>(string, CliSettings) |
Parses a command line string value and runs the handler for the indicated command. |
| Run<TDefinition>(string[], CliSettings) |
Parses a command line string array and runs the handler for the indicated command. |
| RunAsync(Delegate, CliSettings, CancellationToken) |
Parses the command line arguments and runs the indicated command as delegate. |
| RunAsync<TDefinition>(string, CliSettings, CancellationToken) |
Parses a command line string value and runs the handler asynchronously for the indicated command. |
| RunAsync<TDefinition>(string[], CliSettings, CancellationToken) |
Parses a command line string array and runs the handler asynchronously for the indicated command. |