minigrep_zyven/
lib.rs

1//! # minigrep-zyven
2//!
3//! `minigrep-zyven` is a minimal implementation of `grep` in Unix-like system which
4//! will find given query in specified file. Author by [Zyven](https://github.com/Nonsensersunny)
5
6use std::{fs, env, error::Error};
7
8pub struct Config {
9    pub query: String,
10    pub filename: String,
11    pub case_sensitive: bool,
12}
13
14impl Config {
15    pub fn new(mut args: std::env::Args) -> Result<Config, &'static str> {
16        args.next();
17
18        let query = match args.next() {
19            None => return Err("Didn't get a query string"),
20            Some(arg) => arg
21        };
22        let filename = match args.next() {
23            None => return Err("Didn't get file name"),
24            Some(arg) => arg,
25        };
26
27        Ok(Config {
28            query,
29            filename,
30            case_sensitive: match env::var("case_sensitive") {
31                Ok(i) => i == "true",
32                Err(_) => false,
33            }
34        })
35    }
36}
37
38pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
39    // read file
40    let contents = fs::read_to_string(config.filename)?;
41
42    let result = if config.case_sensitive {
43        search(&*config.query, &*contents)
44    } else {
45        search_case_insensitive(&*config.query, &*contents)
46    };
47
48    for i in result {
49        println!("{}", i);
50    }
51
52    Ok(())
53}
54
55/// Search query from contents
56///
57/// # Example
58/// ```
59/// use minigrep::search;
60/// let query = "duct";
61/// let contents = "\
62/// Rust:
63/// safe, fast, productive.
64/// Pick three.
65/// Duct tape.";
66/// assert_eq!(
67///   vec!["safe, fast, productive."],
68///   search(query, contents)
69/// );
70/// ```
71pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
72    contents.lines()
73        .filter(|line| line.contains(query))
74        .collect()
75}
76
77pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
78    contents.lines()
79        .filter(|line| line.to_lowercase().contains(&query.to_lowercase()))
80        .collect()
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn one_result() {
89        let query = "duct";
90        let contents = "\
91Rust:
92safe, fast, productive.
93Pick three.";
94        assert_eq!(vec!["safe, fast, productive."],
95                   search(query, contents));
96    }
97
98    #[test]
99    fn case_sensitive() {
100        let query = "duct";
101        let contents = "\
102Rust:
103safe, fast, productive.
104Pick three.
105Duct tape.";
106
107        assert_eq!(
108            vec!["safe, fast, productive."],
109            search(query, contents)
110        );
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}