Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucas chen committed Jun 27, 2024
0 parents commit ea28770
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "minigrep"
version = "0.1.0"
edition = "2021"

[dependencies]
16 changes: 16 additions & 0 deletions poem.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
I'm nobody! Who are you?
我啥也不是,你呢?
Are you nobody, too?
牛逼如你也是无名之辈吗?
Then there's a pair of us - don't tell!
那我们就是天生一对,嘘!别说话!
They'd banish us, you know.
你知道,我们不属于这里。
How dreary to be somebody!
因为这里属于没劲的大人物!
How public, like a frog
他们就像青蛙一样呱噪,
To tell your name the livelong day
成天将自己的大名
To an admiring bog!
传遍整个无聊的沼泽!
102 changes: 102 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use std::{env, error::Error, fs};

// 命令行参数
// 聚合配置变量到结构体中
pub struct Config<'a> {
query: &'a str,
file_path: &'a str,
ignore_case: bool,
}

impl<'a> Config<'a> {
pub fn build(args: &'a [String]) -> Result<Self, &'static str> {
if args.len() < 3 {
return Err("not enough arguments");
}

let query = &args[1];
let file_path = &args[2];
let ignore_case = env::var("IGNORE_CASE").is_ok();

Ok(Self {
query,
file_path,
ignore_case,
})
}
}

pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
let contents = fs::read_to_string(config.file_path)?;

let iter = if config.ignore_case {
search_case_insensitive(config.query, &contents)
} else {
search(config.query, &contents)
};

iter.into_iter().for_each(|line| println!("{line}"));

Ok(())
}

pub fn search<'a>(query: &'a str, contents: &'a str) -> Vec<&'a str> {
contents
.lines()
.filter(|line| line.contains(query))
.collect()
}

pub fn search_case_insensitive<'a>(query: &'a str, contents: &'a str) -> Vec<&'a str> {
let query = query.to_lowercase();
contents
.lines()
.filter(|line| line.to_lowercase().contains(&query))
.collect()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn one_result() {
let query = "duct";
let contents = "\
Rust:
safe, fast, productive.
Pick three.";

assert_eq!(vec!["safe, fast, productive."], search(query, contents));
}

// 大小写敏感的测试用例
#[test]
fn case_sensitive() {
let query = "duct";
let contents = "\
Rust:
safe, fast, productive.
Pick three.
Duct tape.";

assert_eq!(vec!["safe, fast, productive."], search(query, contents));
}

// 大小写不敏感的测试用例
#[test]
fn case_insensitive() {
let query = "rUsT";
let contents = "\
Rust:
safe, fast, productive.
Pick three.
Trust me.
";

assert_eq!(
vec!["Rust:", "Trust me."],
search_case_insensitive(query, contents)
);
}
}
15 changes: 15 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use minigrep::{Config, run};
use std::env;

fn main() {
let args: Vec<String> = env::args().collect();
let config = Config::build(&args).unwrap_or_else(|err| {
println!("Problem parse arguments: {err}");
std::process::exit(1);
});

if let Err(err) = run(config) {
eprintln!("Application error: {err}");
std::process::exit(1);
}
}

0 comments on commit ea28770

Please sign in to comment.