Accessing global options
I don't see how to handle global options with the new 2.0 API.
var cmd = //... some Command, the RootCommand is somewhere else created, not accessible here
var arg = new Argument<string>("x", "Mysterious x");
cmd.SetHandler(async (string x) =>
{
await DoSomething(x);
},
someArgument);`
Question: How to access/fill global options in this case?
You'll need to have access to your Option<T> instance that was used as a global option and pass it into SetHandler.
I dont think that's going to be a very helpful API when you're building a complex CLI, say you have commands nested 3 layers deep, you're going to be passing alot of dependencies around. If this is set in stone, then I'd maybe go so far as to say the method to AddGlobalOption should be removed if they're not actually "global"
The option is global within the command line interface. Effectively, AddGlobalOption lets you replace calls like this:
var option = new Option<string>("-x");
var rootCommand = new RootCommand
{
option,
new Command("subcommand")
{
option
}
};
with something like this:
var option = new Option<string>("-x");
var rootCommand = new RootCommand
{
new Command("subcommand")
};
rootCommand.AddGlobalOption(option);
when you're building a complex CLI, say you have commands nested 3 layers deep, you're going to be passing alot of dependencies around
Can you give an example?
hey @jonsequitur - this is the sort of thing I mean: https://gist.github.com/abbottdev/7bbfd9e59752cd15a93d684e7bad616f
The reason for creating sub-classed commands is because the composability of the commands when you need to specify handlers ends up with a mass of variables - bear in mind this is a simple example :)
With the above ^ I dont see what value adding AddGlobalOption does - if you have to pass the option around anyway as it would be a dependency to all commands that require it, and therefore it's implicitly global.
Thanks, @abbotdev. Your example seems to mix instantiating subcommands within your constructors while passing in the global option. I wonder if a static property on a base class would be more consistent with this OOP style?
public class MyCommand : Command
{
public static Option<string> envOption = new("--env", "An environment override");
public MyCommand(string name, string description) : base(name, description) {}
}
public class GenerateMessageCommand : MyCommand
{
public GenerateMessageCommand() : base("message", "Generates messages")
{
this.AddOption(envOption);
this.AddCommand(new Command("order", "Generates order messages"));
this.AddCommand(new GenerateStockMessageCommand(envOption));
}
}
Since https://github.com/dotnet/command-line-api/pull/2083, you can also use ParseResult.GetValue<T>(string name) to look up the values of global options, in which case you don't need to carry the Option<T> instance around; but then the compiler cannot verify that you've spelled the name of the option correctly.