question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Is there a way to implement multiple level verbs?

See original GitHub issue

Issue by akfish Thursday Oct 31, 2013 at 19:48 GMT _Originally opened as https://github.com/gsscoder/commandline/issues/107_


I am trying to make an app with multiple level of verbs, something like:

app repo list
app repo add
app account list

What I tried is:

    class Options
    {
        #region Global Options
        //...
        #endregion

        #region Help
        //..
        #endregion

        #region Verbs
        [VerbOption("account", HelpText = "Manage mail accounts")]
        public AccountOptions AccountVerb { get; set; }

        [VerbOption("repo", HelpText = "Manage repositories")]
        public RepoOptions RepoVerb { get; set; }
        #endregion
    }

In each verb, nested a sub verb:

    class AccountOptions : IOptions
    {
        [VerbOption("add", HelpText = "Add an account")]
        public AddOption AddVerb { get; set; }

        //And so on....

        public class AddOption : IOptions
        {
        }
        //And so on....

    }

main:

    class Program
    {
        static void Main(string[] args)
        {
            string theVerb = null;
            IOptions theOptions = null;

            var options = new Options();
            if (CommandLine.Parser.Default.ParseArguments(args, options, (verb, subOptions) =>
            {
                theVerb = verb;
                if (verb != null)
                    theOptions = subOptions as IOptions;
            }))
            {
                theOptions.Execute(options);
            }
            else
            {
                Console.Error.WriteLine("Command line parsing error.");
            }
        }
    }

I was able to get first level of verbs to working (e.g. app repo, app account, as the documents said. But the second level ones (app account list, app account add) didn’t.

So is there a way to do this? Thanks.

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:4
  • Comments:13 (12 by maintainers)

github_iconTop GitHub Comments

1reaction
laterwetcommented, Oct 14, 2018

A small trick I found that works quite well. When I find a match with an existing sub-parser (verb), I skip the 1st argument, and forward it to another Parser. This could be done recursively, and probably in a better way than reflection.

    interface ISubParser
    {
        int RunAndReturnExitCode(string[] args);
    }

    [Verb("repo", HelpText = "Manage repositories.")]
    public class RepoVerb : ISubParser
    {
        int ISubParser.RunAndReturnExitCode(string[] args)
        {
            return Parser.Default.ParseArguments<AddOptions, RemoveOptions>(args)
                .MapResult(
                  (AddOptions opts) => AddRepo.RunAndReturnExitCode(opts),
                  (RemoveOptions opts) => RemoveRepo.RunAndReturnExitCode(opts),
                  errs => 1);
        }
    }

    class Program
    {
        private static Type GetSubParser(string verb)
        {
            return Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x =>
                typeof(ISubParser).IsAssignableFrom(x)
                && x.GetCustomAttribute<VerbAttribute>()?.Name == verb);
        }

        static int Main(string[] args)
        {
            if (args.Length > 0)
            {
                Type type = GetSubParser(args[0]);
                if (type != null)
                {
                    // Command with sub-verbs
                    return (Activator.CreateInstance(type) as ISubParser).RunAndReturnExitCode(args.Skip(1).ToArray());
                }
            }

            return Parser.Default.ParseArguments<RepoVerb, AccountVerb>(args)
                .MapResult(
                  (RepoVerb opts) => 1,
                  (AccountVerb opts) => 1,
                  errs => 1);
        }
    }
1reaction
ericnewton76commented, Nov 4, 2017

Comment by akfish Tuesday Dec 02, 2014 at 07:01 GMT


@Nate-Wilkins I was able to implement this feature in my project without actually modifying this project. Here is my implementation: https://github.com/akfish/git-mail/tree/develop/git-mail

You should know that the project linked above was never finished, since later I moved on to node.js for cross-platform purpose and I haven’t been working on .Net platform for almost a year. But the CLI part was completed and would hopefully give you some hints.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Is there a way to implement multiple level verbs? #107
I am trying to make an app with multiple level of verbs, something like: app repo list app repo add app account list...
Read more >
How To Use Multiple Verbs | CSU
Multiple verbs (also known as display commands) can be used to summarize several levels of data, or to display summary data and detail...
Read more >
The Added Power of Multi-Verb Requests
The basic mechanism is to create a multi-verb request and ensure that the verb at the lowest sort level provides the detail that...
Read more >
How to Align Bloom's Verbs with Learning Levels
Learn how to use Bloom's verbs to design learning objectives, activities, and assessments that match the cognitive complexity and challenge of your domain....
Read more >
How to use multiple verbs in one sentence properly - YouTube
This spoken English learning video will teach you the rules you need to follow while using two verbs in same simple sentence and...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found