CliArgumentAttribute Class
Definition
- Namespace
- DotMake.CommandLine
- Assembly
- DotMake.CommandLine.dll
Specifies a class property that represents an argument which is a value that can be passed on the command line to a command or an option.
[CliArgument]
public string SomeCliArgument { get; set; }
Note that an argument is required if the decorated property does not have a default value (set via a property initializer), see Required property for details.
Arguments: An argument is a value passed to an option or a command. The following examples show an argument for the verbosity option and an argument for the build command.
dotnet tool update dotnet-suggest --verbosity quiet --global
^---^
dotnet build myapp.csproj
^----------^
Arguments can have default values that apply if no argument is explicitly provided. For example, many options are implicitly Boolean parameters with a default of true when the option name is in the command line.
[AttributeUsage(AttributeTargets.Property|AttributeTargets.Parameter)]
public class CliArgumentAttribute : Attribute
- Inheritance
-
CliArgumentAttribute
Examples
// 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>();
//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 pass a method reference:
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}'");
}
// Localizing commands, options and arguments is supported.
// You can specify a `nameof` operator expression with a resource property (generated by resx) in the attribute's argument (for `string` types only)
// and the source generator will smartly use the resource property accessor as the value of the argument so that it can localize at runtime.
// If the property in the `nameof` operator expression does not point to a resource property, then the name of that property will be used as usual.
// The reason we use `nameof` operator is that attributes in `.NET` only accept compile-time constants and you get `CS0182` error if not,
// so specifying resource property directly is not possible as it's not a compile-time constant but it's a static property access.
[CliCommand(Description = nameof(TestResources.CommandDescription))]
public class LocalizedCliCommand
{
[CliOption(Description = nameof(TestResources.OptionDescription))]
public string Option1 { get; set; } = "DefaultForOption1";
[CliArgument(Description = nameof(TestResources.ArgumentDescription))]
public string Argument1 { get; set; }
}
// Note that you can have a specific type (other than `string`) for a property which a `CliOption` or `CliArgument`
// attribute is applied to, for example these properties will be parsed and bound/populated automatically:
[CliCommand]
public class WriteFileCliCommand
{
[CliArgument]
public FileInfo OutputFile { get; set; }
[CliOption]
public List<string> Lines { get; set; }
public void Run()
{
if (OutputFile.Exists)
return;
using (var streamWriter = OutputFile.CreateText())
{
foreach (var line in Lines)
{
streamWriter.WriteLine(line);
}
}
}
}
// Any type with a public constructor or a static `Parse` method with a string parameter (other parameters, if any,
// should be optional) - These types can be bound/parsed automatically even if they are wrapped
// with `Enumerable` or `Nullable` type.
[CliCommand]
public class ArgumentConverterCliCommand
{
[CliOption(Required = false)]
public ClassWithConstructor Opt { get; set; }
[CliOption(Required = false, AllowMultipleArgumentsPerToken = true)]
public ClassWithConstructor[] OptArray { get; set; }
[CliOption(Required = false)]
public CustomStruct? OptNullable { get; set; }
[CliOption(Required = false)]
public IEnumerable<ClassWithConstructor> OptEnumerable { get; set; }
[CliOption(Required = false)]
public List<ClassWithConstructor> OptList { get; set; }
[CliOption(Required = false)]
public CustomList<ClassWithConstructor> OptCustomList { get; set; }
[CliArgument]
public IEnumerable<ClassWithParser> Arg { get; set; }
public void Run(CliContext context)
{
context.ShowValues();
}
}
public class ClassWithConstructor
{
private readonly string value;
public ClassWithConstructor(string value)
{
if (value == "exception")
throw new Exception("Exception in ClassWithConstructor");
this.value = value;
}
public override string ToString()
{
return value;
}
}
public class ClassWithParser
{
private string value;
public override string ToString()
{
return value;
}
public static ClassWithParser Parse(string value)
{
if (value == "exception")
throw new Exception("Exception in ClassWithParser");
var instance = new ClassWithParser();
instance.value = value;
return instance;
}
}
public struct CustomStruct
{
private readonly string value;
public CustomStruct(string value)
{
this.value = value;
}
public override string ToString()
{
return value;
}
}
// Arrays, lists, collections - any type that implements `IEnumerable<T>` and has a public constructor with a `IEnumerable<T>`
// or `IList<T>` parameter (other parameters, if any, should be optional).
// If type is generic `IEnumerable<T>`, `IList<T>`, `ICollection<T>` interfaces itself, array `T[]` will be used.
// If type is non-generic `IEnumerable`, `IList`, `ICollection` interfaces itself, array `string[]` will be used.
[CliCommand]
public class EnumerableCliCommand
{
[CliOption(Required = false)]
public IEnumerable<int> OptEnumerable { get; set; }
[CliOption(Required = false)]
public List<string> OptList { get; set; }
[CliOption(Required = false, AllowMultipleArgumentsPerToken = true)]
public FileAccess[] OptEnumArray { get; set; }
[CliOption(Required = false)]
public Collection<int?> OptCollection { get; set; }
[CliOption(Required = false)]
public HashSet<string> OptHashSet { get; set; }
[CliOption(Required = false)]
public Queue<FileInfo> OptQueue { get; set; }
[CliOption(Required = false)]
public CustomList<string> OptCustomList { get; set; }
[CliArgument]
public IList ArgIList { get; set; }
public void Run(CliContext context)
{
context.ShowValues();
}
}
public class CustomList<T> : List<T>
{
public CustomList(IEnumerable<T> items)
: base(items)
{
if (items is IEnumerable<string> strings && strings.First() == "exception")
throw new Exception("Exception in CustomList");
}
}
// In `[CliOption]` and `[CliArgument]` attributes;
// `ValidationRules` property allows setting predefined validation rules such as `ExistingFile`, `NonExistingFile`, `ExistingDirectory`,
// `NonExistingDirectory`, `ExistingFileOrDirectory`, `NonExistingFileOrDirectory`, `LegalPath`, `LegalFileName`, `LegalUri`, `LegalUrl`.
// Validation rules can be combined.
// `ValidationPattern` property allows setting a regular expression pattern for custom validation,
// and `ValidationMessage` property allows setting a custom error message to show when `ValidationPattern` does not match.
[CliCommand]
public class ValidationCliCommand
{
[CliOption(Required = false, ValidationRules = CliValidationRules.ExistingFile)]
public FileInfo OptFile1 { get; set; }
[CliOption(Required = false, ValidationRules = CliValidationRules.NonExistingFile | CliValidationRules.LegalPath)]
public string OptFile2 { get; set; }
[CliOption(Required = false, ValidationRules = CliValidationRules.ExistingDirectory)]
public DirectoryInfo OptDir { get; set; }
[CliOption(Required = false, ValidationPattern = @"(?i)^[a-z]+$")]
public string OptPattern1 { get; set; }
[CliOption(Required = false, ValidationPattern = @"(?i)^[a-z]+$", ValidationMessage = "Custom error message")]
public string OptPattern2 { get; set; }
[CliOption(Required = false, ValidationRules = CliValidationRules.LegalUrl)]
public string OptUrl { get; set; }
[CliOption(Required = false, ValidationRules = CliValidationRules.LegalUri)]
public string OptUri { get; set; }
[CliArgument(Required = false, ValidationRules = CliValidationRules.LegalFileName)]
public string OptFileName { get; set; }
public void Run(CliContext context)
{
context.ShowValues();
}
}
[CliCommand(Description = "A root cli command with custom order")]
public class OrderedCliCommand
{
[CliOption(Description = "Description for Option1", Order = 2)]
public string Option1 { get; set; } = "DefaultForOption1";
[CliOption(Description = "Description for Option2", Order = 1)]
public string Option2 { get; set; } = "DefaultForOption2";
[CliArgument(Description = "Description for Argument1", Order = 2)]
public string Argument1 { get; set; } = "DefaultForArgument1";
[CliArgument(Description = "Description for Argument2", Order = 1)]
public string Argument2 { get; set; } = "DefaultForArgument2";
[CliCommand(Description = "Description for sub-command1", Order = 2)]
public class Sub1CliCommand
{
}
[CliCommand(Description = "Description for sub-command2", Order = 1)]
public class Sub2CliCommand
{
}
}
/*
Apps that use System.CommandLine have built-in support for tab completion in certain shells.
To enable it, the end user has to [take a few steps once per shell](https://learn.microsoft.com/en-us/dotnet/standard/commandline/tab-completion#get-tab-completion-values-at-run-time).
Once the user does this, tab completion is automatic for static values in your app, such as enum values or values you
define by setting `CliOptionAttribute.AllowedValues` or `CliArgumentAttribute.AllowedValues`.
You can also customize the tab completion by getting values dynamically at runtime.
In your command class, inherit `ICliGetCompletions` and implement `GetCompletions` method.
This method will be called for every option and argument in your class.
In the method, you should switch according to the property name
which corresponds to the option or argument whose completions will be retrieved.
The dynamic tab completion list created by this code also appears in help output:
*/
[CliCommand(Description = "A root cli command with completions for options and arguments")]
public class GetCompletionsCliCommand : ICliGetCompletions
{
[CliOption(Description = "Description for DateOption")]
public DateTime DateOption { get; set; }
[CliArgument(Description = "Description for FruitArgument")]
public string FruitArgument { get; set; } = "DefaultForFruitArgument";
public void Run(CliContext context)
{
if (!context.Result.HasArgs)
context.ShowHelp();
else
context.ShowValues();
}
public IEnumerable<CompletionItem> GetCompletions(string propertyName, CompletionContext completionContext)
{
switch (propertyName)
{
case nameof(DateOption):
var today = DateTime.Today;
var dates = new List<CompletionItem>();
foreach (var i in Enumerable.Range(1, 7))
{
var date = today.AddDays(i);
dates.Add(new CompletionItem(
label: date.ToShortDateString(),
sortText: $"{i:2}"));
}
return dates;
case nameof(FruitArgument):
return new [] { "apple", "orange", "banana" }
.Select(value => new CompletionItem(value));
}
return Enumerable.Empty<CompletionItem>();
}
}
Properties
| AllowedValues |
Gets or sets the list of allowed values for an argument. Configures an argument to accept only the specified values, and to suggest them as command line completions. Note that if the argument type is an enum, values are automatically added. |
| Arity |
Gets or sets the arity of the argument. The arity refers to the number of values that can be passed on the command line. In most cases setting argument arity is not necessary as it is automatically determined based on the argument type (the decorated property's type):
|
| Description |
Gets or sets the description of the argument. This will be displayed in usage help of the command line application. |
| HelpName |
Gets or sets the name of the argument when displayed in help. |
| Hidden |
Gets or sets a value indicating whether the argument is hidden. You might want to support a command, option, or argument, but avoid making it easy to discover. For example, it might be a deprecated or administrative or preview feature. Use the Hidden property to prevent users from discovering such features by using tab completion or help. |
| Name |
Gets or sets the name of the argument that will be used mainly for displaying in usage help of the command line application.
If not set (or is empty/whitespace), the name of the property that this attribute is applied to, will be used to generate argument name automatically:
These suffixes will be stripped from the property name:
Default convention can be changed via parent command's NameCasingConvention property. |
| Order |
Gets or sets the order of the argument. The order is used when printing the symbols in help and for arguments additionally effects the parsing order. When not set (or is |
| Required |
Gets or sets a value indicating whether the argument is required when its parent command is invoked. Default is auto-detected. An option/argument will be considered required when
An option/argument will be considered optional when
When an argument is required, the argument has to be specified on the command line and if its parent command is invoked without it, an error message is displayed and the command handler isn't called. When an argument is not required, the argument doesn't have to be specified on the command line, the default value provides the argument value. |
| ValidationMessage |
Gets or sets an error message to show when ValidationPattern does not match and validation fails. |
| ValidationPattern |
Gets or sets a regular expression pattern used to determine if argument value(s) is valid.
Note that you can specify regular expression options inline in the pattern with the syntax
Regular expression quick reference
|
| ValidationRules |
Gets or sets a set of validation rules used to determine if argument value(s) is valid. When combining validation rules, use bitwise 'or' operator(| in C#):
|