1use std::env;
2use std::error::Error;
3use std::fs;
4use std::process;
5
6pub struct Config {
7 pub query: String,
8 pub file_path: String,
9 pub ignore_case: bool,
10}
11
12impl Config {
13 pub fn build(mut args: impl Iterator<Item = String>) -> Result<Config, &'static str> {
20 args.next();
21
22 let query = match args.next() {
23 Some(s) => s,
24 None => return Err("Didn't get a query string".into()),
25 };
26 let file_path = match args.next() {
27 Some(s) => s,
28 None => return Err("Didn't get a file path".into()),
29 };
30 let ignore_case = match env::var("IGNORE_CASE") {
31 Ok(x) => match x.parse::<i32>().unwrap_or_else(|err| {
32 println!("[Config][build] Got err: {err}");
33 process::exit(1);
34 }) {
35 0 => false,
36 _ => true,
37 },
38 Err(_) => false,
39 };
40 Ok(Config {
41 query,
42 file_path,
43 ignore_case,
44 })
45 }
46}
47
48pub fn run(config: &Config) -> Result<(), Box<dyn Error>> {
49 let content = fs::read_to_string(&config.file_path)?;
50 let results = if config.ignore_case {
51 search_case_insensitive(&config.query, &content)
52 } else {
53 search(&config.query, &content)
54 };
55 for line in results {
56 println!("{line}");
57 }
58 Ok(())
59}
60
61pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
62 let mut results = Vec::new();
63 for line in contents.lines() {
64 if line.contains(query) {
65 results.push(line.trim());
66 }
67 }
68 results
69}
70pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
84 let query = &query.to_lowercase();
85 let mut results = Vec::new();
86 for line in contents.lines() {
87 if line.to_lowercase().contains(query) {
88 results.push(line);
89 }
90 }
91 results
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn one_result() {
100 let query = "duct";
101 let contents = "\
102Rust:
103safe, fast, productive.
104Pick three
105Duct tape.";
106 assert_eq!(vec!["safe, fast, productive."], search(query, contents));
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}