use std::io::Write;
use std::process::Command;
use tempfile::NamedTempFile;
#[derive(Clone)]
pub enum DotOutputT {
Browser,
SVG(String),
XWindow,
}
pub trait ConvertibleToDotOutputT {
fn to_dot_output_t(self) -> DotOutputT;
}
impl ConvertibleToDotOutputT for DotOutputT {
fn to_dot_output_t(self) -> DotOutputT {
self
}
}
impl ConvertibleToDotOutputT for &str {
fn to_dot_output_t(self) -> DotOutputT {
match self {
"xwindow" => DotOutputT::XWindow,
"browser" => DotOutputT::Browser,
x if x.ends_with(".svg") => DotOutputT::SVG(x[..x.len() - 4].to_string()),
_ => panic!("Can be one of xwindow or browser"),
}
}
}
pub fn show_dot<T1: ToString, T2: ConvertibleToDotOutputT>(dot_code: T1, output_to: T2) {
let mut fp = NamedTempFile::new().unwrap();
writeln!(fp, "{}", dot_code.to_string()).unwrap();
let (_file, fpath) = fp.keep().unwrap();
match output_to.to_dot_output_t() {
DotOutputT::XWindow => {
let output = Command::new("dot").arg("-Tx11")
.arg(fpath.to_str().unwrap())
.output()
.expect("could not run 'dot'");
if !output.status.success() {
panic!("dot exited with error: {}",
String::from_utf8_lossy(&output.stderr));
}
}
DotOutputT::SVG(fname) => {
let output = Command::new("dot").arg("-Tsvg")
.arg(fpath.to_str().unwrap())
.arg("-o")
.arg(fname.as_str())
.output()
.expect("could not run 'dot'");
if !output.status.success() {
panic!("dot exited with error: {}",
String::from_utf8_lossy(&output.stderr));
}
}
DotOutputT::Browser => unimplemented!("Browser output not yet supported"),
}
}