alex_minigrep/
lib.rs

1//! # minigrep Crate
2//!
3//! `minigrep` is just a simple getting started test project.
4//! 
5
6use std::error::Error;
7use std::fs::File;
8use std::io::prelude::*;
9use std::env;
10
11pub fn run(config: Config) -> Result<(), Box<Error>> {
12    let mut file = File::open(config.filename)?;
13    let mut contents = String::new();
14    file.read_to_string(&mut contents)?;
15
16
17    let results = if config.case_sensitive {
18        search(&config.query, &contents)
19    } else {
20        search_case_insensitive(&config.query, &contents)
21    };
22
23    for line in results {
24        println!("{}", line);
25    }
26
27    Ok(())
28}
29
30pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
31    contents.lines()
32        .filter(|line| line.contains(&query))
33        .collect()
34}
35
36
37/// searches a string and ignores the case 
38/// 
39/// # Examples
40/// 
41/// ```
42///   let query = "foo";
43///   let content = "\
44///Hallo Welt,
45///Foo Bar,
46///";
47/// 
48/// assert_eq!(vec!["Foo Bar"], minigrep::search_case_insensitive(&query, &content));
49/// ```
50pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
51    let query = query.to_lowercase();
52
53    contents.lines()
54        .filter(|line| line.to_lowercase().contains(&query))
55        .collect()
56}
57
58pub struct Config {
59    query: String,
60    filename: String,
61    case_sensitive: bool,
62}
63
64impl Config {
65    pub fn new(mut args: std::env::Args) -> Result<Config, &'static str> {
66        if args.len() < 3 {
67            return Err("not enough arguments");
68        }
69
70        args.next(); // ignore program name
71
72        let query = match args.next() {
73            Some(arg) => arg,
74            None => return Err("Didn't get a query string"),
75        };
76
77        let filename = match args.next() {
78            Some(arg) => arg,
79            None => return Err("Didn't get a file name"),
80        };
81        
82        let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
83
84        Ok(Config { query, filename, case_sensitive })
85    }
86}
87
88
89#[cfg(test)]
90mod test {
91    use super::*;
92
93    #[test]
94    fn case_sensitive() {
95        let query = "duct";
96        let contents = "\
97Rust:
98safe, fast, productive.
99Pick three.";
100
101        assert_eq!(
102            vec!["safe, fast, productive."],
103            search(query, contents)
104        );
105    }
106
107    #[test]
108    fn case_insensitive() {
109        let query = "rUsT";
110        let contents = "\
111Rust:
112safe, fast, productive.
113Pick three.
114Trust me.";
115
116        assert_eq!(
117            vec!["Rust:", "Trust me."],
118            search_case_insensitive(query, contents)
119        );
120    }
121}