Categories
.NET C# SmartCon

SmartCon – Part 2

In the second part of the SmartCon series, I want to talk a little bit about command line arguments help.

As a guy raised in the 80s, I am used to the command line. Most PCs (if you could afford one) weren’t even able to show a graphical user interface. So, all I had was this ugly c:\> prompt an a DOS box or the bash$ prompt on a unix/linux box. The only command I realy knew of, which worked out of the box was turbo, which started the Turbo-Pascal IDE on the DOS-box at school.

When making my first steps on the command line, I realized, a lot of commands offered tons of information via the /h or --help command line argument. And on most commands, there are also tons of command line switches you can use.

When writing my first console apps, I repeatedly wrote code handling a -h command line switch, which always produced a long string, stored in the binary and passes the string to the console output. After the first run realizing all the typos I had in the description, correcting the typos, recompile, re-run, then looking at ugly line-breaks, correcting the line-breaks, re-compile, re-run etc. So, how can can we do this smarter?

SmartCon offers two built in mechanisms for easily providing command line help via the ArgumentHelpProvider class. The easiest way to enrich you console app with a nice help message is via a XML file containing the desired content to be shown.

So, first step is to create an App.config file, if you don’t already have it. Then you need to register a new config section for your command line documentation:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <configSections>
    <section name="Help" 
             type="SmartCon.Help.HelpSection, SmartCon" />
  </configSections>

  [...]

</configuration>
App.config

This enriches the App.config file with a new section named Help, where you can define your command line switches and the corresponding text to be shown when the user asks for the command line help.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
  [...]
  
  <Help>
    <Commands>
      <add key="f" arg="filename" description="Looks for the given file." />
      <add key="h" description="Shows this help page." />
    </Commands>
  </Help>
  
</configuration>
App.config

In this example, we are defining two entries in the help section, one entry for the command line switch -f filename and one for the command line switch -h.

The second thing you need to do to provide the user with your newly created help information, is to set up a command line handler for the -h command line switch, which outputs the help using the previously mentioned ArgumentHelpProvider class.

class Program
{
    // Create a new instance of the SmartConsole:
    private static SmartConsole _console = new SmartConsole();

    private static void Main(string[] args)
    {
        // Set up a handler for the 2 command line switches:
        var handler = new ArgumentProcessor();
        handler.RegisterArgument("h", (v) => GetHelp());
        handler.RegisterArgument("f", (v) => SetFilename(v));

        // Start processing the passed arguments:
        handler.Process(args);
    }

    private static void GetHelp()
    {
        // Set up a new instance of a help provider.
        // The help provider automatically checks the 
        // App.config file for any registered 'Help'
        // section and processes the given information.
        var hp = new ArgumentHelpProvider();
        
        // Retrieve a string conatining the documentation,
        // which is already nicely formatted and also has
        // indentation:
        var help = hp.GetDocumentation();

        // Output the help in the console:
        _console.WriteLine();
        _console.WriteLine(help);

        // Then stop here...
        Environment.Exit(0);
    }

    private static void SetFilename(string filename)
    {
        // set the filename here...
    }	
}
C#

There is also a second way of defining the command line help inline in your code. You can decorate every class with the Documentation attribute, specifying the Key, ArgumentExample and Description properties containing the desired information.

[Documentation(Key = "h", Description = "Shows this help page.")]
[Documentation(Key = "f", ArgumentExample = "filename", 
               Description = "Looks for the given file.")]
class Program
{
    private static SmartConsole _console = new SmartConsole();

    // ...
    
    private static void GetHelp()
    {
        var hp = new ArgumentHelpProvider(typeof(Program));
        var help = hp.GetDocumentation();

        _console.WriteLine();
        _console.WriteLine(help);

        Environment.Exit(0);
    }

}
C#

Please note that the ArgumentHelpProvider is initialized with the type of the class, which was decorated with the Documentation attribute (here: typeof(Program)).

Finally, calling the program with the -h command line switch, will produce the following output:

C:\> .\Demo.exe -h

Usage: Demo -f=filename  -h

-f=filename
    Looks for the given file.

-h
    Shows this help page.
Output

Source is available via github, package available via nuget.org:

By marcus

Software developer, engineer and architect.

Leave a Reply

Your email address will not be published. Required fields are marked *