Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Command Line Parser verb help not working?

Tags:

c#

command

I have defined options as follows:

public class ArgumentsHeader
{
    [VerbOption("configure", HelpText = "Sets configuration on server.")]
    public ServerConfigurationArguments ServerConfigurationArguments { get; set; }

    [HelpVerbOption]
    public string GetUsage(string s)
    {
        return HelpText.AutoBuild(this, s);//always just 'help' or null showing up here.
    }
}
public class ServerConfigurationArguments : ArgumentsBase
{
    [Option('f', "filename", HelpText = "Path to JSON configuration file", DefaultValue = "config.json", Required = true)]
    public string PathToConfig { get; set; }
}

Then parsing them like this:

        string invokedVerb = null;
        object invokedVerbInstance = null;


        var parser = new Parser(x =>
        {
            x.MutuallyExclusive = true;
        });
        var options = new ArgumentsHeader();
        if (!parser.ParseArguments(args, options,
            (verb, subOptions) =>
            {
                // if parsing succeeds the verb name and correct instance
                // will be passed to onVerbCommand delegate (string,object)
                invokedVerb = verb;
                invokedVerbInstance = subOptions;
            }))
        {
            Exit(ExitStatus.InvalidArguments);
        }

But if I try to run my exe with 'help configure' it will just print out entire help, AND in GetUsage(string) method there is only 'help' command showing up in debugger.

Is it a bug or what?

like image 857
eocron Avatar asked Jan 05 '23 06:01

eocron


2 Answers

It IS a bug.

I checked with a program similar to yours and had the same (mis)behavior, then switched to the Command Line project itself, had the same but I think I found the problem.

If you are using the "source" version of Command Line Parser embedded in your project, you may fix it as follows (the code below is from class commandLine.Parser):

private bool TryParseHelpVerb(string[] args, object options, Pair<MethodInfo, HelpVerbOptionAttribute> helpInfo, OptionMap optionMap)
    {
        var helpWriter = _settings.HelpWriter;
        if (helpInfo != null && helpWriter != null)
        {
            if (string.Compare(args[0], helpInfo.Right.LongName, GetStringComparison(_settings)) == 0)
            {
                // User explicitly requested help
                // +++ FIX
                // var verb = args.FirstOrDefault(); // This looks wrong as the first element is always the help command itself
                var verb = args.Length == 1 ? null : args[1]; // Skip the help command and use next argument as verb
                // --- FIX
                if (verb != null)
                {
                    var verbOption = optionMap[verb];
                    if (verbOption != null)
                    {
                        if (verbOption.GetValue(options) == null)
                        {
                            // We need to create an instance also to render help
                            verbOption.CreateInstance(options);
                        }
                    }
                }

                DisplayHelpVerbText(options, helpInfo, verb);
                return true;
            }
        }

        return false;
    }

Unfortunately, if you link directly to the Command Line Parser DLL I don't think there is any workaround for it. In this case only the author can fix it...

like image 67
avat Avatar answered Jan 06 '23 19:01

avat


If you are using the NuGet package, here is a quick work around. Store the args with the options so you can forward the actual verb to HelpText.AutoBuild. Also you will need to have an instance of your Verb Option for the HelpText.AutoBuild to inspect.

public class ArgumentsHeader
{
    public string[] args { get; set; } = new string[0];

    [VerbOption("configure", HelpText = "Sets configuration on server.")]
    public ServerConfigurationArguments ServerConfigurationArguments { get; set; } = new ServerConfigurationArguments();

    [HelpVerbOption]
    public string GetUsage(string verb)
    {
        if (verb?.ToLower() == "help" && args.Length > 1)
        {
            verb = args[1];
        }

        return HelpText.AutoBuild(this, verb);
    }
}

Then just create the options with the args.

 var options = new ArgumentsHeader { args = args };
like image 30
romerod Avatar answered Jan 06 '23 20:01

romerod