Moderator: parsing commandline arguments in Swift

There are a lot of command line argument parsers written in Swift available on Github, so when I needed one for a client project I was surprised I could not find any which fulfilled these requirements:

  • handle --tag=value.
  • treat unrecognised arguments as an error and list them.

Nor could I find any where it would be relatively easy to add these features, since most just loop through the arguments from first to last and have one big function trying to find out what to do with each of them. That becomes messy quickly.

I think it’s much simpler to create multiple small argument parsers, where each one in turn takes in the list of arguments, removes the ones it wants to handle and passes the rest on to the next one. Any arguments left over are then unrecognised and can be handled accordingly. This way the end user does not need to worry about the order of the arguments. The developer however needs to be careful about the order of the parsers.

So I created Moderator with these goals:

  • required arguments and those with default values should not produce optionals.
  • easily combine parsers.
  • type-safe.
  • make it easy to ensure all provided arguments are valid before acting upon any of them.

And as always:

  • as simple as possible, but no simpler.

And this is what it looks like (from linuxmain-generator):

For more, see the project homepage.

  • Looks cool. I was going to try using SwiftShell, so will probably give this a try too.

    Calling reduce on the parsers array seemed kinda puzzling at first, and the overall behavior seems a little bit emergent rather than explicit, but I think I get how most of it works now. However some questions:

    1) If i wanted an option that can be repeated, like how the “verbose” option is often used, I need to write a custom parser that counts occurrences, or collects repeated values? And currently, repeated instances of valid options just end up in “remaining”, right?
    2) Interleaving simple arguments and options will work because the parsed options get removed first?
    3) I don’t see it, is there something that prevents anything following a “–” argument from being treated as an option?
    4) If i wanted to allow something like the trailing arguments to commands like “cp file files…”, they’re in “remaining” after calling “parse” with “strict: false”?
    5) If strict is false, I’d have to manually detect unknown options within “remaining” as well as occurrences of “–“? Would it be good to instead make a custom parser that collects arbitrary trailing arguments instead of relying on “remaining”?