pmcp_code_mode/
templates.rs1use std::collections::HashMap;
23
24pub const INSTRUCTIONS_URI: &str = "code-mode://instructions";
26
27pub const POLICIES_URI: &str = "code-mode://policies";
29
30#[derive(Debug, Clone, Default)]
32pub struct TemplateContext {
33 vars: HashMap<String, String>,
34}
35
36impl TemplateContext {
37 pub fn new() -> Self {
39 Self::default()
40 }
41
42 pub fn set(mut self, key: &str, value: impl Into<String>) -> Self {
44 self.vars.insert(key.to_string(), value.into());
45 self
46 }
47
48 pub fn set_bool(self, key: &str, value: bool) -> Self {
50 self.set(key, if value { "true" } else { "false" })
51 }
52
53 pub fn set_num(self, key: &str, value: impl std::fmt::Display) -> Self {
55 self.set(key, value.to_string())
56 }
57
58 pub fn render(&self, template: &str) -> String {
64 let mut result = template.to_string();
65 for (key, value) in &self.vars {
66 let placeholder = format!("{{{{{}}}}}", key);
67 result = result.replace(&placeholder, value);
68 }
69 result
70 }
71}
72
73pub fn render(template: &str, ctx: &TemplateContext) -> String {
77 ctx.render(template)
78}
79
80pub fn conditional(condition: bool, content: &str) -> String {
85 if condition {
86 content.to_string()
87 } else {
88 String::new()
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_basic_render() {
98 let ctx = TemplateContext::new()
99 .set("name", "IMDB")
100 .set_num("timeout", 300);
101
102 let result = ctx.render("Server: {{name}}, Timeout: {{timeout}}s");
103 assert_eq!(result, "Server: IMDB, Timeout: 300s");
104 }
105
106 #[test]
107 fn test_unknown_keys_preserved() {
108 let ctx = TemplateContext::new().set("name", "test");
109 let result = ctx.render("{{name}} and {{unknown}}");
110 assert_eq!(result, "test and {{unknown}}");
111 }
112
113 #[test]
114 fn test_conditional() {
115 assert_eq!(conditional(true, "hello"), "hello");
116 assert_eq!(conditional(false, "hello"), "");
117 }
118
119 #[test]
120 fn test_code_examples_not_broken() {
121 let ctx = TemplateContext::new().set("server_name", "Test");
123 let template = r#"{{server_name}} API
124
125```javascript
126const path = `/users/${userId}`;
127```"#;
128 let result = ctx.render(template);
129 assert!(result.contains("Test API"));
130 assert!(result.contains("${userId}"));
131 }
132}