cu29_rendercfg/
rendercfg.rs

1mod config;
2use clap::Parser;
3use config::read_configuration;
4pub use cu29_traits::*;
5use std::io::Cursor;
6use std::io::Write;
7use std::path::PathBuf;
8use std::process::{Command, Stdio};
9use tempfile::Builder;
10
11#[derive(Parser)]
12#[clap(author, version, about, long_about = None)]
13struct Args {
14    /// Config file name
15    #[clap(value_parser)]
16    config: PathBuf,
17    /// Open the SVG in the default system viewer
18    #[clap(long)]
19    open: bool,
20}
21
22/// Render the configuration file to a dot file then convert it to an SVG and optionally opens it with inkscape.
23fn main() -> std::io::Result<()> {
24    // Parse command line arguments
25    let args = Args::parse();
26
27    let config = read_configuration(args.config.to_str().unwrap())
28        .expect("Failed to read configuration file");
29    let mut content = Vec::<u8>::new();
30    {
31        let mut cursor = Cursor::new(&mut content);
32        config.render(&mut cursor, None).unwrap();
33    }
34
35    // Generate SVG from DOT
36    let mut child = Command::new("dot")
37        .arg("-Tsvg")
38        .stdin(Stdio::piped())
39        .stdout(Stdio::piped())
40        .spawn()
41        .expect("Failed to start dot process");
42
43    {
44        let stdin = child.stdin.as_mut().expect("Failed to open stdin");
45        let result = stdin.write_all(&content);
46        if let Err(e) = result {
47            eprintln!("Failed to write to stdin of the dot process: {e}");
48            std::process::exit(1);
49        }
50    }
51
52    let output = child.wait_with_output().expect("Failed to read stdout");
53
54    if !output.status.success() {
55        std::process::exit(1);
56    }
57
58    let graph_svg = output.stdout;
59    if args.open {
60        // Create a temporary file to store the SVG
61        let mut temp_file = Builder::new().suffix(".svg").tempfile()?;
62        temp_file.write_all(graph_svg.as_slice())?;
63
64        // Open the SVG in the default system viewer
65        Command::new("inkscape") // xdg-open fails silently (while it works from a standard bash on the same file :shrug:)
66            .arg(temp_file.path())
67            .status()
68            .expect("failed to open SVG file");
69    } else {
70        // Write the SVG content to a file
71        let mut svg_file = std::fs::File::create("output.svg")?;
72        svg_file.write_all(graph_svg.as_slice())?;
73    }
74    Ok(())
75}