1use std::{env, error::Error, fs};
2
3pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
4    let content = fs::read_to_string(&config.filename)?; let search_result = if config.case_sensitive {
7        search(&config.query, &content)
8    } else {
9        search_case_insensitive(&config.query, &content)
10    };
11    for line in search_result {
12        println!("find: {}", line);
13    }
14    Ok(()) }
17
18pub struct Config {
19    pub cmd: String,
20    pub query: String,
21    pub filename: String,
22    pub case_sensitive: bool,
23}
24
25impl Config {
26    pub fn new(mut args: std::env::Args) -> Result<Config, &'static str> {
27        if args.len() < 3 {
28            return Err("Parsing args failed, args were insuffient");
30        }
31        Ok(Config {
33            cmd: match args.next() {
34                Some(arg) => arg,
35                None => return Err("没有cmd "),
36            },
37            query: match args.next() {
38                Some(arg) => arg,
39                None => return Err("没有query字符串 "),
40            },
41            filename: match args.next() {
42                Some(arg) => arg,
43                None => return Err("没有filename字符串 "),
44            },
45            case_sensitive: env::var("CASE_INSENSITIVE").is_err(), })
50    }
51}
52
53fn search<'a>(query: &str, content: &'a str) -> Vec<&'a str> {
54    content
66        .lines() .filter(|line| line.contains(query)) .collect() }
70
71fn search_case_insensitive<'a>(query: &str, content: &'a str) -> Vec<&'a str> {
72    let lowercase_query = query.to_ascii_lowercase();
81    content
82        .lines()
83        .filter(|line| line.to_lowercase().contains(&lowercase_query))
84        .collect()
85}
86
87#[cfg(test)]
88mod tests {
89    use std::vec;
90
91    use super::*;
92
93    #[test]
95    fn case_sensitive() {
96        let query = "duct";
97        let contents = "\
98Rust:
99safe, fast, productive.
100Pick three.
101Duct tape.";
102        assert_eq!(vec!["safe, fast, productive."], search(query, contents))
103    }
104
105    #[test]
106    fn case_insensitive() {
107        let query = "rUsT";
108        let contents = "\
109Rust:
110safe, fast, productive.
111Pick three.
112rust me";
113        assert_eq!(
114            vec!["Rust:", "rust me"],
115            search_case_insensitive(query, contents)
116        )
117    }
118}