minigrepyuqing/
lib.rs

1//! ## My
2//! `my_crate` is a collection of utilities to make performing certain
3//!
4//! hjhjhj
5
6use std::env;
7use std::error::Error;
8use std::fs;
9
10/// # example
11/// jkjkjkhghf
12/// ghjghjgj
13
14pub struct Config {
15    pub query: String,
16    pub file_path: String,
17    pub ignore_case: bool,
18}
19
20impl Config {
21    // fn new(args: &[String]) -> Config {
22    //     if args.len() < 3 {
23    //         panic!("not enough arguments");
24    //     }
25    //     let query = args[1].clone();
26    //     let file_path = args[2].clone();
27
28    //     Config { query, file_path }
29    // }
30
31    pub fn build(mut args: impl Iterator<Item = String>) -> Result<Config, &'static str> {
32        args.next();
33
34        let query = match args.next() {
35            Some(arg) => arg,
36            None => return Err("Didn't get a query string"),
37        };
38
39        let file_path = match args.next() {
40            Some(arg) => arg,
41            None => return Err("Didn't get a file path"),
42        };
43
44        let ignore_case = env::var("IGNORE_CASE").is_ok();
45
46        Ok(Config {
47            query,
48            file_path,
49            ignore_case,
50        })
51    }
52}
53
54// Box<dyn Error> a type that implements the Error trait
55
56pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
57    println!("Searching for {}", config.query);
58    println!("In file {}", config.file_path);
59
60    let contents = fs::read_to_string(config.file_path)?;
61
62    let results = if config.ignore_case {
63        search_case_insensitive(&config.query, &contents)
64    } else {
65        search(&config.query, &contents)
66    };
67
68    for line in results {
69        println!("{line}");
70    }
71
72    Ok(())
73}
74
75/// search
76///
77/// # Examples
78///
79/// ```
80/// use minigrep::search;
81///
82/// let query = "bvc";
83/// let contents = "\
84/// bvc
85/// llk
86/// mnb bvc
87/// ";
88///
89/// search(&query, &contents);
90/// ```
91
92pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
93    contents
94        .lines()
95        .filter(|line| line.contains(query))
96        .collect()
97}
98
99/// search_case_insensitive
100///
101/// # Examples
102/// ```
103/// let arg = 5;
104/// search_case_insensitive()
105/// ```
106pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
107    contents
108        .lines()
109        .filter(|line| line.to_lowercase().contains(&query.to_lowercase()))
110        .collect()
111}
112
113#[cfg(test)]
114mod tests {
115    use super::*;
116
117    #[test]
118    fn one_result() {
119        let query = "duct";
120        let contents = "\
121Rust:
122safe, fast, productive.
123Pick three.
124Duct tape.";
125
126        assert_eq!(vec!["safe, fast, productive."], search(query, contents));
127    }
128
129    #[test]
130    fn case_insensitive() {
131        let query = "rUsT";
132        let contents = "\
133Rust:
134safe, fast, productive.
135Pick three.
136Trust me.";
137
138        assert_eq!(
139            vec!["Rust:", "Trust me."],
140            search_case_insensitive(query, contents)
141        );
142    }
143}