1use std::env;
2use std::error::Error;
3use std::fs;
4
5pub struct Config {
6 pub query: String,
7 pub file_path: String,
8 pub ignore_case: bool,
9}
10
11impl Config {
12 pub fn build(mut args: impl ExactSizeIterator<Item = String>) -> Result<Config, &'static str> {
13 args.next();
15 if args.len() < 2 {
16 return Err("Not enough arguments");
17 }
18
19 let ignore_case: bool;
20 if args.len() > 2 {
21 ignore_case = match args.next() {
23 Some(arg) => arg.contains("IGNORE_CASE"),
24 None => false,
25 };
26 } else {
27 ignore_case = env::var("IGNORE_CASE").is_ok();
28 }
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
39 Ok(Config {
40 query,
41 file_path,
42 ignore_case,
43 })
44 }
45}
46
47pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
48 contents
49 .lines()
50 .filter(|line| line.contains(query))
51 .collect()
52}
53
54pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
55 contents
57 .lines()
58 .filter(|line| line.to_lowercase().contains(&query.to_lowercase()))
59 .collect()
60}
61
62pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
63 let contents = fs::read_to_string(config.file_path)?;
64
65 let results = if config.ignore_case {
66 search_case_insensitive(&config.query, &contents)
67 } else {
68 search(&config.query, &contents)
69 };
70
71 for line in results {
72 println!("{line}");
73 }
74
75 Ok(())
76}
77
78#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn case_sensitive() {
85 let query = "duct";
86 let contents = "\
87Rust:
88safe, fast, productive.
89Pick three.
90Duct tape.";
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 = "\
98Rust:
99safe, fast, productive.
100Pick three.
101Trust me.";
102
103 assert_eq!(
104 vec!["Rust:", "Trust me."],
105 search_case_insensitive(query, contents)
106 )
107 }
108}