ralph/template/variables/context.rs
1//! Purpose: Define shared data types for template-variable validation and
2//! substitution.
3//!
4//! Responsibilities:
5//! - Represent substitution context derived from targets and git state.
6//! - Represent validation warnings and aggregate validation results.
7//!
8//! Scope:
9//! - Data modeling only; no template scanning, substitution, or git probing.
10//!
11//! Usage:
12//! - Used by the `validate`, `detect`, and `substitute` companions and their
13//! callers through re-exports from `template::variables`.
14//!
15//! Invariants/Assumptions:
16//! - Warning display text is part of the user-facing contract.
17//! - Validation helpers preserve existing warning semantics and ordering.
18
19/// Context for template variable substitution.
20#[derive(Debug, Clone, Default)]
21pub struct TemplateContext {
22 /// The target file/path provided by user.
23 pub target: Option<String>,
24 /// Module name derived from target (e.g., "src/cli/task.rs" -> "cli::task").
25 pub module: Option<String>,
26 /// Filename only (e.g., "src/cli/task.rs" -> "task.rs").
27 pub file: Option<String>,
28 /// Current git branch name.
29 pub branch: Option<String>,
30}
31
32/// Warning types for template validation.
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub enum TemplateWarning {
35 /// Unknown template variable found (variable name, optional field context).
36 UnknownVariable { name: String, field: Option<String> },
37 /// Git branch detection failed (error message).
38 GitBranchDetectionFailed { error: String },
39}
40
41impl std::fmt::Display for TemplateWarning {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 match self {
44 TemplateWarning::UnknownVariable { name, field: None } => {
45 write!(f, "Unknown template variable: {{{{{}}}}}", name)
46 }
47 TemplateWarning::UnknownVariable {
48 name,
49 field: Some(field),
50 } => {
51 write!(
52 f,
53 "Unknown template variable in {}: {{{{{}}}}}",
54 field, name
55 )
56 }
57 TemplateWarning::GitBranchDetectionFailed { error } => {
58 write!(f, "Git branch detection failed: {}", error)
59 }
60 }
61 }
62}
63
64/// Result of template validation.
65#[derive(Debug, Clone, Default)]
66pub struct TemplateValidation {
67 /// Warnings collected during validation.
68 pub warnings: Vec<TemplateWarning>,
69 /// Whether the template uses {{branch}} variable.
70 pub uses_branch: bool,
71}
72
73impl TemplateValidation {
74 /// Check if there are any unknown variable warnings.
75 pub fn has_unknown_variables(&self) -> bool {
76 self.warnings
77 .iter()
78 .any(|w| matches!(w, TemplateWarning::UnknownVariable { .. }))
79 }
80
81 /// Get list of unknown variable names (deduplicated).
82 pub fn unknown_variable_names(&self) -> Vec<String> {
83 let mut names: Vec<String> = self
84 .warnings
85 .iter()
86 .filter_map(|w| match w {
87 TemplateWarning::UnknownVariable { name, .. } => Some(name.clone()),
88 _ => None,
89 })
90 .collect();
91 names.sort();
92 names.dedup();
93 names
94 }
95}