Skip to main content

minigrep_nepelover/
lib.rs

1//! # minigrep
2//! 
3//! `minigrep` es una librería para buscar un determinado texto en ficheros de texto.
4use std::io::BufRead;
5pub struct Config{
6    query: String,
7    file_path: String,
8    ignore_case: bool,
9}
10
11impl Config {
12    pub fn query(&self) -> &str{
13        self.query.as_str()
14    }
15
16    pub fn file_path(&self) -> &str{
17        self.file_path.as_str()
18    }
19
20    pub fn ignore_case(&self) -> &bool{
21        &self.ignore_case
22    }
23
24    pub fn build(
25        mut args: impl Iterator<Item = String>,
26    ) -> Result<Config, &'static str>{
27        args.next();
28
29        let query = match args.next() {
30            Some(arg) => arg,
31            None => return Err("Did not get a query string"),
32        };
33        
34        let file_path = match args.next() {
35            Some(arg) => arg,
36            None => return Err("Did not get a file path"),
37        };
38
39        Ok(
40            Config { 
41                query: query, 
42                file_path: file_path,
43                ignore_case: std::env::var("IGNORE_CASE").is_ok(),
44            }
45        )
46    }
47    pub fn run(&self) -> Result<(), Box<dyn std::error::Error>>{
48        let file = std::fs::File::open(self.file_path.as_str())?;
49
50        let reader = std::io::BufReader::new(file);
51
52        let contents:String = reader.lines().filter_map(
53            |line|{
54                if let None = line.as_ref().ok(){
55                    None
56                } else {
57                    Some(format!("{}\n", line.unwrap()))
58                }
59            }
60        ).collect();
61
62        let results:Vec<&str> = if self.ignore_case{
63            search_case_insensitive(self.query.as_str(), &contents)
64        } else{
65            search(self.query.as_str(), &contents)
66        };
67
68        for line in results{
69            println!("{line}");
70        }
71
72        Ok(())
73    }
74    
75}
76/// Busca un elemento(query) en un determinado texto(contents).
77/// 
78///  # Example
79/// ```
80/// let query = "nepe";
81///let contents = "\
82///Sí, me has pillado
83///soy un amante de los Nepes
84///cuando veo un Nepe
85///sólo pienso en su gran sabor neperil.";
86///
87///assert_eq!(vec!["sólo pienso en su gran sabor neperil."], minigrep_nepelover::search(query, contents));
88/// ```
89pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str>{
90    contents.lines().filter(
91        |l|{
92            l.contains(query)   
93        }
94    ).collect()
95}
96
97pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str>{
98    contents.lines().filter(
99        |line|{
100            line.to_lowercase().contains(&query.to_lowercase())
101        }
102    ).collect()
103}
104
105#[cfg(test)]
106mod tests{
107    use super::*;
108
109    #[test]
110    fn case_sensitive(){
111        let query = "duct";
112        let contents = "\
113Rust:
114safe, fast, productive.
115Pick three.
116Duck tape.";
117
118        assert_eq!(vec!["safe, fast, productive."], search(query, contents));
119    }
120
121    #[test]
122    fn case_insensitive(){
123        let query = "rUsT";
124        let contents = "\
125Rust:
126safe, fast, productive.
127Pick three.
128Trust me.";
129
130        assert_eq!(
131            vec!["Rust:", "Trust me."],
132            search_case_insensitive(query, contents)
133        );
134    }
135
136}