Command Aliases with Superpowers to Replace Make (Announcing Bonnie v0.3.0)
Tags: rust, productivity, make
Published: 2021-07-09 01:09:54

{% github arctic-hen7/bonnie %}

Let's talk about command aliases, making short commands to reference longer ones. What tool springs to mind for you? If you're a JavaScript developer, probably NPM or Yarn scripts, which have such features inbuilt. If you use any other language, Make is probably at the top of the list.

For a very long time, there have been very few dedicated command aliasing tools, and yet build commands get more and more complex! Make was designed as a full build tool, though it's regularly used for simple command aliasing, which is absolute overkill! Not only is Make old and clunky, using it for command aliasing is like using a sledgehammer to crack an egg!

Make works well for command aliasing, but we can do better. Make is great for what it was designed for, don't get me wrong, but that was **not** simple command aliasing. And yet without Make, we have basically no real solutions though to command aliasing on a per-project basis (sure you can define global aliases in `~/.bash_aliases`, but they don't help for multiple different projects).

Enter [Bonnie](https://github.com/arctic-hen7/bonnie), a tool I built a while ago while I was learning Rust. Since then, I've used Bonnie every day to manage my own command aliases, and it's recently undergone significant changes.

Now, Bonnie supports everything from simple key-value command aliasing to nested subcommands, it has a miniature programming language inbuilt that allows you to specify control flow between commands, and it even supports running different commands on different operating systems, the holy grail of cross-platform collaboration.

Bonnie also has [extensive documentation](https://github.com/arctic-hen7/bonnie/wiki) and pre-built binaries on [its releases page](https://github.com/arctic-hen7/bonnie/releases) for Linux, MacOS, Windows, and even musl (for Alpine Linux and the like).

The rest of this post will be a brief tutorial on how to use Bonnie to make command aliasing dead simple in your projects.

## Installation

1. Head over to [the releases page](https://github.com/arctic-hen7/bonnie/releases) and download the latest binary for your OS.
2. Move that binary to somewhere from which you can execute it easily (e.g. `/usr/local/bin` on Linux).
3. Run `bonnie -v` as a sanity check in the terminal.

## Setup

1. Go into a project that needs command aliasing.
2. Run `bonnie -i`.

Congratulations! You now have a super-basic Bonnie configuration in that directory in `bonnie.toml`. It's written in TOML, which is designed to be a human-readable version of JSON and YAML that doesn't sacrifice features.

## Alias time

Let's say you have a really long build command. But, it's the same every time you run it, and it works on every OS. Easy.

```toml
version = "0.3.0"

[scripts]
build = "long command here"
```

How about a multistage command for deploying to a platform like Netlify? Easy.

```toml
version = "0.3.0"

[scripts]
deploy = [
	"stage 1",
	"stage 2"
]
```

Well what about an execution command that needs to do different things on different OSes? Still easy.

```toml
version = "0.3.0"

[scripts]
run.generic = "generic fallback here"
run.targets.windows = "windows command here"
run.targets.macos = "macos command here"
run.targets.linux = "linux command here"
# iOS, Android, OpenBSD, FreeBSD, NetBSD, Dragonfly...
```

Need to depend on some environment variables and user-given arguments? *Still* easy.

```toml
version = "0.3.0"

[scripts]
run.cmd = "execution command here with %ENV_VAR and %arg1"
run.args = [ "arg1" ]
run.env_vars = [ "ENV_VAR" ]
```

How about adding all the arguments a user gives into one place? Even easier, just use `%%`.

```toml
version = "0.3.0"

[scripts]
run = "execution command here with %%"
```

What if you've got multiple subprojects to build and you want to do it in a certain order with fallbacks? Bit long, but still easy.

```toml
version = "0.3.0"

[scripts]
build.subcommands.frontend = "build command here"
build.subcommands.backend = "build command here"
build.subcommands.update = "recovery command here"
build.order = """
frontend {
	Success => backend {
		Failure => update {
			Success => backend
		}
	},
	Failure => update {
		Success => frontend {
			Success => backend {
				Failure => update {
					Success => backend
				}
			}
		}
	}
}
"""
```

Yeah, you can do that. Take a look at [the docs](https://github.com/arctic-hen7/bonnie/wiki) for more, like taking user arguments, inserting environment variables, and using custom execution shells! All the examples above can be combined in just about any way you can think of!

## Closing words

Bonnie is a command aliasing tool with straight-up superpowers, and I honestly think it can replace just about every use-case of Make for command aliasing. I strongly encourage you to try it out! Any suggestions are more than welcome, and please open an issue if you find any bugs or want to suggest some more features!