yuan_grep/
lib.rs

1//! # My Crate
2//!
3//! `my_crate` is a collection of utilities to make performing certain
4//! calculations more convenient.
5
6use std::error::Error;
7use std::fs;
8use std::env;
9
10/// Adds one to the number given.
11// --snip--
12/// 
13/// # Examples
14///
15/// ```
16/// let arg = 5;
17/// let answer = my_crate::add_one(arg);
18///
19/// assert_eq!(6, answer);
20/// ```
21pub fn add_one(x: i32) -> i32 {
22    x + 1
23}
24
25
26pub struct Config {
27    pub query: String,
28    pub filename: String,
29    pub case_sensitive:bool
30}
31
32impl Config {
33    pub fn new(mut args: env::Args) -> Result<Config, &'static str> {
34        args.next();
35        let query = match args.next() {
36            Some(arg) => arg,
37            None => return Err("Didn't get a query string")
38        };
39        let filename = match args.next() {
40            Some(arg) => arg,
41            None => return Err("Didn't get filename string")
42        };
43        let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
44        Ok(Config { query, filename ,case_sensitive})
45    }
46}
47
48pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
49    let contents = fs::read_to_string(config.filename)?;
50
51    let results = if config.case_sensitive  {
52        search(&config.query, &contents)
53    }else{
54        search_case_insensitive(&config.query, &contents)
55    };
56
57    for line in results {
58        println!("{}", line)
59    } 
60
61    Ok(())
62}
63
64
65/// 查询指定内容所在行
66/// 
67/// # Examples
68/// 
69/// ```
70///     use yuan_grep::search;
71///     let query = "duct";
72///     let contents = "\
73///Rust:
74///safe, fast, productive.
75///Pick three.
76///Duct tape.";
77///
78///     assert_eq!(vec!["safe, fast, productive."], search(query, contents));
79/// ```
80pub fn search<'a>(query:&str,contents:&'a str) -> Vec<&'a str> {
81    contents.lines().into_iter().filter(|line| line.contains(query)).collect()
82}
83
84pub fn search_case_insensitive<'a>(query:&str, contents:&'a str) -> Vec<&'a str> {
85    contents.lines().into_iter()
86    .filter(|line| line.to_lowercase().contains(&(query.to_lowercase())))
87    .collect()
88}
89
90
91#[cfg(test)]
92mod tests {
93
94    use crate::*;
95
96    #[test]
97    fn case_sensitive(){
98        let query = "duct";
99        let contents = "\
100Rust:
101safe, fast, productive.
102Pick three.
103Duct tape.";
104
105        assert_eq!(vec!["safe, fast, productive."], search(query, contents));
106    }
107
108
109    #[test]
110    fn case_insensitive(){
111        let query = "rUsT";
112        let contents = "\
113Rust:
114safe, fast, productive.
115Pick three.
116Trust me.";
117
118        assert_eq!(
119            vec!["Rust:", "Trust me."], 
120            search_case_insensitive(query, contents)
121        );
122    }
123    
124}