minigrepwebdot/
lib.rs

1//! # minigrepwebdot
2//! 
3//! minigrepwebdot is a command-line utility tool that helps to search for occurences of words on a file.
4
5
6use std::{env, fs};
7use std::error::Error;
8
9/// # Config
10/// 
11/// This is a struct used to hold information about user's arguments on file search.
12/// 
13/// # Examples
14/// 
15/// ```
16/// minigrepwebdot::Config::build(vec!["hey".to_string(), "hey".to_string(), "poem.txt".to_string()].into_iter());
17/// ```
18pub struct Config {
19    pub query: String,
20    pub  file_path: String,
21    pub ignore_case: bool
22}
23
24impl Config {
25    pub fn build(mut args: impl Iterator<Item = String>) -> Result<Config, &'static str> {
26        args.next();
27        
28        let query = match args.next() {
29            Some(arg) => arg,
30            None => return Err("Didn't get a query string")
31        };
32
33        let file_path = match args.next() {
34            Some(arg) => arg,
35            None => return Err("Didn't get a file path")
36        };
37
38        let ignore_case = env::var("IGNORE_CASE").is_ok();
39        
40        Ok(Config {query, file_path, ignore_case})
41    }
42}
43
44pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
45    let contents = fs::read_to_string(config.file_path)?;
46
47    let results = if config.ignore_case {
48        search_case_insensitive(&config.query, &contents)
49    } else {
50        search(&config.query, &contents)
51    };
52
53    for line in results {
54        println!("{line}")
55    }
56
57    Ok(())
58}
59
60pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
61    contents.lines().filter(|line| line.contains(query)).collect() 
62}
63
64pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
65    contents.lines().filter(|line| line.to_ascii_lowercase().contains(&query.to_ascii_lowercase())).collect()
66}
67
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn case_sensitive() {
75        let query = "duct";
76        let contents = "\
77Rust:
78safe, fast, productive.
79Pick three.
80Duct tape.";
81
82        assert_eq!(vec!["safe, fast, productive."], search(query, contents))
83    }
84
85    #[test]
86    fn case_insensitive(){
87        let query = "rUSt";
88        let contents = "\
89Rust:
90safe, fast, productive.
91Pick three.
92Trust me.";
93
94        assert_eq!(vec!["Rust:", "Trust me."], search_case_insensitive(query, contents));
95    }
96}