diff options
author | Lars Wirzenius <liw@liw.fi> | 2019-09-19 09:17:22 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2019-09-19 09:52:35 +0300 |
commit | a3559c97d9de83c8841354fbdf3c5a38fa25f046 (patch) | |
tree | 58897c272a5b0716721e5ca4bce3e9d3f86d64d3 /src | |
parent | 446e0f28bdd640f26def54ad069baa1c9cc9ec41 (diff) | |
download | roadmap-a3559c97d9de83c8841354fbdf3c5a38fa25f046.tar.gz |
Change: implement Roadmap::as_dot
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 47 |
1 files changed, 36 insertions, 11 deletions
@@ -12,22 +12,28 @@ //! # use roadmap::Step; //! # fn main() -> std::result::Result<(), Box<dyn std::error::Error>> { //! let mut r = roadmap::Roadmap::new(); -//! assert_eq!(r.steps().len(), 0); +//! assert_eq!(r.step_names().len(), 0); //! -//! let endgoal = roadmap::Step::new("endgoal", "the end goal"); +//! let mut endgoal = roadmap::Step::new("endgoal", "the end goal"); +//! endgoal.add_dependency("first"); //! assert_eq!(endgoal.name(), "endgoal"); //! assert_eq!(endgoal.label(), "the end goal"); -//! r.add_step(&endgoal)?; -//! assert_eq!(r.steps().len(), 1); +//! assert_eq!(endgoal.dependencies(), vec!["first"]); //! //! let first = roadmap::Step::new("first", "the first step"); +//! +//! +//! r.add_step(&endgoal)?; +//! assert_eq!(r.step_names().len(), 1); //! r.add_step(&first)?; -//! assert_eq!(r.steps().len(), 2); +//! assert_eq!(r.step_names().len(), 2); //! -//! if let Some(step) = r.get_step("endgoal") { -//! step.add_dependency("first"); -//! assert_eq!(endgoal.dependencies(), vec!["first"]); +//! assert_eq!(r.as_dot()?, r#"digraph "roadmap" { +//! endgoal [label="the end goal"]; +//! first [label="the first step"]; +//! first -> endgoal; //! } +//! "#.to_string()); //! # Ok(()) //! # } //! ``` @@ -61,7 +67,7 @@ impl Step { } /// Return vector of names of dependencies for a step. - pub fn dependencies(self) -> Vec<String> { + pub fn dependencies(&self) -> Vec<String> { self.depends.clone() } @@ -88,7 +94,7 @@ impl Roadmap { } /// Return list of step names. - pub fn steps<'a>(&'a self) -> Vec<&'a str> { + pub fn step_names<'a>(&'a self) -> Vec<&'a str> { let mut names = vec![]; for step in self.steps.iter() { names.push(step.name()); @@ -112,6 +118,25 @@ impl Roadmap { /// is the textual representation, and the caller needs to use the /// Graphviz dot(1) tool to create an image from it. pub fn as_dot(self) -> Result<String, Box<dyn std::error::Error>> { - Ok("".to_string()) + let labels = self.steps.iter().map(|step| + format!("{} [label=\"{}\"];\n", step.name(), step.label()) + ); + + let mut dot = String::new(); + dot.push_str("digraph \"roadmap\" {\n"); + for line in labels { + dot.push_str(&line); + } + + for step in self.steps.iter() { + for dep in step.dependencies() { + let line = format!("{} -> {};\n", dep, step.name()); + dot.push_str(&line); + } + } + + dot.push_str("}\n"); + + Ok(dot) } } |