mirror of https://github.com/rust-lang/book
Propagate ch12 tech review edits to src
This commit is contained in:
parent
2382aafe15
commit
e44d600dd1
|
@ -83,6 +83,7 @@ combinator
|
|||
ConcreteType
|
||||
config
|
||||
Config
|
||||
confignew
|
||||
const
|
||||
consts
|
||||
constant's
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$ cargo run test sample.txt
|
||||
$ cargo run -- test sample.txt
|
||||
Compiling minigrep v0.1.0 (file:///projects/minigrep)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.0s
|
||||
Running `target/debug/minigrep test sample.txt`
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$ cargo run the poem.txt
|
||||
$ cargo run -- the poem.txt
|
||||
Compiling minigrep v0.1.0 (file:///projects/minigrep)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.0s
|
||||
Running `target/debug/minigrep the poem.txt`
|
||||
|
|
|
@ -22,7 +22,7 @@ struct Config {
|
|||
|
||||
// ANCHOR: here
|
||||
impl Config {
|
||||
fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::process;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
@ -29,7 +29,7 @@ struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ fn main() {
|
|||
// ANCHOR_END: here
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
@ -37,7 +37,7 @@ struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::error::Error;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
@ -38,7 +38,7 @@ struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
// --snip--
|
||||
// ANCHOR_END: here
|
||||
if args.len() < 3 {
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::process;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ fn main() {
|
|||
// ANCHOR_END: here
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ pub struct Config {
|
|||
// ANCHOR_END: here
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$ cargo run to poem.txt
|
||||
$ cargo run -- to poem.txt
|
||||
Compiling minigrep v0.1.0 (file:///projects/minigrep)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.0s
|
||||
Running `target/debug/minigrep to poem.txt`
|
||||
|
|
|
@ -14,7 +14,7 @@ pub struct Config {
|
|||
|
||||
// ANCHOR: here
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
eprintln!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ fn main() {
|
|||
// ANCHOR_END: here
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
@ -41,7 +41,7 @@ struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$ cargo run frog poem.txt
|
||||
$ cargo run -- frog poem.txt
|
||||
Compiling minigrep v0.1.0 (file:///projects/minigrep)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.38s
|
||||
Running `target/debug/minigrep frog poem.txt`
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$ cargo run needle haystack
|
||||
$ cargo run -- needle haystack
|
||||
Compiling minigrep v0.1.0 (file:///projects/minigrep)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 1.57s
|
||||
Running `target/debug/minigrep needle haystack`
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$ cargo run body poem.txt
|
||||
$ cargo run -- body poem.txt
|
||||
Compiling minigrep v0.1.0 (file:///projects/minigrep)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.0s
|
||||
Running `target/debug/minigrep body poem.txt`
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$ cargo run monomorphization poem.txt
|
||||
$ cargo run -- monomorphization poem.txt
|
||||
Compiling minigrep v0.1.0 (file:///projects/minigrep)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.0s
|
||||
Running `target/debug/minigrep monomorphization poem.txt`
|
||||
|
|
|
@ -7,7 +7,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ pub struct Config {
|
|||
|
||||
// ANCHOR: ch13
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
println!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use minigrep::Config;
|
|||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
let config = Config::new(&args).unwrap_or_else(|err| {
|
||||
let config = Config::build(&args).unwrap_or_else(|err| {
|
||||
eprintln!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(args: &[String]) -> Result<Config, &'static str> {
|
||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
||||
if args.len() < 3 {
|
||||
return Err("not enough arguments");
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use minigrep::Config;
|
|||
|
||||
// ANCHOR: here
|
||||
fn main() {
|
||||
let config = Config::new(env::args()).unwrap_or_else(|err| {
|
||||
let config = Config::build(env::args()).unwrap_or_else(|err| {
|
||||
eprintln!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ pub struct Config {
|
|||
|
||||
// ANCHOR: here
|
||||
impl Config {
|
||||
pub fn new(
|
||||
pub fn build(
|
||||
mut args: impl Iterator<Item = String>,
|
||||
) -> Result<Config, &'static str> {
|
||||
// --snip--
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::process;
|
|||
use minigrep::Config;
|
||||
|
||||
fn main() {
|
||||
let config = Config::new(env::args()).unwrap_or_else(|err| {
|
||||
let config = Config::build(env::args()).unwrap_or_else(|err| {
|
||||
eprintln!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ pub struct Config {
|
|||
|
||||
// ANCHOR: here
|
||||
impl Config {
|
||||
pub fn new(
|
||||
pub fn build(
|
||||
mut args: impl Iterator<Item = String>,
|
||||
) -> Result<Config, &'static str> {
|
||||
args.next();
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::process;
|
|||
use minigrep::Config;
|
||||
|
||||
fn main() {
|
||||
let config = Config::new(env::args()).unwrap_or_else(|err| {
|
||||
let config = Config::build(env::args()).unwrap_or_else(|err| {
|
||||
eprintln!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(
|
||||
pub fn build(
|
||||
mut args: impl Iterator<Item = String>,
|
||||
) -> Result<Config, &'static str> {
|
||||
args.next();
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::process;
|
|||
use minigrep::Config;
|
||||
|
||||
fn main() {
|
||||
let config = Config::new(env::args()).unwrap_or_else(|err| {
|
||||
let config = Config::build(env::args()).unwrap_or_else(|err| {
|
||||
eprintln!("Problem parsing arguments: {}", err);
|
||||
process::exit(1);
|
||||
});
|
||||
|
|
|
@ -12,11 +12,12 @@ $ cd minigrep
|
|||
|
||||
The first task is to make `minigrep` accept its two command line arguments: the
|
||||
filename and a string to search for. That is, we want to be able to run our
|
||||
program with `cargo run`, a string to search for, and a path to a file to
|
||||
search in, like so:
|
||||
program with `cargo run`, two hyphens to indicate the following arguments are
|
||||
for our program rather than for `cargo`, a string to search for, and a path to
|
||||
a file to search in, like so:
|
||||
|
||||
```console
|
||||
$ cargo run searchstring example-filename.txt
|
||||
$ cargo run -- searchstring example-filename.txt
|
||||
```
|
||||
|
||||
Right now, the program generated by `cargo new` cannot process arguments we
|
||||
|
@ -51,11 +52,11 @@ First, we bring the `std::env` module into scope with a `use` statement so we
|
|||
can use its `args` function. Notice that the `std::env::args` function is
|
||||
nested in two levels of modules. As we discussed in [Chapter
|
||||
7][ch7-idiomatic-use]<!-- ignore -->, in cases where the desired function is
|
||||
nested in more than one module, it’s conventional to bring the parent module
|
||||
into scope rather than the function. By doing so, we can easily use other
|
||||
functions from `std::env`. It’s also less ambiguous than adding `use
|
||||
std::env::args` and then calling the function with just `args`, because `args`
|
||||
might easily be mistaken for a function that’s defined in the current module.
|
||||
nested in more than one module, we’ve chosen to bring the parent module into
|
||||
scope rather than the function. By doing so, we can easily use other functions
|
||||
from `std::env`. It’s also less ambiguous than adding `use std::env::args` and
|
||||
then calling the function with just `args`, because `args` might easily be
|
||||
mistaken for a function that’s defined in the current module.
|
||||
|
||||
> ### The `args` Function and Invalid Unicode
|
||||
>
|
||||
|
|
|
@ -32,7 +32,7 @@ First, we bring in a relevant part of the standard library with a `use`
|
|||
statement: we need `std::fs` to handle files.
|
||||
|
||||
In `main`, the new statement `fs::read_to_string` takes the `filename`, opens
|
||||
that file, and returns a `Result<String>` of the file’s contents.
|
||||
that file, and returns a `std::io::Result<String>` of the file’s contents.
|
||||
|
||||
After that, we again add a temporary `println!` statement that prints the value
|
||||
of `contents` after the file is read, so we can check that the program is
|
||||
|
|
|
@ -246,19 +246,24 @@ the technique we used in Listing 9-13 isn’t the best to use here: a call to
|
|||
we’ll use the other technique you learned about in Chapter 9—[returning a
|
||||
`Result`][ch9-result]<!-- ignore --> that indicates either success or an error.
|
||||
|
||||
#### Returning a `Result` from `new` Instead of Calling `panic!`
|
||||
<!-- Old headings. Do not remove or links may break. -->
|
||||
<a id="returning-a-result-from-new-instead-of-calling-panic"></a>
|
||||
|
||||
#### Returning a `Result` Instead of Calling `panic!`
|
||||
|
||||
We can instead return a `Result` value that will contain a `Config` instance in
|
||||
the successful case and will describe the problem in the error case. When
|
||||
`Config::new` is communicating to `main`, we can use the `Result` type to
|
||||
signal there was a problem. Then we can change `main` to convert an `Err`
|
||||
variant into a more practical error for our users without the surrounding text
|
||||
about `thread 'main'` and `RUST_BACKTRACE` that a call to `panic!` causes.
|
||||
the successful case and will describe the problem in the error case. We’re also
|
||||
going to change the function name from `new` to `build` because many
|
||||
programmers expect `new` functions to never fail. When `Config::build` is
|
||||
communicating to `main`, we can use the `Result` type to signal there was a
|
||||
problem. Then we can change `main` to convert an `Err` variant into a more
|
||||
practical error for our users without the surrounding text about `thread
|
||||
'main'` and `RUST_BACKTRACE` that a call to `panic!` causes.
|
||||
|
||||
Listing 12-9 shows the changes we need to make to the return value of
|
||||
`Config::new` and the body of the function needed to return a `Result`. Note
|
||||
that this won’t compile until we update `main` as well, which we’ll do in the
|
||||
next listing.
|
||||
Listing 12-9 shows the changes we need to make to the return value of the
|
||||
function we’re now calling `Config::build` and the body of the function needed
|
||||
to return a `Result`. Note that this won’t compile until we update `main` as
|
||||
well, which we’ll do in the next listing.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
|
@ -267,25 +272,28 @@ next listing.
|
|||
```
|
||||
|
||||
<span class="caption">Listing 12-9: Returning a `Result` from
|
||||
`Config::new`</span>
|
||||
`Config::build`</span>
|
||||
|
||||
Our `new` function now returns a `Result` with a `Config` instance in the
|
||||
Our `build` function now returns a `Result` with a `Config` instance in the
|
||||
success case and a `&'static str` in the error case. Our error values will
|
||||
always be string literals that have the `'static` lifetime.
|
||||
|
||||
We’ve made two changes in the body of the `new` function: instead of calling
|
||||
`panic!` when the user doesn’t pass enough arguments, we now return an `Err`
|
||||
value, and we’ve wrapped the `Config` return value in an `Ok`. These changes
|
||||
make the function conform to its new type signature.
|
||||
We’ve made two changes in the body of the function: instead of calling `panic!`
|
||||
when the user doesn’t pass enough arguments, we now return an `Err` value, and
|
||||
we’ve wrapped the `Config` return value in an `Ok`. These changes make the
|
||||
function conform to its new type signature.
|
||||
|
||||
Returning an `Err` value from `Config::new` allows the `main` function to
|
||||
handle the `Result` value returned from the `new` function and exit the process
|
||||
more cleanly in the error case.
|
||||
Returning an `Err` value from `Config::build` allows the `main` function to
|
||||
handle the `Result` value returned from the `build` function and exit the
|
||||
process more cleanly in the error case.
|
||||
|
||||
#### Calling `Config::new` and Handling Errors
|
||||
<!-- Old headings. Do not remove or links may break. -->
|
||||
<a id="calling-confignew-and-handling-errors"></a>
|
||||
|
||||
#### Calling `Config::build` and Handling Errors
|
||||
|
||||
To handle the error case and print a user-friendly message, we need to update
|
||||
`main` to handle the `Result` being returned by `Config::new`, as shown in
|
||||
`main` to handle the `Result` being returned by `Config::build`, as shown in
|
||||
Listing 12-10. We’ll also take the responsibility of exiting the command line
|
||||
tool with a nonzero error code away from `panic!` and instead implement it by
|
||||
hand. A nonzero exit status is a convention to signal to the process that
|
||||
|
@ -297,8 +305,8 @@ called our program that the program exited with an error state.
|
|||
{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-10/src/main.rs:here}}
|
||||
```
|
||||
|
||||
<span class="caption">Listing 12-10: Exiting with an error code if creating a
|
||||
new `Config` fails</span>
|
||||
<span class="caption">Listing 12-10: Exiting with an error code if building a
|
||||
`Config` fails</span>
|
||||
|
||||
In this listing, we’ve used a method we haven’t covered in detail yet:
|
||||
`unwrap_or_else`, which is defined on `Result<T, E>` by the standard library.
|
||||
|
@ -358,7 +366,7 @@ argument.
|
|||
#### Returning Errors from the `run` Function
|
||||
|
||||
With the remaining program logic separated into the `run` function, we can
|
||||
improve the error handling, as we did with `Config::new` in Listing 12-9.
|
||||
improve the error handling, as we did with `Config::build` in Listing 12-9.
|
||||
Instead of allowing the program to panic by calling `expect`, the `run`
|
||||
function will return a `Result<T, E>` when something goes wrong. This will let
|
||||
us further consolidate the logic around handling errors into `main` in a
|
||||
|
@ -414,7 +422,7 @@ have some error-handling code here! Let’s rectify that problem now.
|
|||
#### Handling Errors Returned from `run` in `main`
|
||||
|
||||
We’ll check for errors and handle them using a technique similar to one we used
|
||||
with `Config::new` in Listing 12-10, but with a slight difference:
|
||||
with `Config::build` in Listing 12-10, but with a slight difference:
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
|
@ -424,7 +432,7 @@ with `Config::new` in Listing 12-10, but with a slight difference:
|
|||
|
||||
We use `if let` rather than `unwrap_or_else` to check whether `run` returns an
|
||||
`Err` value and call `process::exit(1)` if it does. The `run` function doesn’t
|
||||
return a value that we want to `unwrap` in the same way that `Config::new`
|
||||
return a value that we want to `unwrap` in the same way that `Config::build`
|
||||
returns the `Config` instance. Because `run` returns `()` in the success case,
|
||||
we only care about detecting an error, so we don’t need `unwrap_or_else` to
|
||||
return the unwrapped value, which would only be `()`.
|
||||
|
@ -444,7 +452,7 @@ Let’s move all the code that isn’t the `main` function from *src/main.rs* to
|
|||
* The `run` function definition
|
||||
* The relevant `use` statements
|
||||
* The definition of `Config`
|
||||
* The `Config::new` function definition
|
||||
* The `Config::build` function definition
|
||||
|
||||
The contents of *src/lib.rs* should have the signatures shown in Listing 12-13
|
||||
(we’ve omitted the bodies of the functions for brevity). Note that this won’t
|
||||
|
|
|
@ -157,14 +157,14 @@ Looks like that still works! Now, let’s run the program with `IGNORE_CASE`
|
|||
set to `1` but with the same query `to`.
|
||||
|
||||
```console
|
||||
$ IGNORE_CASE=1 cargo run to poem.txt
|
||||
$ IGNORE_CASE=1 cargo run -- to poem.txt
|
||||
```
|
||||
|
||||
If you’re using PowerShell, you will need to set the environment variable and
|
||||
run the program as separate commands:
|
||||
|
||||
```console
|
||||
PS> $Env:IGNORE_CASE=1; cargo run to poem.txt
|
||||
PS> $Env:IGNORE_CASE=1; cargo run -- to poem.txt
|
||||
```
|
||||
|
||||
This will make `IGNORE_CASE` persist for the remainder of your shell
|
||||
|
@ -178,7 +178,7 @@ We should get lines that contain “to” that might have uppercase letters:
|
|||
|
||||
<!-- manual-regeneration
|
||||
cd listings/ch12-an-io-project/listing-12-23
|
||||
IGNORE_CASE=1 cargo run to poem.txt
|
||||
IGNORE_CASE=1 cargo run -- to poem.txt
|
||||
can't extract because of the environment variable
|
||||
-->
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ Let’s run the program again with arguments that don’t cause an error but sti
|
|||
redirect standard output to a file, like so:
|
||||
|
||||
```console
|
||||
$ cargo run to poem.txt > output.txt
|
||||
$ cargo run -- to poem.txt > output.txt
|
||||
```
|
||||
|
||||
We won’t see any output to the terminal, and *output.txt* will contain our
|
||||
|
|
Loading…
Reference in New Issue