use std::error::Error;
use std::{env, fs};
pub struct Config {
pub search: String,
pub file_path: String,
pub ignore_case: bool,
}
impl Config {
pub fn build(args: &Vec<String>) -> Result<Config, &'static str> {
if args.len() < 3 {
return Err("至少传入2个参数");
}
let search = args[1].clone();
let file_path = args[2].clone();
let ignore_case = env::var("IGNORE_CASE").is_ok();
Ok(Config {
search,
file_path,
ignore_case,
})
}
}
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
let content = fs::read_to_string(config.file_path)?;
let result;
if config.ignore_case {
result = find_insensitive(&config.search, &content);
} else {
result = find(&config.search, &content);
}
for line in result {
println!("{line}");
}
Ok(())
}
pub fn find<'a>(search: &str, content: &'a str) -> Vec<&'a str> {
let mut result = vec![];
for line in content.lines() {
if line.contains(search) {
result.push(line);
}
}
result
}
pub fn find_insensitive<'a>(search: &str, content: &'a str) -> Vec<&'a str> {
let mut result = vec![];
let search = search.to_lowercase();
for line in content.lines() {
if line.to_lowercase().contains(&search) {
result.push(line);
}
}
result
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn case_sensitive() {
let search = "rust";
let content = "\
nice. rust
I'm hboot.
hello world.
Rust
";
assert_eq!(vec!["nice. rust"], find(search, content));
}
#[test]
fn case_insensitive() {
let search = "rust";
let content = "\
nice. rust
I'm hboot.
hello world.
Rust
";
assert_eq!(
vec!["nice. rust", "Rust"],
find_insensitive(search, content)
);
}
}