use regex::Regex;
use std::sync::OnceLock;
fn skill_ref_regex() -> &'static Regex {
static RE: OnceLock<Regex> = OnceLock::new();
RE.get_or_init(
|| match Regex::new(r"^/([a-z0-9-]+(?:/[a-z0-9-]+)*)(?:\s+(.*))?$") {
Ok(re) => re,
Err(_) => unreachable!("static regex pattern is valid"),
},
)
}
pub fn detect_skill_ref(message: &str) -> Option<(&str, &str)> {
let captures = skill_ref_regex().captures(message)?;
let skill_id = captures.get(1)?.as_str();
let remaining = captures.get(2).map(|m| m.as_str()).unwrap_or("");
Some((skill_id, remaining))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_detect_skill_ref_simple() {
let result = detect_skill_ref("/pdf-processing hello");
assert_eq!(result, Some(("pdf-processing", "hello")));
}
#[test]
fn test_detect_skill_ref_namespaced() {
let result = detect_skill_ref("/extraction/email hello");
assert_eq!(result, Some(("extraction/email", "hello")));
}
#[test]
fn test_detect_skill_ref_deep() {
let result = detect_skill_ref("/a/b/c rest of the message");
assert_eq!(result, Some(("a/b/c", "rest of the message")));
}
#[test]
fn test_detect_skill_ref_none() {
let result = detect_skill_ref("hello world");
assert_eq!(result, None);
}
#[test]
fn test_detect_skill_ref_midsentence() {
let result = detect_skill_ref("use /extraction/email for this");
assert_eq!(result, None); }
#[test]
fn test_detect_skill_ref_only() {
let result = detect_skill_ref("/pdf-processing");
assert_eq!(result, Some(("pdf-processing", "")));
}
#[test]
fn test_strip_skill_ref() {
assert_eq!(
detect_skill_ref("/extraction/email extract stuff"),
Some(("extraction/email", "extract stuff"))
);
}
}