2020-09-19: Parsing command-line arguments with meap in real programs

Now that meap is feature complete, I’ve started adding it to some personal projects as a replacement for my previous command-line argument parser - simon. Meap is intentionally more conservative in its features than simon, so switching was not always straightforward.

The first program I adapted was sand, which is a replacement for sleep that waits for a given amount of time, but gives you a running update of the amount of time left. It doesn’t have very complicated arguments, so this was not super interesting.

The second program I changed was slime99, which is a game I made for the “7 Day Roguelike” gamejam earlier this year. This was a little more involved. In particular, it revealed a use case I hadn’t planned for: choosing at most one of a set of possibilities. When run in a terminal, slime99 accepts an argument telling what colour space to run in (24-bit rgb, 256 colours, greyscale). This seemed like a common enough use case, so I added some combinators and a macro to make this simpler. The code in slime99 that parses this argument now looks like this:

enum ColEncodeChoice {
    TrueColour,
    Rgb,
    Greyscale,
    Ansi,
}

impl ColEncodeChoice {
    fn parser() -> impl meap::Parser<Item = Self> {
        use meap::Parser;
        use ColEncodeChoice::*;
        meap::choose_at_most_one!(
            flag("true-colour").some_if(TrueColour),
            flag("rgb").some_if(Rgb),
            flag("greyscale").some_if(Greyscale),
            flag("ansi").some_if(Ansi),
        )
        .with_default_general(TrueColour)
    }
}