robb.re

Optparse applicative

Posted on August 9, 2016

An example of using sub-parsers with optparse applicative. Largely based on https://github.com/rob-b/pivotal

The first things we define are our data types.

When defining the args parser, we start with optionsWithInfo. Almost all of my cli apps have this function; it’s the top-level entry that gets executed by execParser. Here we setup help, info, and description for our argument parser - parseCommand

We define parseCommand to add two option flags, both of which are optional, as well as a sub-command commandParser.

We use a couple of custom Readers in this app so lets look at those

Optparse applicative has a few default readers of which I most commonly use auto and str to parse options as Integers and Strings. In this case I was using functions internally that required ByteString and Text so I wrote a couple of new readers in order to convert my appliction’s options to the correct types at the fringes. I also used readerEnum to ensure that certain options only support certain pre-determined values.

The sub-parsers look as follows.

The stories command is designed to either operate on a list of stories or, given a story id, one specific story. This is the reason that StoriesOption is a sum type of either StoriesDetail or StoriesList.

And here we put together the commandParser sub-command. The sub-commands use a little helper function withInfo (taken from here) that, like optionsWithInfo, adds help, info and descriptions to each sub-command.

For the Profile and Projects data types we don’t require any kind of parsing as they do not take any form of further args and so for those we simply use pure to life them into the Parser.