Skip to content

Commit

Permalink
add commandline parsing using Clap
Browse files Browse the repository at this point in the history
  • Loading branch information
BramDevlaminck committed Oct 25, 2023
1 parent 2bc69d7 commit 842354c
Show file tree
Hide file tree
Showing 4 changed files with 297 additions and 24 deletions.
216 changes: 216 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
clap = { version = "4.4.7", features = ["derive"] }
103 changes: 80 additions & 23 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,100 @@ mod tree;
mod cursor;
mod searcher;
mod read_only_cursor;

use std::{env, fs, io};
use std::io::Write;
use clap::{Parser, ValueEnum};
use std::{fs, io};
use std::fs::File;
use std::io::{BufRead, Write};
use std::path::Path;
use crate::searcher::Searcher;
use crate::tree::{Node, Tree};
use crate::tree_builder::{UkkonenBuilder, TreeBuilder};

/// Enum that represents the 2 kinds of search that we support
/// - Search until match and return boolean that indicates if there is a match
/// - Search until match, if there is a match search the whole subtree to find all matching proteins
#[derive(ValueEnum, Clone, Debug, PartialEq)]
enum SearchMode {
Match,
AllOccurrences
}

fn main() {
let args: Vec<String> = env::args().collect();
#[derive(Parser, Debug)]
struct Arguments {
#[arg(short, long)]
database_file: String,
#[arg(short, long)]
search_file: Option<String>,
#[arg(long)]
build_only: bool,
#[arg(short, long, value_enum)]
mode: Option<SearchMode>
}

// The output is wrapped in a Result to allow matching on errors
// Returns an Iterator to the Reader of the lines of the file.
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>, {
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}

let file_name = args.get(1).expect("Input file name expected");
/// Executes the kind of search indicated by the commandline arguments
fn handle_search_word(searcher: &mut Searcher, word: String, search_mode: &SearchMode) {
let word = match word.strip_suffix('\n') {
None => word,
Some(stripped) => String::from(stripped)
}.to_uppercase();
if *search_mode == SearchMode::Match {
println!("{}", searcher.search_if_match(word.as_bytes()))
} else {
let results = searcher.search_protein(word.as_bytes());
println!("found {} matches", results.len());
results.iter()
.for_each(|res| println!("* {}", res));
}

let mut data = fs::read_to_string(file_name).expect("Reading input file to build tree from went wrong");
}


fn main() {
let args = Arguments::parse();
let mut data = fs::read_to_string(args.database_file).expect("Reading input file to build tree from went wrong");
data = data.to_uppercase();
data.push('$');

let tree = Tree::new(&data, UkkonenBuilder::new());

let mut searcher = Searcher::new(&tree, data.as_bytes());
// option that only builds the tree, but does not allow for querying (easy for benchmark purposes)
if args.build_only {
return
} else if args.mode.is_none() {
eprintln!("search mode expected!");
std::process::exit(1);
}

loop {
print!("Input your search string: ");
io::stdout().flush().unwrap();
let mut word = String::new();
let mut searcher = Searcher::new(&tree, data.as_bytes());
let mode = &args.mode.unwrap();
if let Some(search_file) = args.search_file {
// File `search_file` must exist in the current path
if let Ok(lines) = read_lines(&search_file) {
for line in lines.into_iter().flatten() {
handle_search_word(&mut searcher, line, mode);
}
} else {
eprintln!("File {} could not be opened!", search_file);
std::process::exit(1);
}
} else {
loop {
print!("Input your search string: ");
io::stdout().flush().unwrap();
let mut word = String::new();

if io::stdin().read_line(&mut word).is_err() {
continue;
if io::stdin().read_line(&mut word).is_err() {
continue;
}
handle_search_word(&mut searcher, word, mode);
}
word = match word.strip_suffix('\n') {
None => word,
Some(stripped) => stripped.to_string()
}.to_uppercase();
// println!("{}", searcher.search_if_match(word.as_bytes()))
let results = searcher.search_protein(word.as_bytes());
println!("found {} matches", results.len());
results.iter()
.for_each(|res| println!("* {}", res));
}
}
1 change: 0 additions & 1 deletion src/searcher.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::thread::current;
use crate::cursor::CursorIterator;
use crate::read_only_cursor::ReadOnlyCursor;
use crate::tree::Tree;
Expand Down

0 comments on commit 842354c

Please sign in to comment.