Thoughts on Swift Argument Parser
I'm a big fan of Swift Argument Parser. It generally makes command line argument processing painless.
But…
That assumes you are in its primary use case as the main program's command processor.
What if you want to use it to drive a CLI?
You no longer have a primary command, you'll have to sort that out from the first argument. You could do that outside with a dictionary, or make a single fake command and make the rest subcommands. This has some frustrating shortcomings. It would be nicer to add a layer for "one of many commands".
What if your command needs context?
When my SSH command executer in my server wants to run a command, it needs to know how to write its output back to the remote SSH client. The .run()
methods of ArgumentParser don't take arguments. The commands themselves are structs
and really don't want you to be clever and make them classes.
What if the shell didn't break my command into an array of string?
I weep each time I see someone break a command with .split(separator:" ")
. I mean, at least remember to set the omittingEmptySubsequences
that you might not know exists. But what about quoted strings? What about backslashes? What if I want one of the arguments to be an empty string?
Problem Solved
I built ParsableCommands which adds a "one of many commands" layer to ArgumentParser and includes a proper string tokenizer if you need it. Easy to use and very little code.
The context issue is a little harder. The are an astonishingly large number of ways to fail at this in Swift. I tried things for about 6 hours before settling on a per-context-type derived protocol of ParsableCommand, adding an new .run(context:MyType)
method to ParsableCommand, and using a switch
to look at the command between parsing and running and figure out which kind of context it needs from its type.
This doesn't lend itself to a package solution, but the example program in the ParsableCommands package shows how to do it.
Synergy
Combining this with the SSHConsole works very well for having an out of band diagnostic and management interface to an HTTP server.