use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::error::Error;
pub struct Config {
pub query: String,
pub filename: String,
pub case_sensitive: bool,
}
impl Config {
pub fn new(args: Vec<String>) -> Result<Config, &'static str> {
if args.len() < 3 {
return Err("args are not enough");
}
let query = args[1].to_string();
let filename = args[2].to_string();
let case_sensitive = env::var("CASE_INSENSITIVE").is_err();
Ok(Config{ query, filename, case_sensitive})
}
}
pub fn run(config: Config) -> Result<(), Box<Error>> {
let mut file = File::open(config.filename)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let result = if config.case_sensitive {
search(&config.query, &contents)
} else {
search_case_insensitive(&config.query, &contents)
};
for line in result {
println!("{}", line);
}
Ok(())
}
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
let mut result = Vec::new();
for line in contents.lines() {
if line.contains(query) {
result.push(line);
}
}
result
}
pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
let mut result = Vec::new();
let query = query.to_lowercase();
for line in contents.lines() {
if line.to_lowercase().contains(&query) {
result.push(line);
}
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn searching() {
let contents = "\
abc def to name,
998 ab To you
after de";
let result = search("ou", contents);
assert_eq!(vec!["998 ab To you"], result);
}
#[test]
fn searching_case_insensitive() {
let contents = "\
abc def to name,
998 ab To you
after de";
let result = search_case_insensitive("TO", contents);
assert_eq!(vec!["abc def to name,", "998 ab To you"], result);
}
#[test]
fn new_config() {
let args = vec!["app".to_string(), "pzs".to_string(), "zj".to_string()];
let config = Config::new(args).unwrap();
assert_eq!(String::from("pzs"), config.query);
assert_eq!(String::from("zj"), config.filename);
assert_eq!(true, config.case_sensitive);
}
}