1use std::{env, error::Error, fs, process};
3
4#[derive(Debug)]
5pub struct CommandInput {
6 query: String,
7 filename: String,
8 case_sensitive: bool,
9}
10
11impl CommandInput {
12 pub fn new(mut args: env::Args) -> Result<CommandInput, &'static str> {
13 args.next();
14
15 let query = match args.next() {
16 Some(i) => i,
17 None => return Err("Didn't get query param"),
18 };
19
20 let filename = match args.next() {
21 Some(i) => i,
22 None => return Err("Didn't get filename param"),
23 };
24
25 let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
27
28 return Ok(CommandInput {
29 query,
30 filename,
31 case_sensitive,
32 });
33 }
34}
35
36pub fn run(command: CommandInput) -> Result<(), Box<dyn Error>> {
39 let contents = fs::read_to_string(&command.filename)?;
40
41 let result = if command.case_sensitive {
42 search_case_sensitive(&command.query, &contents)
43 } else {
44 search_case_insensitive(&command.query, &contents)
45 };
46
47 for line in result {
48 println!("{}", line);
49 }
50
51 Ok(())
52}
53
54pub fn search_case_sensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
55 let mut result: Vec<&str> = vec![];
56 for item in contents.lines() {
57 if item.contains(query) {
58 result.push(item);
59 }
60 }
61
62 result
63}
64
65pub fn search_case_sensitive_function_style<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
66 contents
67 .lines()
68 .filter(|line| line.contains(query))
69 .collect()
70}
71
72pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
73 let query = query.to_lowercase();
74
75 let mut result = Vec::new();
76 for line in contents.lines() {
77 if line.to_lowercase().contains(&query) {
78 result.push(line);
79 }
80 }
81
82 return result;
83}
84
85pub fn search_case_insensitive_function_stype<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
86 let query = query.to_lowercase();
87 contents
88 .lines()
89 .filter(|line| line.to_lowercase().contains(&query))
90 .collect()
91}
92
93#[cfg(test)]
94mod tests {
95 use std::vec;
96
97 use crate::{search_case_insensitive, search_case_sensitive};
98
99 #[test]
100 fn case_sensitive() {
101 let query = "duct";
102 let contents = "
103Rust:
104safe, fast, productive.
105Pick three.";
106 assert_eq!(
107 vec!["safe, fast, productive."],
108 search_case_sensitive(query, contents)
109 );
110 }
111
112 #[test]
113 fn case_insensitive() {
114 let query = "rUst";
115 let contents = "
116Rust:
117safe, fast, productive.
118Pick three.
119Trust me.";
120
121 assert_eq!(
122 vec!["Rust: ", "Trust me."],
123 search_case_insensitive(query, contents)
124 );
125 }
126}