1use std::error::Error;
2use std::fs;
3use std::env;
4
5pub struct Config{
6 pub query:String,
7 pub file_name:String,
8 pub case_sensitive:bool,
9}
10impl Config{
11 pub fn new(mut args: std::env::Args) -> Result<Config,&'static str>{
12 args.next();
13 let query = match args.next(){
14 Some(arg) => arg,
15 None => return Err("Didn't get a query String"),
16 };
17 let file_name = match args.next(){
18 Some(arg) => arg,
19 None => return Err("Didn't get a file name"),
20 };
21 let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
22 Ok(Config{query,file_name,case_sensitive})
23 }
24}
25pub fn run(config:Config) -> Result<(),Box<dyn Error>>{
26 let contents = fs::read_to_string(config.file_name)?;
27 let results = if config.case_sensitive {
28 search(&config.query, &contents)
29 }else{
30 search_case_insensitive(&config.query, &contents)
31 };
32 for line in results {
33 println!("{}",line);
34 }
35 Ok(())
36}
37pub fn search<'a>(query:&str,contents:&'a str) -> Vec<&'a str>{
46 contents.lines().filter(|a|a.contains(query)).collect()
47}
48pub fn search_case_insensitive<'a>(query:&str,contents:&'a str)
57-> Vec<&'a str>{
58 contents.lines().filter(|a|a.to_lowercase().
59 contains(&query.to_lowercase())).collect()
60}
61#[cfg(test)]
62mod tests{
63 use super::*;
64 #[test]
65 fn case_sensitive(){
66 let query = "duct";
67 let contents="\
68Rust:
69safe,fast,productive.
70Pick three.
71Duct tape";
72 assert_eq!(vec!["safe,fast,productive."],search(query,contents));
73 }
74 #[test]
75 fn case_insensitive(){
76 let query = "rUsT";
77 let contents="\
78Rust:
79safe,fast,productive.
80Pick three.
81Trust me.";
82 assert_eq!(vec!["Rust:", "Trust me."],
83 search_case_insensitive(query,contents));
84 }
85}