use std::error::Error; use std::fmt; pub struct Config { pub query: String, pub filename: String, pub sensitive: bool, } impl Config { pub fn new(args: &[String]) -> Result { if args.len() < 2 { return Err("args len less then 2"); } let query = args[0].clone(); let filename = args[1].clone(); let sensitive = std::env::var("CASE_SENSITIVE").is_ok(); Ok(Config { query, filename, sensitive, }) } } pub struct GrepRet { line: i32, context: String, } impl GrepRet { fn new(line: i32, context: &str) -> GrepRet { GrepRet { line, context: context.to_string(), } } } impl fmt::Display for GrepRet { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "line:{}: {}", self.line, self.context) } } pub fn run(config: &Config) -> Result, Box> { let context = std::fs::read_to_string(&config.filename)?; if config.sensitive { Ok(search_sensitive(&config.query, &context)) } else { Ok(search_insensitive(&config.query, &context)) } } fn search_sensitive(query: &str, context: &String) -> Vec { let mut idx = 0; let mut result = Vec::new(); for line in context.lines() { idx += 1; if line.contains(query) { result.push(GrepRet::new(idx, line)); } } result } fn search_insensitive(query: &str, context: &String) -> Vec { let mut idx = 0; let mut result = Vec::new(); for line in context.lines() { idx += 1; let lower = line.to_lowercase(); if lower.contains(&query.to_lowercase()) { result.push(GrepRet::new(idx, line)); } } result } #[cfg(test)] pub mod test { use super::*; #[test] fn grep_new1() { let line = 10; let context = "zzz"; let grep_ret = GrepRet::new(line, context); assert_eq!(line, grep_ret.line); assert_eq!(context, grep_ret.context); } #[test] fn grep_new2() { let line = 10; let context = "zzz"; let grep_ret = GrepRet::new(line, context); assert_ne!(!line, grep_ret.line); assert_eq!(context, grep_ret.context); } #[test] #[ignore] // cargo test -- --ignored fn grep_new3() { let line = 10; let context = "zzz"; let grep_ret = GrepRet::new(line, context); assert_ne!(!line, grep_ret.line); assert_eq!(context, grep_ret.context); } }