When it comes to writing CLI tools or simple scripts, bash is a pretty good solution. If you follow a few simple rules and make sure to check & document all your dependencies, you can create tools that work on a wide variety of systems and platforms (even Windows). However, where bash starts to fall down is when you need to create much more complex tooling. Not impossible, but it just gets harder and harder to maintain (and also lacks a few basic features of modern languages).
Enter Swift (my favorite language) and Apple’s Swift Argument Parser project. It’s an Open Source project actively maintained by Apple, that allows you to use Swift to create complex CLI tooling within a few minutes.
It literally takes you less than 3 minutes to set up the basic project and have the first CLI command ready (given that you already know Swift).
Have a look at this project for a simple CLI with two commands and a bunch of options/flags I created for a small project of mine.
The project is pretty self explanatory and Apple’s documentation is pretty good, too.
Essentially, you write “Commands” like this:
import ArgumentParser
struct Something: ParsableCommand {
@Flag(help: "Include flag.")
var include = false
@Option(name: .shortAndLong, help: "Some option.")
var option: Int?
@Argument(help: "A mandatory argument.")
var argument: String
func validate() throws {
// Validation logic
}
func run() throws {
// do something
}
}
Something.main()
And then you can compile it and run the tool like this:
$ something --help
USAGE: something [--option <option>] [--include] <argument>
ARGUMENTS:
<argument> A mandatory argument.
OPTIONS:
--include Include flag.
-o, --option <option> Some Option.
-h, --help Show help for this command.
Of course you can have more complex tools with multiple commands and different options per command.
So you can easily build a tool like this:
$ changelog-generator
OVERVIEW: A Swift command-line tool to generate changelogs for configured projects
USAGE: changelog-generator [--config-file <config-file>] <subcommand>
OPTIONS:
-c, --config-file <config-file>
-h, --help Show help information.
SUBCOMMANDS:
generate Generate Changelogs for a project
generate-all Generate Changelogs for all projects
See 'changelog-generator help <subcommand>' for detailed help.
$ changelog-generator help generate
OVERVIEW: Generate Changelogs for a project
USAGE: changelog-generator generate <release> [--push] [--create-mr] [--no-delete] [--access-token <access-token>] [--base-branch <base-branch>] [--git-url <git-url>] [--local-path <local-path>]
ARGUMENTS:
<release> The name of the release, e.g. 8.0-IT-32
OPTIONS:
-c, --config-file <config-file>
--push Push
-m, --create-mr Create merge request
--no-delete Don't delete git project when finished
-t, --access-token <access-token>
Personal access token (needed for merge request operations)
-b, --base-branch <base-branch>
Base branch (default: master)
-g, --git-url <git-url> Git Url
-l, --local-path <local-path>
Path to local git repo
-h, --help Show help information.