Hey there, Rusty folks! π As you may know, I've been diving headfirst into the magical land of Rust, and I've decided to share my journey with you as I build a command line tool! Let's get ready to rumble, shall we? π
Step 0: Say "Hello" to the World
Alright, let's start with the basics - the "Hello World!" program. You know, like anyone starting with a new programming language! Here's a simple one-liner:
cargo new termoil
cd termoil
Now inside the termoil
directory, you'll find a src
folder with a main.rs
file. Open it up and add this code snippet:
fn main(){
println!("Hello world!");
}
This is like magic, isn't it? π« We're using println!
for the first time. It's like shouting "Hello World!" from the top of a mountain, just without the echo. It's a macro to print stuff to the console. If you're wondering why there's an exclamation mark, that's Rust's way of saying "Hey, I'm a macro, not a function!" π£
Now, we've got our very basic Rust program. But we need to make it more useful, right?
Step 1: Taking user input using std library
Our first mission is figuring out how to take user input. Imagine it like being at a party and trying to get someone's attention. After doing some research, I found that the std
library can help me do just that! Let's add this code snippet to our main.rs
file:
fn main() {
let arguments = std::env::args().collect::<Vec<String>>();
println!("{:?}", arguments);
}
Here's a quick breakdown of the code:
std::env::args()
gives us an iterator over the command line arguments (like a conga line of words waiting to be heard).We then use
collect::<Vec<String>>()
to collect the arguments into aVec<String>
(imagine it as herding those conga-dancing words into a cozy little word pen).Finally, we print out the collected arguments using
println!("{:?}", arguments);
.
Run the code and see what happens!
$ cargo run -- hello world
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/rusty hello world`
["target/debug/rusty", "hello", "world"]
Step 2: Realizing the limitations of std library for CLI apps
Alright, so using the std
library for taking user input is decent enough. But it's not quite the best choice for CLI apps. If we stick with it, we'll have to do a lot of manual work (akin to making a delicious smoothie with just a spoon - possible but far from ideal). So let's bring out the big guns and switch to a more powerful option: the clap
crate!
Add this dependency to your Cargo.toml
file:
What is cargo.toml?
Cargo.toml
is like the map and compass of your Rust project. It's a configuration file written in TOML (Tom's Obvious, Minimal Language) format that helps you manage your project's dependencies, metadata, and build settings. It's where you declare essential information about your project and any additional crates (libraries) you want to use.
[dependencies]
clap = { version = "4.2.1", features = ["derive"] }
This tells Cargo (Rust's package manager) that our project relies on the clap
crate with version 4.2.1 and the "derive" feature enabled. When we build or run our project, Cargo will automatically download and compile the clap
crate and make it available for us to use in our code.
Think of
Cargo.toml
as a treasure map that guides you through the Rust ecosystem, helping you find all the powerful tools and libraries you need for your coding adventure! πΊοΈπ
Step 3: Switching to clap for better user input handling
Now that we have clap
ready to roll, let's update our main.rs
file:
use clap::Parser;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
// query the user wants to enter
#[arg(short, long)]
query: String,
}
fn main() {
let arguments = Args::parse();
println!("Query: {:?}", arguments.query);
}
Let's dissect the changes like a biologist examining a fascinating new species:
We've imported the
Parser
trait fromclap
withuse clap::Parser;
.Now, structs in Rust are like customized containers that can store different types of data (picture a lunchbox designed to hold your favorite snacks). So we created a new struct called
Args
and derived theParser
andDebug
traits for it.Inside the struct, we defined a field named
query
with typeString
. This will hold the user's input (like storing their attention-grabbing party phrase in our tailor-made lunchbox).We used the attribute
#[arg(short, long)]
to tellclap
that this field is an argument. Here's what it means:The
short
attribute tellsclap
to accept a single hyphen followed by a single character as a short version of the argument (e.g.,-q
).The
long
attribute accepts a double hyphen followed by the full argument name (e.g.,--query
). Both of these attributes make it easier for users to provide input without typing the whole thing out.
In the
main
function, we replaced our previous user input handling code withlet arguments = Args::parse();
. Think of it as upgrading from a spoon to an actual blender for our smoothie-making process - way more efficient!Lastly, we print out the parsed query with
println!("Query: {:?}", arguments.query);
.
Additional information:
Traits: A trait is like a template of behavior that can be shared among different types. It's a way to define certain methods or functionalities that a type must implement. Think of it as a blueprint for a robot with defined abilities (like walking or talking) that can be inherited by actual robots.
Parser trait: When we derive the
Parser
trait for ourArgs
struct, we're telling Rust that we want theArgs
struct to have all the parsing powers that come with theParser
trait. This allows us to parse command-line arguments according to our desired structure and makes handling user input much more convenient.
Run the code again and bask in the glory of using clap
for your CLI app!
$ cargo run -- --query hello
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/rusty --query hello`
Query: "hello"
And there you have it, my fellow explorers! We journeyed through the forest of user input handling, going from the standard library to upgrading our tools with the mighty clap
crate. Remember, the right tools make all the difference when venturing into the wild world of programming! π Happy coding!π
Cover: Bhupesh