CLI
Reading and writing to the command line is something pretty common for programs. It forms the glue that binds Unix together.
Echo
println!
print!
fmt!
Stdin
read each line into a string
use std::io;
fn main() {
let mut input = String::new();
match io::stdin().read_line(&mut input) {
Ok(n) => {
println!("{} bytes read", n);
println!("{}", input);
}
Err(err) => println!("error: {}", err),
}
}
read single line from stdin to string
fn main () {
let mut line = String::new();
let stdin = io::stdin();
stdin.lock().read_line(&mut line).unwrap();
}
Stdout
print single line to stdout no newline
fn main () {
print!("minutes: ");
io::stdout().flush().unwrap();
}
Options parsing
extern crate getopts;
use getopts::Options;
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
let program = args[0].clone();
let mut options = Options::new();
options.optflag("h", "help", "Output usage information");
let matches = match options.parse(&args[1..]) {
Ok(m) => { m }
Err(f) => { panic!(f.to_string()) }
};
// help command
if matches.opt_present("h") {
print_usage(&program, options);
return;
}
}
// print CLI usage
fn print_usage(program: &str, opts: Options) {
let brief = format!("Usage: {} <file> [options]", program);
print!("{}", opts.usage(&brief));
}
// and then to parse the first argument do:
if !matches.free.is_empty() {
let input = matches.free.clone();
let command = &input[0];
match command.trim() {
"my_cool_command" => {},
_ => {
println!("Error: unknown command '{}'\n", command.trim());
print_usage(&program, options);
}
}
} else {
println!("Error: expected <command>\n");
print_usage(&program, options);
}
Subshell
Spawn a new command; returns the status code:
use std::process::Command;
fn main() {
let output = Command::new("ls")
.arg("-la")
.output()
.expect("failed to execute process");
println!("status: {}", output.status);
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
}