"CLAP" stands for Command-Line Argument Parser.
In order to get started using clap, you need to understand three things:
1 - How to Run a Simple Rust Program
Suppose you want to create a program called "fun". You should have a working installation of Rust and Cargo (the web is full of explanations of how to install this). In your file directory where you want to create the "fun" project:
$ cargo new fun
$ cargo run
This should print "Hello, World!", because every cargo-created project has this simple capability as a starting point.
2 - How to Work with a struct
This is a little bit more advanced. Here's the "src/main.rs" program from our "cargo new fun" command above:
A structure is simply a variable of a customized type, which often holds other variables. You should be familiar in a general way with variables, and know that they come in various kinds, or types: there are String variables and there are i32 variables and there are usize variables, etc. A struct simply allows you to create your own customized variable type, and fill it with a collection of other variables of various types.
Say you have a variable called "last" which holds a person's last name, and a variable called "age" which holds that person's age in years. The first variable might be a type of String (which holds a string of text), and the second might be a type of i8 (which holds an integer in the range of -128 to +127; a u8, which holds a range of 0 to 255, might be a better option).
Think of these two variables as two different types of fruit. We can carry them around in our hands if we like, or we can create a shopping bag to put them into. This shopping bag is analogous to a struct, except that a struct is well-defined as to what it can hold, whereas a shopping bag will hold just about anything pretty much, willy-nilly.
So a better way to think of it is as a custom-tool case, with exact-fitting compartments for the tools.
Example:
// This is the "master design" from which all toolboxes will be built. struct toolbox_template { owner: String, // It will belong to a specific person, hammer: String, // and will hold a hammer, screwdriver: i8, // and a screwdriver of a certain size. }
Note that this is just the definition of the "template" for a toolbox; it doesn't actually create a toolbox. Let's put this template into our "main.rs" file, along with the creation of two toolboxes based on this template, and then we'll print out a couple of messages about those tools. (We no longer need the "Hello, World!" println, so we'll delete it as per the Strikethru marking.)
So you can see that a struct is just a custom-built variable, a "carrying case", that holds various other variables. The "struct" part defines the type, and then you have to create variables of that type which actually hold the desired data.
A Basic clap Setup
So, you can write a simple Rust program, and you kindda understand a struct. Good. Now lets add clap into the mix.
We first have to tell Cargo (the Rust "compiler" (sort of, but not really)) about Clap. This is done by adding some information to the "Cargo.toml" file. Before doing this, my Cargo.toml file for the "fun" program looks like this:
$ cat Cargo.toml [package] name = "fun" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] $
If you have a recent version of Clap/Cargo, you can add Clap to your "fun" project with this command:
$ cargo add clap --features derive
That'll generate some churn, after which your "Cargo.toml" file will look more like this (the new stuff is in hilite):
$ cat Cargo.toml [package] name = "fun" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies]clap = { version = "4.2.7", features = ["derive"] }
Now Cargo knows about clap. Your program does not, but Cargo does. When you compile your program again, Cargo will include all the clap stuff. Try it. Your program will run just as it did before, except for all the extra compiling of Clap.
We want to be able to specify our hammer and screwdriver on the command-line. The command will look something like this:
$ code run -- --name=Bob --hammer=peen --screwdriver=9
Add the Strikethru. The "use" line simply tells our program the path to find parse-related stuff in the Clap crate. The "derive" line magically makes our struct definition able to associate its components with information coming from the Command-Line Argument Parser (clap).
If you try to run this with arguments, like so:
$ cargo run -- --name=Bob hammer=peen screwdriver=9
you'll get a message about an unexpected argument, and a tip that tells you to do what you're already doing, along with a "usage" blurb.
However, if you run your program this way:
$ cargo run -- --Bob peen 9
it works!
And that's all that's needed for a very basic clap setup. It's reading your command-line arguments according to the position they're given. If you change the order, like this:
$ cargo run -- --9 Bob peen
you'll break your program. Like this, though:
$ cargo run -- --peen Bob 9
and you'll just get unwanted results.
So we want to be able to name our arguments. That's done like this:
Try running that with $ cargo run -- --name=Bob hammer=peen screwdriver=9
.
Hmm, a different error message. And again, it doesn't really make sense. Ah, but now I see it. We defined an argument named "owner", but we're typing in an argument named "name". Let's try this:
$ cargo run -- --owner name=Bob hammer=peen screwdriver=9
.
Yay! That works!
But what if we really want to type in "name" instead of "owner", but don't want to change the variable name? Easy. Just do this:
What if we want to just use "s" for "screwdriver"?
Then our command-line would like look: cargo run -- --name=Bob --hammer=peen -s=9
Notice that single-letter arguments are introduced with a single-hyphen (e.g. -s=9
), rather than a double-hyphen (--s=9
).
What if we want to just use "d" for "screwDriver"?
Notice that the definition uses single-quotes around "d" rather than double-quotes.
What if we want to allow either a short form or a long form?
What if we want to make the name optional, with a default?
Note that "Bubba".to_string() won't work in this case, so we had to use an alternative method of converting a string literal to a String-type. Don't worry for now about understanding that; just know that usually it doesn't matter which conversion method you use, and that if one method doesn't work, try another.
This short tutorial won't answer all your questions, but it should get you started. Have fun, Rustacean!