Creating a simple CLI in Rust
September 12, 2021
Summary
Setup
First of all, you must have rustup
installed, in order to do so, run the
following command:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
This is the official way to install
rustup
as recommended onrustup.rs
It will fetch the shell installation script, and execute it right away, without saving anything on your machine, when executed, the script will instruct you through the whole process with well explained and detailed installation instructions, carefully follow them until the whole process is done
Initializing a new project
After that, move to a directory of your preference (optional) and initialize a new empty project by running:
cargo new <project_name>
A directory with the specified project name will be created on the current directory, besides that, a little few others things will be added under the hood, it’s structure should look like the following:
.
├── Cargo.toml
└── src
└── main.rs
Creating the CLI
Differently from Node, we don’t have a CLI for installing packages
automatically for us, instead, is necessary to manually write the desired
package name and version directly on Cargo.toml
Tip: you can leverage this by using a plugin for your editor of choice, for instance, in my case, i’m using neovim, so something like
vim-crates
can be really useful when it comes to updating dependencies
For creating ou CLI, we need the structopt
dependency, it’s responsible for
generating a command line parser, based on a given struct
, to install it,
simply include the following line on your Cargo.toml
, more specifically,
under the [dependencies]
table:
structopt = "0.3.23"
You don’t necessarily need to use this version, it’s the latest at the time of writing, but feel free to use the latest one available to you (unless there are breaking dependencies, then probably won’t work)
Now, the most important part, we need to establish the logic of our program,
for this example, it will have a required name
argument, and a optional
--is-programmer
flag, our CLI will greet the user by output
“Hey <user>!”, and if the --is-programmer
flag is passed, it will append
“Have you heard about Rust?” to the greeting message:
// imports a external dependency, don't confuse it with `mod`
// which is used for importing local modules
use structopt::StructOpt;
// pass the struct below as an argument to `StructOpt` for generating the
// command line parser
#[derive(StructOpt)]
struct Cli {
// required argument, represents the person name
name: String,
// optional flag, will define whether or not the second part of the
// greeting will be displayed short flag will be set to "-p", long flag
// will be determined accordingly to the property name "--is-programmer"
#[structopt(short = "p", long)]
is_programmer: bool
}
fn main() {
// gets a object containing all the CLI flags and their respective values
let args = Cli::from_args();
// the message to be displayed to the user
let mut message_vector = vec!["Hey ", &args.name, "! "];
// complements the greeting if the user is a programmer
if args.is_programmer {
message_vector.push("Have you heard about Rust?")
}
// concatenate the message vector into a string
let message = message_vector.join("");
// displays the greeting message
println!("{}", message.join)
}
Now, let’s test it with cargo run
and pass some flags to see if everything is
working properly:
cargo run Edgar
And we should expect the following output:
Hey Edgar!
And with the --is-programmer
flag:
cargo run -- --is-programmer Daisy
The output below should be displayed:
Hey Daisy! Have you heard about Rust?
That’s all for this post, consider reading structopt
docs for more information on this amazing library!