wowlab_docgen_cli/context/collectors/
env_vars.rs1use serde::Serialize;
2
3use super::{ContextEntry, to_value};
4use crate::RenderCtx;
5
6#[derive(Debug, Serialize)]
8pub struct EnvVar {
9 pub name: String,
10 pub default: String,
11}
12
13#[must_use]
15pub fn collect(ctx: &RenderCtx<'_>) -> Vec<ContextEntry> {
16 let env_path = ctx.dir.join(".env.example");
17 let Some(content) = ctx.workspace.contents(&env_path) else {
18 return Vec::new();
19 };
20
21 let vars: Vec<EnvVar> = content
22 .lines()
23 .filter(|line| {
24 let trimmed = line.trim();
25
26 !trimmed.is_empty() && !trimmed.starts_with('#')
27 })
28 .filter_map(|line| {
29 let (name, default) = if let Some(eq) = line.find('=') {
30 let key = line[..eq].trim().to_string();
32 let val = line[eq + 1..].trim().to_string();
34
35 (key, val)
36 } else {
37 return None;
38 };
39
40 if name.is_empty() {
41 return None;
42 }
43
44 Some(EnvVar { name, default })
45 })
46 .collect();
47
48 if vars.is_empty() {
49 return Vec::new();
50 }
51
52 vec![("env_vars", to_value(&vars))]
53}
54
55#[cfg(test)]
56mod tests {
57 use googletest::prelude::*;
58
59 use super::*;
60
61 fn parse_lines(input: &str) -> Vec<EnvVar> {
62 input
63 .lines()
64 .filter(|line| {
65 let trimmed = line.trim();
66
67 !trimmed.is_empty() && !trimmed.starts_with('#')
68 })
69 .filter_map(|line| {
70 let (name, default) = if let Some(eq) = line.find('=') {
71 (
72 line[..eq].trim().to_string(),
73 line[eq + 1..].trim().to_string(),
74 )
75 } else {
76 return None;
77 };
78
79 if name.is_empty() {
80 return None;
81 }
82
83 Some(EnvVar { name, default })
84 })
85 .collect()
86 }
87
88 #[gtest]
89 fn parses_key_value_pairs() -> Result<()> {
90 let input = "FOO=bar\nBAZ=\n# comment\n\nQUX=hello world";
91 let vars = parse_lines(input);
92
93 verify_that!(vars, len(eq(3)))?;
94 verify_eq!(vars[0].name, "FOO")?;
95 verify_eq!(vars[0].default, "bar")?;
96 verify_eq!(vars[1].name, "BAZ")?;
97 verify_eq!(vars[1].default, "")?;
98 verify_eq!(vars[2].name, "QUX")?;
99
100 verify_eq!(vars[2].default, "hello world")
101 }
102
103 #[gtest]
104 fn ignores_comments_and_blanks() -> Result<()> {
105 let input = "# this is a comment\n\n # indented comment\nKEY=val";
106 let vars = parse_lines(input);
107
108 verify_that!(vars, len(eq(1)))?;
109
110 verify_eq!(vars[0].name, "KEY")
111 }
112
113 #[gtest]
114 fn skips_lines_without_equals() -> Result<()> {
115 let input = "NO_EQUALS\nGOOD=yes";
116 let vars = parse_lines(input);
117
118 verify_that!(vars, len(eq(1)))?;
119
120 verify_eq!(vars[0].name, "GOOD")
121 }
122}