use mapm::problem::Filter;
use mapm::problem::FilterAction;
use colour::*;
use std::fs;
use std::path::Path;
use crate::utils::msg;
pub fn parse_filters(args: &[String]) -> Vec<FilterAction> {
let mut filters: Vec<FilterAction> = Vec::new();
for arg in args {
if &arg[0..1] == "!" {
filters.push(FilterAction::Negative(parse_filter(&arg[1..])));
} else {
filters.push(FilterAction::Positive(parse_filter(arg)));
}
}
filters
}
fn parse_filter(arg: &str) -> Filter {
match arg.find("<=") {
Some(idx) => match arg[idx + 2..].parse::<usize>() {
Ok(val) => Filter::Le {
key: String::from(&arg[0..idx]),
val,
},
Err(_) => {
e_red_ln!("Filter key `{}` was passed with non-integer value `{}`, despite non-equality comparison operator `<=`", &arg[0..idx], &arg[idx+2..]);
quit::with_code(exitcode::USAGE);
}
},
None => match arg.find(">=") {
Some(idx) => match arg[idx + 2..].parse::<usize>() {
Ok(val) => Filter::Ge {
key: String::from(&arg[0..idx]),
val,
},
Err(_) => {
e_red_ln!("Filter key `{}` was passed with non-integer value `{}`, despite non-equality comparison operator `>=`", &arg[0..idx], &arg[idx+2..]);
quit::with_code(exitcode::USAGE);
}
},
None => match arg.find('=') {
Some(idx) => Filter::Eq {
key: String::from(&arg[0..idx]),
val: String::from(&arg[idx + 1..]),
},
None => match arg.find('<') {
Some(idx) => match arg[idx + 1..].parse::<usize>() {
Ok(val) => Filter::Lt {
key: String::from(&arg[0..idx]),
val,
},
Err(_) => {
e_red_ln!("Filter key `{}` was passed with non-integer value `{}`, despite non-equality comparison operator `<`", &arg[0..idx], &arg[idx+1..]);
quit::with_code(exitcode::USAGE);
}
},
None => match arg.find('>') {
Some(idx) => match arg[idx + 1..].parse::<usize>() {
Ok(val) => Filter::Gt {
key: String::from(&arg[0..idx]),
val,
},
Err(_) => {
e_red_ln!("Filter key `{}` was passed with non-integer value `{}`, despite non-equality comparison operator `>`", &arg[0..idx], &arg[idx+1..]);
quit::with_code(exitcode::USAGE);
}
},
None => Filter::Exists {
key: String::from(arg),
},
},
},
},
},
}
}
pub fn filtered_names(filters: &[FilterAction], problem_dir: &Path) -> Vec<String> {
let mut filtered_names: Vec<String> = Vec::new();
for file in fs::read_dir(problem_dir).unwrap() {
if file
.as_ref()
.unwrap()
.path()
.extension()
.and_then(std::ffi::OsStr::to_str)
!= Some("yml")
{
continue;
}
let name = String::from(
file.as_ref()
.unwrap()
.path()
.file_stem()
.unwrap()
.to_str()
.unwrap(),
);
let problem_res = mapm::problem::fetch_problem(&name, problem_dir);
match problem_res {
Ok(problem) => {
if problem.filter(filters).is_some() {
filtered_names.push(name);
}
}
Err(msg) => {
e_yellow_ln!("Source of error is {}.yml", name);
msg::print_err(&msg);
}
}
}
filtered_names
}