acp/vars/
resolver.rs

1//! @acp:module "Variable Resolver"
2//! @acp:summary "Resolves variable references and provides lookup functionality"
3//! @acp:domain cli
4//! @acp:layer service
5
6use regex::Regex;
7use std::collections::HashMap;
8
9use super::{VarEntry, VarType, VarsFile};
10
11/// @acp:summary "Resolves variable references from a vars file"
12pub struct VarResolver {
13    vars: HashMap<String, VarEntry>,
14    var_pattern: Regex,
15}
16
17impl VarResolver {
18    /// Create a new resolver from a vars file
19    pub fn new(vars_file: VarsFile) -> Self {
20        Self {
21            vars: vars_file.variables,
22            var_pattern: Regex::new(r"\$([A-Z][A-Z0-9_]+)(?:\.(\w+))?").unwrap(),
23        }
24    }
25
26    /// Get a variable by name
27    pub fn get(&self, name: &str) -> Option<&VarEntry> {
28        self.vars.get(name)
29    }
30
31    /// Find all variable references in text
32    pub fn find_references(&self, text: &str) -> Vec<VarReference> {
33        self.var_pattern
34            .captures_iter(text)
35            .map(|cap| VarReference {
36                full_match: cap.get(0).unwrap().as_str().to_string(),
37                name: cap.get(1).unwrap().as_str().to_string(),
38                modifier: cap.get(2).map(|m| m.as_str().to_string()),
39                start: cap.get(0).unwrap().start(),
40                end: cap.get(0).unwrap().end(),
41            })
42            .collect()
43    }
44
45    /// Get variables by type
46    pub fn by_type(&self, var_type: VarType) -> Vec<&VarEntry> {
47        self.vars
48            .values()
49            .filter(|v| v.var_type == var_type)
50            .collect()
51    }
52
53    /// Search variables by query string
54    pub fn search(&self, query: &str) -> Vec<&VarEntry> {
55        let q = query.to_lowercase();
56        self.vars
57            .values()
58            .filter(|v| {
59                v.value.to_lowercase().contains(&q)
60                    || v.description
61                        .as_ref()
62                        .map(|s| s.to_lowercase().contains(&q))
63                        .unwrap_or(false)
64            })
65            .collect()
66    }
67}
68
69/// @acp:summary "A parsed variable reference from text"
70#[derive(Debug, Clone)]
71pub struct VarReference {
72    pub full_match: String,
73    pub name: String,
74    pub modifier: Option<String>,
75    pub start: usize,
76    pub end: usize,
77}