newminigrep/
lib.rs

1//! # Minigrep made by me
2//!
3//! `minigrep` is a personal version of grep.
4
5use std::fs;
6use std::error::Error;
7use std::env;
8
9pub struct Config {
10    pub query: String,
11    pub filename: String,
12    pub case_sensitive: bool,
13}
14
15impl Config {
16    // pub fn new(args: &[String]) -> Result<Config, &'static str> {
17    pub fn new(mut args: env::Args) -> Result<Config, &'static str> {
18        args.next();
19        let query = match args.next() {
20            Some(arg) => arg,
21            None => return Err("Didn't get a query string")
22        };
23        
24        let filename = match args.next() {
25            Some(arg) => arg,
26            None => return Err("Didn't get a file name")
27        };
28
29        let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
30        
31        Ok(Config { query, filename, case_sensitive })
32    }
33    
34}
35
36
37/// To Run program
38/// # Examples commands
39///
40/// ```
41/// cargo run frog poem.txt
42/// ```
43
44/// ```
45/// cargo run fRog poem.txt
46/// ```
47pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
48    let contents = fs::read_to_string(config.filename)?;
49    println!("&config.query: {}, &contents: {}", &config.query, &contents);
50    let results = if config.case_sensitive {
51        search(&config.query, &contents)
52    } else {
53        search_case_insensitive(&config.query, &contents)
54    };
55    
56    for line in results {
57        println!("{}", line);
58    };
59    
60    Ok(())
61}
62
63pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
64    contents.lines().filter(|line| line.contains(query)).collect()
65    // Below code does same thing as above.
66    // let mut vector = vec![];
67    // for line in contents.lines() {
68    //     if line.contains(query) {
69    //         vector.push(line);
70    //     }
71    // }
72    // vector
73}
74
75pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
76    let query = query.to_lowercase();
77    contents.lines().filter(|line| line.to_lowercase().contains(&query)).collect()
78    // Below code does same thing as above.
79    // let mut vector = vec![];
80    // let query = query.to_lowercase();
81    // for line in contents.lines() {
82    //     if line.to_lowercase().contains(&query) {
83    //         vector.push(line);
84    //     }
85    // }
86    // 
87    // vector
88}
89
90#[cfg(test)]
91mod tests {
92    use super::{search, search_case_insensitive};
93
94    #[test]
95    fn case_sensitive() {
96        let query = "duct";
97        let contents = "\
98Rust:
99safe, fast, productive.
100Pick three.
101Duct tape.";
102
103        assert_eq!(vec!["safe, fast, productive."], search(query, contents));
104    }
105    
106    #[test]
107    fn case_insensitve() {
108        let query = "rust";
109        let contents = "\
110Rust:
111safe, fast, productive.
112Pick three.
113Trust me.";
114
115        assert_eq!(vec!["Rust:", "Trust me."], search_case_insensitive(query, contents));
116    }
117}