Closed
Description
Hi.
I like this library a lot! But one thing I'm missing is support for "verbs". Like when the first argument on command line is a verb which then has options specific to that verb. Similar to git commit -m "message"
.
I put the code below together as a proof of concept. Though, looking at it now I think I would have preferred to have the Option
attribute assigned to parameters of the method instead of a dedicated class, but that would require some more intrusive changes. Is this something you would be interested in exploring or is totally out of scope for this library?
using System;
using System.Linq;
using System.Reflection;
using CommandLine;
namespace SampleApp
{
public class VerbProgram
{
private static void Main(string[] args)
{
//MyVerbs.FooOptions options = new MyVerbs.FooOptions();
//if (!CommandLineParser.Default.ParseArguments(
// new[] { "--flag" }, options))
//{
// Environment.Exit(1);
//}
MyVerbs verbs = new MyVerbs();
if (!VerbParser.Default.ParseArguments(
new[] { "foo", "--flag" }, verbs))
{
Environment.Exit(1);
}
Environment.Exit(0);
}
}
internal class MyVerbs
{
internal class FooOptions : CommandLineOptionsBase
{
[Option("f", "flag", Required = true)]
public bool Flag { get; set; }
}
[Verb]
public void Foo(FooOptions options)
{
Console.WriteLine(options.Flag);
}
}
public class VerbAttribute : Attribute
{
/// <summary>
/// By default the name of the verb is a lowercase version of the
/// method name, set this property to override.
/// </summary>
public string Name { get; set; }
public string HelpText { get; set; }
}
internal class VerbParser
{
public static VerbParser Default = new VerbParser();
internal ICommandLineParser ArgumentParser = CommandLineParser.Default;
public bool ParseArguments(string[] args, object verbs)
{
// store name of verb and remove it from args
var verbName = args[0];
args = args.Skip(1).ToArray();
// find verb method
Pair<MethodInfo, VerbAttribute> verb = null;
foreach (Pair<MethodInfo, VerbAttribute> pair in
ReflectionUtil.RetrieveMethods<VerbAttribute>(verbs))
{
string name = pair.Right.Name;
if (string.IsNullOrEmpty(name))
{
name = pair.Left.Name.ToLower();
}
if (verbName.Equals(name))
{
verb = pair;
break;
}
}
if (verb == null)
{
return false; // verb not found
}
object options = Activator.CreateInstance(
verb.Left.GetParameters()[0].ParameterType);
if (!ArgumentParser.ParseArguments(args, options))
{
return false; // couldnt parse verb arguments
}
verb.Left.Invoke(verbs, new[] {options});
return true;
}
}
}
Metadata
Metadata
Assignees
Labels
No labels