Command-line rust notes (1)
Accessing command line arguments
std::env::args() -> Args
returns an iterators on the command line arguments passed into the binary:
impl Iterator for Args {
type Item = String;
fn next(&mut self) -> Option<String>
}
Channeling standard out and standard error
When running a command line program, standard output goes to channel 1 while standard error goes to channel 2:
# stdout will be written to ./out and stderr will be written to ./err
some-command ... 1>out 2>err
Parsing command line arguments
clap
is a crate that can be used declare and parse command line arguments:
cargo add clap@4.0.32 --features derive
- To declare a CLI schema, bring in the
clap::Parser
trait, then define a struct with the#[derive(Parser)]
attribute - Add attributes like
#[command(...)]
to the argument struct to define metadata for the program. Common options includeauthors
,about
,long_about
,version
. They will show up when running with the-h/--help
and/or-v/--version
flags. They default to what is written inCargo.toml
- For keyword arguments, some common options:
#[arg(short='n', long="number")]
(use characters for the “short” flag)#[arg(default_value_t=...)]
- Positional argument behaviors:
file: String
: a single argument that is requiredfile: Option<String>
: a single, optional argumentfiles Vec<String>
: zero or more positional arguments
Dependencies for testing only
Adding the --dev
flag in cargo add
means that the crate will be compiled for testing only. One useful crate is assert_cmd
, which can be used to run both system binaries and cargo binaries:
let assert = Command::cargo_bin("mybin")? // => Result<Command, ...>
.args(&["-f", "-l"])
.write_std("Hello, world")
.assert() // => assert_cmd::Assert
.success()
.try_stdout("some output")?
.try_stderr("some errors")?