Skip to content

Repository files navigation

Declarative Command Line

WTQ CI

Nuget

Attribute-driven layer on top of System.CommandLine to make the most common use cases easier to set up.

Minimalistic Example

A minimal example, using DI to instantiate command objects:

Add NuGet Packages

2 packages are needed:

<ItemGroup>
<PackageReferenceInclude="DeclarativeCommandLine"Version="2.0.4" />
<PackageReferenceInclude="DeclarativeCommandLine.Generator"Version="2.0.4" />
<PackageReferenceInclude="Microsoft.Extensions.DependencyInjection"Version="9.0.9"/>
</ItemGroup>

Program.cs

usingDeclarativeCommandLine;usingMicrosoft.Extensions.DependencyInjection;namespaceMyApp;[Command(Description="Math commands")]publicclassAppRootCommand{}[Command(Description="Add 2 numbers",Parent=typeof(AppRootCommand))]publicclassAddCommand:ICommand{[Option(Required=true)]publicintValueA{get;set;}[Option(Required=true)]publicintValueB{get;set;}publicvoidExecute(){Console.WriteLine($"A={ValueA} + {ValueB} = {ValueA+ValueB}");}}publicstaticclassProgram{publicstaticintMain(string[]args){varp=newServiceCollection().AddTransient<AppRootCommand>().AddTransient<AddCommand>().BuildServiceProvider();returnnewCommandBuilder().Build(t =>p.GetRequiredService(t)).Parse(args).Invoke();}}

Result

$ ./myapp
Required command was not provided.
Description:
Usage:
myapp [command] [options]
Options:
-?, -h, --help Show help and usage information
--version Show version information
Commands:
add
$ ./myapp add
Option '--value-a' is required.
Option '--value-b' is required.
Description:
Usage:
myapp add [options]
Options:
--value-a <value-a> (REQUIRED)
--value-b <value-b> (REQUIRED)
-?, -h, --help Show help and usage information
$ ./myapp add --value-a 20 --value-b 22
A=20 + 22 = 42

Generated

This is what the source generator has written, based on the attribute-annotated classes:

/// <auto-generated/>usingDeclarativeCommandLine;usingSystem;usingSystem.CommandLine;namespaceMyApp{publicpartialclassCommandBuilder{publicvirtualRootCommandBuild(Func<Type,object>serviceProvider){varcmd1=newRootCommand();cmd1.Hidden=false;// global::MyApp.AddCommand{varcmd2=newCommand("add");cmd1.Add(cmd2);cmd2.Hidden=false;// Option --value-avaropt3=newOption<Int32>("--value-a");{cmd2.Add(opt3);opt3.Description="";opt3.Hidden=false;opt3.Required=true;}// Option --value-bvaropt4=newOption<Int32>("--value-b");{cmd2.Add(opt4);opt4.Description="";opt4.Hidden=false;opt4.Required=true;}cmd2.SetAction(async(parseResult,ct)=>{varcmd2Inst=(global::MyApp.AddCommand)serviceProvider(typeof(global::MyApp.AddCommand));cmd2Inst.ValueA=parseResult.GetValue(opt3);cmd2Inst.ValueB=parseResult.GetValue(opt4);if(cmd2InstisIAsyncCommandWithParseResultcmd2001){awaitcmd2001.ExecuteAsync(parseResult,ct).ConfigureAwait(false);}if(cmd2InstisIAsyncCommandcmd2002){awaitcmd2002.ExecuteAsync(ct).ConfigureAwait(false);}if(cmd2InstisICommandcmd2003){cmd2003.Execute();}});}returncmd1;}}}

Progress

Command

  • Action
  • Aliases
  • Arguments
  • Description
  • Hidden
  • Name
  • Options
  • Subcommands
  • Completions
  • TreatUnmatchedTokensAsErrors
  • Validators

Arguments

  • AcceptOnlyFromAmong
  • Default
  • Description
  • Name
  • AcceptLegalFileNamesOnly
  • AcceptLegalFilePathsOnly
  • Arity
  • Completions
  • HelpName
  • Hidden
  • Validators

Directives

  • dir.Description
  • dir.Hidden
  • dir.Name

Option

  • opt.AcceptOnlyFromAmong
  • opt.Aliases
  • opt.DefaultValueFactory
  • opt.Description
  • opt.Hidden
  • opt.Name
  • opt.Required
  • opt.AcceptLegalFileNamesOnly
  • opt.AcceptLegalFilePathsOnly
  • opt.AllowMultipleArgumentsPerToken
  • opt.Arity
  • opt.Completions
  • opt.HelpName
  • opt.Recursive
  • opt.Validators

About

Attribute-driven layer on top of System.CommandLine to make the most common use cases easier to set up.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages