From 2e575857872679ce8ebb1eda9e7b1b30f5dd3139 Mon Sep 17 00:00:00 2001 From: Oliver Hamlet Date: Wed, 3 Oct 2018 18:31:26 +0100 Subject: [PATCH] Add evaluation of active() and many_active() conditions --- src/function/eval.rs | 101 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ 2 files changed, 104 insertions(+) diff --git a/src/function/eval.rs b/src/function/eval.rs index 3917a5e..8cecf59 100644 --- a/src/function/eval.rs +++ b/src/function/eval.rs @@ -92,6 +92,32 @@ fn evaluate_many(state: &State, parent_path: &Path, regex: &Regex) -> Result Result { + Ok(path + .to_str() + .map(|s| state.active_plugins.contains(&s.to_lowercase())) + .unwrap_or(false)) +} + +fn evaluate_active_regex(state: &State, regex: &Regex) -> Result { + Ok(state.active_plugins.iter().any(|p| regex.is_match(p))) +} + +fn evaluate_many_active(state: &State, regex: &Regex) -> Result { + let mut found_one = false; + for active_plugin in &state.active_plugins { + if regex.is_match(&active_plugin) { + if found_one { + return Ok(true); + } else { + found_one = true; + } + } + } + + Ok(false) +} + impl Function { pub fn eval(&self, state: &State) -> Result { // TODO: Handle all variants. @@ -99,7 +125,10 @@ impl Function { match *self { Function::FilePath(ref f) => evaluate_file_path(state, f), Function::FileRegex(ref p, ref r) => evaluate_file_regex(state, p, r), + Function::ActivePath(ref p) => evaluate_active_path(state, p), + Function::ActiveRegex(ref r) => evaluate_active_regex(state, r), Function::Many(ref p, ref r) => evaluate_many(state, p, r), + Function::ManyActive(ref r) => evaluate_many_active(state, r), _ => Ok(false), } } @@ -117,6 +146,10 @@ mod tests { use GameType; fn state>(data_path: T) -> State { + state_with_active_plugins(data_path, &[]) + } + + fn state_with_active_plugins>(data_path: T, active_plugins: &[&str]) -> State { let data_path = data_path.into(); if !data_path.exists() { create_dir(&data_path).unwrap(); @@ -125,6 +158,10 @@ mod tests { State { game_type: GameType::tes4, data_path: data_path, + active_plugins: active_plugins + .into_iter() + .map(|s| s.to_lowercase()) + .collect(), } } @@ -219,6 +256,46 @@ mod tests { assert!(function.eval(&state).unwrap()); } + #[test] + fn function_active_path_eval_should_be_true_if_the_path_is_an_active_plugin() { + let function = Function::ActivePath(PathBuf::from("Blank.esp")); + let state = state_with_active_plugins(".", &["Blank.esp"]); + + assert!(function.eval(&state).unwrap()); + } + + #[test] + fn function_active_path_eval_should_be_case_insensitive() { + let function = Function::ActivePath(PathBuf::from("Blank.esp")); + let state = state_with_active_plugins(".", &["blank.esp"]); + + assert!(function.eval(&state).unwrap()); + } + + #[test] + fn function_active_path_eval_should_be_false_if_the_path_is_not_an_active_plugin() { + let function = Function::ActivePath(PathBuf::from("inactive.esp")); + let state = state_with_active_plugins(".", &["Blank.esp"]); + + assert!(!function.eval(&state).unwrap()); + } + + #[test] + fn function_active_regex_eval_should_be_true_if_the_regex_matches_an_active_plugin() { + let function = Function::ActiveRegex(regex("Blank\\.esp")); + let state = state_with_active_plugins(".", &["Blank.esp"]); + + assert!(function.eval(&state).unwrap()); + } + + #[test] + fn function_active_regex_eval_should_be_false_if_the_regex_does_not_match_an_active_plugin() { + let function = Function::ActiveRegex(regex("inactive\\.esp")); + let state = state_with_active_plugins(".", &["Blank.esp"]); + + assert!(!function.eval(&state).unwrap()); + } + #[test] fn function_many_eval_should_be_false_if_no_directory_entries_match() { let function = Function::Many(PathBuf::from("."), regex("missing")); @@ -256,4 +333,28 @@ mod tests { assert!(function.eval(&state).unwrap()); } + + #[test] + fn function_many_active_eval_should_be_true_if_the_regex_matches_more_than_one_active_plugin() { + let function = Function::ManyActive(regex("Blank.*")); + let state = state_with_active_plugins(".", &["Blank.esp", "Blank.esm"]); + + assert!(function.eval(&state).unwrap()); + } + + #[test] + fn function_many_active_eval_should_be_false_if_one_active_plugin_matches() { + let function = Function::ManyActive(regex("Blank\\.esp")); + let state = state_with_active_plugins(".", &["Blank.esp", "Blank.esm"]); + + assert!(!function.eval(&state).unwrap()); + } + + #[test] + fn function_many_active_eval_should_be_false_if_the_regex_does_not_match_an_active_plugin() { + let function = Function::ManyActive(regex("inactive\\.esp")); + let state = state_with_active_plugins(".", &["Blank.esp", "Blank.esm"]); + + assert!(!function.eval(&state).unwrap()); + } } diff --git a/src/lib.rs b/src/lib.rs index 77c5548..8615f62 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ extern crate regex; #[cfg(test)] extern crate tempfile; +use std::collections::HashSet; use std::io; use std::path::PathBuf; use std::str; @@ -61,6 +62,7 @@ impl GameType { pub struct State { game_type: GameType, data_path: PathBuf, + active_plugins: HashSet, // Lowercased plugin filenames. } // Compound conditions joined by 'or' @@ -160,6 +162,7 @@ mod tests { State { game_type: GameType::tes4, data_path: data_path, + active_plugins: HashSet::new(), } }