Accessing the command line
Sooner or later, you'll want to interact with the user in some way or another. The most basic way to do this is by letting the user pass parameters while calling the application through the command line.
How to do it...
In the
bin
folder, create a file calledcli_params.rs
Add the following code and run it with
cargo run --bin cli_params some_option some_other_option
:
1 use std::env; 2 3 fn main() { 4 // env::args returns an iterator over the parameters 5 println!("Got following parameters: "); 6 for arg in env::args() { 7 println!("- {}", arg); 8 } 9 10 // We can access specific parameters using the iterator API 11 let mut args = env::args(); 12 if let Some(arg) = args.nth(0) { 13 println!("The path to this program is: {}", arg); 14 } 15 if let Some(arg) = args.nth(1) { 16 println!("The first parameter is: {}", arg); 17 } 18 if let Some(arg) = args.nth(2) { 19 println!("The second parameter is: {}", arg); 20 } 21 22 // Or as a vector 23 let args: Vec<_> = env::args().collect(); 24 println!("The path to this program is: {}", args[0]); 25 if args.len() > 1 { 26 println!("The first parameter is: {}", args[1]); 27 } 28 if args.len() > 2 { 29 println!("The second parameter is: {}", args[2]); 30 } 31 }
How it works...
Calling env::args()
returns an iterator over the provided parameters[6]. By convention, the first command-line parameter on most operating systems is the path to the executable itself [12].
We can access specific parameters in two ways: keep them as an iterator [11] or collect
them into a collection such as Vec
[23]. Don't worry, we are going to talk about them in detail in Chapter 2, Working with Collections. For now, it's enough for you to know that:
Accessing an iterator forces you to check at compile time whether the element exists, for example, an
if let
binding [12]Accessing a vector checks the validity at runtime
This means that we could have executed lines [26] and [29] without checking for their validity first in [25] and [28]. Try it yourself, add the &args[3];
line at the end of the program and run it.
Note
We check the length anyways because it is considered good style to check whether the expected parameters were provided. With the iterator way of accessing parameters, you don't have to worry about forgetting to check, as it forces you to do it. On the other hand, by using a vector, you can check for the parameters once at the beginning of the program and not worry about them afterward.
There's more...
If you are building a serious command-line utility in the style of *nix tools, you will have to parse a lot of different parameters. Instead of reinventing the wheel, you should take a look at third-party libraries, such as clap (https://crates.io/crates/clap).