use std::sync::LazyLock;
use crate::{
init::find_root,
learn,
pattern::{self, Pattern},
};
pub static PATTERNS: LazyLock<Vec<Pattern>> = LazyLock::new(all_patterns);
pub fn all_patterns() -> Vec<Pattern> {
let mut all_patterns = load_project_patterns();
all_patterns.extend(pattern::load_user_patterns(&learn::patterns_dir()));
all_patterns.extend_from_slice(pattern::builtins());
all_patterns
}
pub fn load_project_patterns() -> Vec<Pattern> {
let Ok(cwd) = std::env::current_dir() else {
return Vec::new();
};
pattern::load_user_patterns(&find_root(&cwd).join(".oo").join("patterns"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn all_patterns_is_nonempty_and_includes_builtins() {
let all = all_patterns();
assert!(
!all.is_empty(),
"the canonical pattern set must not be empty"
);
let builtin_matches: Vec<&str> = pattern::builtins()
.iter()
.map(|p| p.command_match.as_str())
.collect();
assert!(
builtin_matches
.iter()
.any(|bm| { all.iter().any(|p| p.command_match.as_str() == *bm) }),
"all_patterns must include the builtin patterns"
);
}
#[test]
fn all_patterns_precedence_is_project_user_builtin() {
let all = all_patterns();
let user_dir = learn::patterns_dir();
let user_count = if user_dir.exists() {
pattern::load_user_patterns(&user_dir).len()
} else {
0
};
let builtin_count = pattern::builtins().len();
assert!(
all.len() >= user_count + builtin_count,
"all_patterns({}) must contain at least user({}) + builtin({}) entries",
all.len(),
user_count,
builtin_count
);
}
}