minigrep_jondeaves/
lib.rs

1//! # Minigrep
2//!
3//! `minigrep_jondeaves` is a lightweight implementation of the well known grep command.
4use std::{env, error::Error, fs};
5
6pub struct Config {
7    pub query: String,
8    pub filename: String,
9    pub case_sensitive: bool,
10}
11
12impl Config {
13    pub fn new(mut args: env::Args) -> Result<Config, &'static str> {
14        args.next();
15
16        let query = match args.next() {
17            Some(arg) => arg,
18            None => return Err("Didn't get a query string"),
19        };
20
21        let filename = match args.next() {
22            Some(arg) => arg,
23            None => return Err("Didn't get a file name"),
24        };
25
26        let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
27
28        Ok(Config {
29            query,
30            filename,
31            case_sensitive,
32        })
33    }
34}
35
36pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
37    let contents = fs::read_to_string(config.filename)?;
38
39    let result = if config.case_sensitive {
40        search(&config.query, &contents)
41    } else {
42        search_case_insensitive(&config.query, &contents)
43    };
44
45    for line in result {
46        println!("{}", line);
47    }
48
49    Ok(())
50}
51
52/// Finds all lines within a block of text that contain the query, this method is case-sensitive
53///
54/// # Examples
55///
56/// ```
57/// let query = "duct";
58/// let contents = "\
59/// Rust:
60/// safe, fast, productive.
61/// Pick three.
62/// Duct tape.";
63///
64/// assert_eq!(vec!["safe, fast, productive."], minigrep_jondeaves::search(query, contents));
65/// ```
66pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
67    contents
68        .lines()
69        .filter(|line| line.contains(query))
70        .collect()
71}
72
73/// Finds all lines within a block of text that contain the query, this method is case-insensitive
74///
75/// # Examples
76///
77/// ```
78/// let query = "rUsT";
79/// let contents = "\
80/// Rust:
81/// safe, fast, productive.
82/// Pick three.
83/// Trust me.";
84///
85/// assert_eq!(
86///     vec!["Rust:", "Trust me."],
87///     minigrep_jondeaves::search_case_insensitive(query, contents)
88/// );
89/// ```
90pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
91    contents
92        .lines()
93        .filter(|line| line.to_lowercase().contains(&query.to_lowercase()))
94        .collect()
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100
101    #[test]
102    fn case_sensitive() {
103        let query = "duct";
104        let contents = "\
105Rust:
106safe, fast, productive.
107Pick three.
108Duct tape.";
109
110        assert_eq!(vec!["safe, fast, productive."], search(query, contents));
111    }
112
113    #[test]
114    fn case_insensitive() {
115        let query = "rUsT";
116        let contents = "\
117Rust:
118safe, fast, productive.
119Pick three.
120Trust me.";
121
122        assert_eq!(
123            vec!["Rust:", "Trust me."],
124            search_case_insensitive(query, contents)
125        );
126    }
127}