commandlineparser / commandline

The best C# command line parser that brings standardized *nix getopt style, for .NET. Includes F# support
MIT License
4.46k stars 473 forks source link

Show syntax when user does not specify parameters #896

Closed nandaccio closed 11 months ago

nandaccio commented 11 months ago

I would like to show the syntax, based on my "Options" class (it contains only a few, simple, options), when the user does not provide any parameter from the command line.

Invoking :

 private static void ShowSyntax(string[] args)
        {
            var parserResult = new Parser(with => { with.HelpWriter = null; with.AutoHelp = false; with.AutoVersion = false; }).ParseArguments<Options>(args);

            var helpText = HelpText.AutoBuild(parserResult, h =>
            {
                h.AdditionalNewLineAfterOption = false;
                h.AddDashesToOption = true;
                h.AddEnumValuesToHelpText = true;
                h.AutoVersion = false;
                h.AutoHelp = false;
                h.Copyright = string.Empty;
                return h; //return HelpText.DefaultParsingErrorsHandler(parserResult, h);
            }, e => e);

            Console.WriteLine(helpText);
        }

results in displaying version number, copyright information and --help + --version, despite the fact that everything should be configured to hide these details:

image

elgonzo commented 11 months ago

(Disclaimer: I am not involved in the project, and neither am i associated in any way with the project maintainer(s).)

This is one of the quirks and limitations of this library that needs to be worked around by the user.

Note that the second parameter of the HelpText.AutoBuild method is called onError: https://github.com/commandlineparser/commandline/blob/1e3607b97af6141743edb3c434c06d5b492f6fb3/src/CommandLine/Text/HelpText.cs#L320-L326

Which is an appropriate name for that parameter, because this delegate won't be called if there is no error in the provided CLI options/arguments. For some reason, however, the library handles the automatically generated help and version options/verbs also as errors. Requesting help via the auto help option/verb will lead to a special "help requested error". Which in turn will lead to the onError delegate being executed. (How the library implements the automatic help and auto version options/verbs is in my opinion not very good code design, but it is what it is...)


For simple application cases it should be sufficient to replace the empty args[] array with a string array containing only "--help", resulting in a parser result with an "unknown option error", thus the onError delegate will be executed.

If for some reason that error type is not suitable for you and you really need an actual "help requested error", then use a separate parser instance with auto help being keptt enabled for creating a parser result with a "help requested error" in case no CLI options/arguments have been passed to the program:

var parserResult =
    (args.Length == 0)
        ? new Parser().ParseArguments<Options>(new[] {"--help"})
        : new Parser(with => { with.HelpWriter = null; with.AutoHelp = false; with.AutoVersion = false; }).ParseArguments<Options>(args);
nandaccio commented 11 months ago

Thank you @elgonzo for your very thorough explanation, it was very helpful as I could not find a way to implement it looking at the examples/documentation.

I am sharing my version of a ShowSyntax() method here, as it may help people who don't want to show copyright information, --help/--version and heading (e.g. the version number):

         private static void ShowSyntax()
        {
            var parserResult = new Parser().ParseArguments<Options>(new[] { "--help"});

            var helpText = HelpText.AutoBuild(parserResult, h =>
            {
                 h.AdditionalNewLineAfterOption = false;
                 h.AddDashesToOption = true;
                 h.AddEnumValuesToHelpText = true;
                 h.AutoVersion = false;
                 h.AutoHelp = false;
                 h.Copyright = string.Empty;
                 h.Heading = string.Empty;
                 return h;
            }, e => e);

            Console.WriteLine(helpText);
        }