kean_minigrep/
lib.rs

1//! # Kean Minigrep
2//!
3//! `kean_minigrep` is a simple tool used to search strings from a file.
4
5use std::{env, error::Error, fs};
6
7
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(mut args: env::Args) -> Result<Config, &'static str> {
17        args.next();
18
19        let query = match args.next() {
20            Some(v) => v,
21            None => return Err("Didn't get a query string"),
22        };
23
24        let filename = match args.next() {
25            Some(v) => v,
26            None => return Err("Didn't get a filename string"),
27        };
28
29        let case_sensitive = match args.next() {
30            Some(v) => "--insensitive" != v,
31            None => env::var("CASE_INSENSITIVE").is_err(),
32        };
33
34        Ok(Config {
35            query,
36            filename,
37            case_sensitive,
38        })
39    }
40}
41
42pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
43    let contents = fs::read_to_string(config.filename)?;
44
45    let results = if config.case_sensitive {
46        search(&config.query, &contents)
47    } else {
48        search_case_insensitive(&config.query, &contents)
49    };
50
51    for line in results {
52        println!("{}", line);
53    }
54    Ok(())
55}
56
57/// Search query string in contents.
58/// 
59/// # Example
60///
61/// ```
62/// let query = "duct";
63/// let contents = "\
64/// Rust:
65/// safe, fast, productive.
66/// Pick three.
67/// Duct tape.";
68///
69/// assert_eq!(vec!["safe, fast, productive."], kean_minigrep::search(query, contents));
70/// ```
71pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
72    contents
73        .lines()
74        .filter(|line| line.contains(query))
75        .collect()
76}
77
78/// 在内容中搜索字符串,忽略大小写.
79/// 
80/// # 示例
81///
82/// ```
83/// let query = "rUsT";
84/// let contents = "\
85/// Rust:
86/// safe, fast, productive.
87/// Pick three.
88/// Trust me.";
89///
90/// assert_eq!(
91///    vec!["Rust:", "Trust me."],
92///    kean_minigrep::search_case_insensitive(query, contents)
93/// );
94/// ```
95pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
96    contents
97        .lines()
98        .filter(|line| line.to_lowercase().contains(&query.to_lowercase()))
99        .collect()
100}
101
102#[cfg(test)]
103mod tests {
104    use super::*;
105
106    #[test]
107    fn case_sensitive() {
108        let query = "duct";
109        let contents = "\
110Rust:
111safe, fast, productive.
112Pick three.
113Duct tape.";
114        assert_eq!(vec!["safe, fast, productive."], search(query, contents));
115    }
116
117    #[test]
118    fn case_insensitive() {
119        let query = "rUsT";
120        let contents = "\
121Rust:
122safe, fast, productive.
123Pick three.
124Trust me.";
125        assert_eq!(
126            vec!["Rust:", "Trust me."],
127            search_case_insensitive(query, contents)
128        );
129    }
130}