1use std::{env, error::Error, fs};
2
3pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
4 let file_content = fs::read_to_string(config.file_path)?;
5
6 let results = if config.ignore_case {
7 search_case_insensitve(&config.query, &file_content)
8 } else {
9 search(&config.query, &file_content)
10 };
11
12 println!("{:?}", results);
13 for line in results {
14 println!("{line}");
15 }
16
17 Ok(())
18}
19
20pub struct Config {
21 pub query: String,
22 pub file_path: String,
23 pub ignore_case: bool,
24}
25
26impl Config {
27 pub fn build(mut args: impl Iterator<Item = String>) -> Result<Self, &'static str> {
28 args.next();
29
30 let query = match args.next() {
31 Some(arg) => arg,
32 None => return Err("Didn't get a query string"),
33 };
34 let file_path = match args.next() {
35 Some(arg) => arg,
36 None => return Err("Didn't get a file path"),
37 };
38 let ignore_case = env::var("IGNORE_CASE").is_ok();
39
40 Ok(Config {
41 query,
42 file_path,
43 ignore_case,
44 })
45 }
46}
47
48pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
49 contents
50 .lines()
51 .filter(|line| line.trim().contains(query))
52 .map(|line| line.trim())
53 .collect()
54}
55
56pub fn search_case_insensitve<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
57 let query = query.to_lowercase();
58
59 contents
60 .lines()
61 .filter(move |line| line.to_lowercase().trim().contains(&query))
62 .map(|line| line.trim())
63 .collect()
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn one_result() {
72 let query = "duct";
73 let contents = "
74 Rust:
75 safe, fast, productive.
76 Pick three.
77 ";
78
79 assert_eq!(vec!["safe, fast, productive."], search(query, contents));
80 }
81
82 #[test]
83 fn case_sensitive() {
84 let query = "duct";
85 let contents = "
86 Rust:
87 safe, fast, productive.
88 Pick three.
89 Duct tape";
90
91 assert_eq!(vec!["safe, fast, productive."], search(query, contents));
92 }
93
94 #[test]
95 fn case_insensitive() {
96 let query = "rUST";
97 let contents = "
98 Rust:
99 safe, fast, productive.
100 Pick three.
101 Trust me.";
102 assert_eq!(
103 vec!["Rust:", "Trust me."],
104 search_case_insensitve(query, contents)
105 );
106 }
107}