是否有一个C#的命令行解析库,对git,svn等风格的“子命令”有很好的支持?例如,“git”命令有几个子命令:
git add
git status
git diff
...
必须在子命令名称之前的两个全局选项,以及必须遵循其名称的子命令的特定选项.例如,这些做了不同的事情:
git -p add
git add -p
不同的子命令可能各自具有完全不同的选项和参数集.
我一直在使用NDesk.Options,但到目前为止我还不需要实现子命令.我认为它足够灵活,可以在上面构建子命令,但是如何以简洁优雅的方式做到这一点并不是完全明显的.是否可以在NDesk.Options中执行此操作,或者是否有更合适的C#命令行解析库?
最佳答案 我偏爱
my own option parsing library,我是
blogging about currently.我的确计划涵盖子命令,但是在我达到它之前还需要一段时间(它将是最后的帖子之一).
Nito.KitchenSink.OptionParsing不直接支持子命令,但您可以使用该库仅解析部分命令行,并自行处理子命令. “全局”和“子命令特定”选项集添加了一个有趣的转折,但它可以这样做:
using System;
using System.Linq;
using Nito.KitchenSink.OptionParsing;
class Program
{
private sealed class GlobalOptions : OptionArgumentsBase
{
// Use a better name than "POption". This is just an example.
[Option('p', OptionArgument.None)]
public bool POption { get; set; }
// Override Validate to allow AdditionalArguments.
public override void Validate()
{
}
}
private sealed class AddOptions : OptionArgumentsBase
{
[Option('p', OptionArgument.None)]
public bool POption { get; set; }
}
static int Main()
{
try
{
// Parse the entire command line into a GlobalOptions object.
var options = OptionParser.Parse<GlobalOptions>();
// The first entry in AdditionalArguments is our sub-command.
if (options.AdditionalArguments.Count == 0)
throw new OptionParsingException("No sub-command specified.");
object subcommandOptions = null;
string subcommand = options.AdditionalArguments[0];
switch (subcommand)
{
case "add":
{
// Parse the remaining arguments as command-specific options.
subcommandOptions = OptionParser.Parse<AddOptions>(options.AdditionalArguments.Skip(1));
break;
}
case "status": // TODO: Parse command-specific options for this, too.
break;
case "diff": // TODO: Parse command-specific options for this, too.
break;
default:
throw new OptionParsingException("Unknown sub-command: " + subcommand);
}
// At this point, we have our global options, subcommand, and subcommand options.
Console.WriteLine("Global -p option: " + options.POption);
Console.WriteLine("Subcommand: " + subcommand);
var addOptions = subcommandOptions as AddOptions;
if (addOptions != null)
Console.WriteLine("Add-specific -p option: " + addOptions.POption);
return 0;
}
catch (OptionParsingException ex)
{
Console.Error.WriteLine(ex.Message);
// TODO: write out usage information.
return 2;
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
return 1;
}
}
}
上面的示例程序产生以下输出:
>CommandLineParsingTest.exe
No sub-command specified.
>CommandLineParsingTest.exe -p
No sub-command specified.
>CommandLineParsingTest.exe test
Unknown sub-command: test
>CommandLineParsingTest.exe add
Global -p option: False
Subcommand: add
Add-specific -p option: False
>CommandLineParsingTest.exe -p add
Global -p option: True
Subcommand: add
Add-specific -p option: False
>CommandLineParsingTest.exe add -p
Global -p option: False
Subcommand: add
Add-specific -p option: True
>CommandLineParsingTest.exe -p add -p
Global -p option: True
Subcommand: add
Add-specific -p option: True
>CommandLineParsingTest.exe status
Global -p option: False
Subcommand: status
>CommandLineParsingTest.exe -p status
Global -p option: True
Subcommand: status