I recently released a major update to my Niche.CommandLineProcessor NuGet package, an open source project that aims to make it easy to write console applications. The goal of the project is to allow you to concentrate on what the application does, not how to control it.

Here’s some sample code, taken from a personal project to illustrate how the library works. In this post, we’ll look at how the command line parameters are defined. A future post will show how to modify Program.cs to make use of these parameters.

I’m writing a toolbox console application that generates and processes various kinds of documents, imaginatively called the Document.Factory.

One of the many (planned) modes of this application to render Markdown documents into HTML, with the ability to embed CSS and some metadata into the final document.

In use, I want the command line for this mode the tool to look something like this:

dfcmd markdown *.md --output-folder .\html -title "Sharpen the Saw"
    --embed-css this.css --embed-css that.css

We start by declaring a new class that declares all of the command line options we need for processing Markdown files. We call this a mode because it’s a distinct way of using the tool, one of many that I plan to build.

public class MarkdownMode
{
    // ...
}

The easiest parameter to define is for specifying the title of the generated HTML files. This optional parameter requires a single string value:

[Description("The title to include in the header of the documents as metadata")]
public void Title(string title) { }

The long form of the parameter will be --title and the short form -t, both derived from the name of the method.

The void return type and the [Description] attribute are both required. Any simple type (such as int) can be used; the Niche.CommandLineProcessor will automatically handle the conversion for you.

The next parameter we define is for specifying the output folder into which HTML files will be written as they are generated.

[Description("Output folder for generated files (defaults to the current directory)")]
public void OutputFolder(DirectoryInfo folder) { }

The long form of the parameter will be --output-folder and the short form -of; note the way the PascalCase of the original name controls the derivation of the parameters. If the method were renamed Outputfolder, the two parameters would be --outputfolder and -o.

Instead of a simple type, this parameter uses a DirectoryInfo. The Niche.CommandLineProcessor identifies a constructor for DirectoryInfo that accepts a string parameter and uses that to construct the required instance. As before, the void return type and the [Description] attribute are both required.

We want to allow our users to include some CSS styling in the generated documents:

[Description("Path specification for CSS file(s) to embed in HTML output files.")]
public void EmbedCss(IEnumerable<PathSpecification> cssFiles) { }

Continuing our established pattern, the long form of the parameter will be --embed-css and the short form -ec.

As we saw above with DirectoryInfo, the PathSpecification class declares a constructor with a string parameter, allowing the Niche.CommandLineProcessor to construct each instance on your behalf.

By declaring the parameter as IEnumerable<PathSpecification>, the Niche.CommandLineProcessor recognizes this as a parameter that can be specified multiple times. All uses are automatically collected up and passed into a single call of the method. Again, the void return type and the [Description] attribute are both required.

With our mode class MarkdownMode complete, we turn our attention to the root mode of our application, the starting point of all our command line parsing.

public class RootMode
{
    // ...
}

To define the markdown mode, we declare this method:

[Description("Render markdown ")]
public MarkdownMode Markdown()
{
    return new MarkdownMode();
}

This defines the new mode as markdown, based on the method name.

Instead of returning void as we do for regular parameters, mode methods return a new instance that’s used to continue processing of the command line. Modes can be nested as deeply as you choose. The [Description] attribute is required.

In a future post, we’ll look at how to make use of these classes.

Comments

blog comments powered by Disqus
Next Post
Handling command line parameters  23 Dec 2017
Prior Post
Sharpen The Saw #23  11 Dec 2017
Related Posts
Browsers and WSL  31 Mar 2024
Factory methods and functions  05 Mar 2023
Using Constructors  27 Feb 2023
An Inconvenient API  18 Feb 2023
Method Archetypes  11 Sep 2022
A bash puzzle, solved  02 Jul 2022
A bash puzzle  25 Jun 2022
Improve your troubleshooting by aggregating errors  11 Jun 2022
Improve your troubleshooting by wrapping errors  28 May 2022
Keep your promises  14 May 2022
Archives
December 2017
2017