rgen_cli_lib/cmds/
show.rs1use clap::Args;
2use rgen_core::template::Template;
3use std::path::Path;
4use rgen_utils::error::Result;
5
6#[derive(Args, Debug)]
7pub struct ShowArgs {
8 #[arg(
9 value_name = "TEMPLATE",
10 help = "Template file path or pack_id:template_path"
11 )]
12 pub template: String,
13
14 #[arg(short = 'v', long = "vars", help = "Variables (key=value pairs)")]
15 pub vars: Vec<String>,
16}
17
18pub fn run(args: &ShowArgs) -> Result<()> {
19 let template_path = if args.template.contains(':') {
21 return Err(
23 anyhow::anyhow!("Pack-based templates not yet supported in show command").into(),
24 );
25 } else {
26 Path::new(&args.template)
28 };
29
30 if !template_path.exists() {
31 return Err(anyhow::anyhow!("Template file not found: {}", template_path.display()).into());
32 }
33
34 let content = std::fs::read_to_string(template_path)?;
36 let mut template = Template::parse(&content)?;
37
38 let mut vars = std::collections::BTreeMap::new();
40 for var in &args.vars {
41 if let Some((key, value)) = var.split_once('=') {
42 vars.insert(key.to_string(), value.to_string());
43 }
44 }
45
46 let ctx = tera::Context::from_serialize(&vars)?;
48 let mut pipeline = rgen_core::pipeline::PipelineBuilder::new().build()?;
49
50 render_template_frontmatter(&mut template, &mut pipeline, &ctx)?;
52
53 println!("📄 Template: {}", template_path.display());
55 println!("{}", "=".repeat(50));
56
57 if let Some(to) = &template.front.to {
59 println!("Output: {}", to);
60 }
61
62 if !template.front.vars.is_empty() {
63 println!("\nVariables:");
64 for (key, value) in &template.front.vars {
65 println!(" {}: {}", key, value);
66 }
67 }
68
69 if template.front.inject {
70 println!("\nInjection Mode: Enabled");
71 if template.front.prepend {
72 println!(" Mode: prepend");
73 } else if template.front.append {
74 println!(" Mode: append");
75 } else if let Some(before) = &template.front.before {
76 println!(" Mode: before '{}'", before);
77 } else if let Some(after) = &template.front.after {
78 println!(" Mode: after '{}'", after);
79 } else if let Some(line) = template.front.at_line {
80 println!(" Mode: at line {}", line);
81 }
82
83 if let Some(skip_if) = &template.front.skip_if {
84 println!(" Skip if: {}", skip_if);
85 }
86
87 if template.front.idempotent {
88 println!(" Idempotent: true");
89 }
90
91 if template.front.backup.unwrap_or(false) {
92 println!(" Backup: true");
93 }
94 }
95
96 if !template.front.rdf_inline.is_empty() {
97 println!("\nInline RDF blocks: {}", template.front.rdf_inline.len());
98 }
99
100 if !template.front.rdf.is_empty() {
101 println!("\nRDF files: {}", template.front.rdf.len());
102 for rdf_file in &template.front.rdf {
103 println!(" - {}", rdf_file);
104 }
105 }
106
107 if !template.front.sparql.is_empty() {
108 println!("\nSPARQL queries: {}", template.front.sparql.len());
109 for (name, query) in &template.front.sparql {
110 println!(" {}: {}", name, query);
111 }
112 }
113
114 if let Some(sh_before) = &template.front.sh_before {
115 println!("\nShell hook (before): {}", sh_before);
116 }
117
118 if let Some(sh_after) = &template.front.sh_after {
119 println!("\nShell hook (after): {}", sh_after);
120 }
121
122 println!("\nTemplate Body Preview:");
124 println!("{}", "-".repeat(30));
125 let body_lines: Vec<&str> = template.body.lines().take(10).collect();
126 for line in body_lines {
127 println!("{}", line);
128 }
129 if template.body.lines().count() > 10 {
130 println!("... ({} more lines)", template.body.lines().count() - 10);
131 }
132
133 Ok(())
134}
135
136fn render_template_frontmatter(
138 template: &mut Template, pipeline: &mut rgen_core::pipeline::Pipeline, ctx: &tera::Context,
139) -> Result<()> {
140 template
142 .render_frontmatter(pipeline.tera_mut(), ctx)
143 .map_err(|e| anyhow::anyhow!("Template rendering error: {}", e).into())
144}