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)
    }
}