summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2019-10-05 10:49:05 +0300
committerLars Wirzenius <liw@liw.fi>2019-10-05 10:49:05 +0300
commit5122f63f07f2893abdad11937e9842c7d38baffa (patch)
tree4c0e39fb272b0bd7eb0fa57fbdebcf6abbdee8ea
parent94a1206617cf3421ae859a67964244d7bec073b0 (diff)
downloadroadmap-5122f63f07f2893abdad11937e9842c7d38baffa.tar.gz
Change: set README file type via Emacs mode line
-rw-r--r--README2
-rw-r--r--src/#parser.rs#170
l---------src/.#parser.rs1
3 files changed, 2 insertions, 171 deletions
diff --git a/README b/README
index 438c321..e347562 100644
--- a/README
+++ b/README
@@ -1,3 +1,5 @@
+-*-markdown-*-
+
Produce directed acyclic graph representations of a project roadmap.
The idea is to show the steps needed to reach a goal, and the order
they need to be taken, but ignore due dates and other irrelevant
diff --git a/src/#parser.rs# b/src/#parser.rs#
deleted file mode 100644
index 32cdd73..0000000
--- a/src/#parser.rs#
+++ /dev/null
@@ -1,170 +0,0 @@
-use serde_yaml;
-use serde_yaml::Value;
-use std::collections::HashMap
-pub use crate::Roadmap;
-pub use crate::RoadmapResult;
-pub use crate::Status;
-pub use crate::Step;
-
-/// Create a new roadmap from a textual YAML representation.
-pub fn from_yaml(yaml: &str) -> RoadmapResult<Roadmap> {
- let mut roadmap = Roadmap::new();
- let map: HashMap<String, serde_yaml::Value> = serde_yaml::from_str(yaml)?;
-
- for (name, value) in map {
- let step = step_from_value(&name, &value)?;
- roadmap.add_step(step);
- }
-
- roadmap.validate()?;
- Ok(roadmap)
-}
-
-// Convert a Value into a Step, if possible.
-fn step_from_value(name: &str, value: &Value) -> RoadmapResult<Step> {
- match value {
- Value::Mapping(_) => {
- let label = parse_label(&value);
- let status = parse_status(&value)?;
-
- let mut step = Step::new(name, label);
- step.set_status(status);
-
- for depname in parse_depends(&value)?.iter() {
- step.add_dependency(depname);
- }
-
- Ok(step)
- }
- _ => Err("step is not a mapping".to_string().into()),
- }
-}
-
-// Get a sequence of depenencies.
-fn parse_depends(map: &Value) -> RoadmapResult<Vec<&str>> {
- let key_name = "depends";
- let key = Value::String(key_name.to_string());
- let mut depends: Vec<&str> = vec![];
- let need_list_of_names = format!("'depends' must be a list of step names");
-
- match map.get(&key) {
- None => (),
- Some(Value::Sequence(deps)) => {
- for depname in deps.iter() {
- match depname {
- Value::String(depname) => depends.push(depname),
- _ => return Err(need_list_of_names.into()),
- }
- }
- }
- _ => return Err(need_list_of_names.into()),
- }
-
- Ok(depends)
-}
-
-// Get label string from a Mapping element, or empty string.
-fn parse_label(map: &Value) -> &str {
- parse_string("label", map)
-}
-
-// Get status string from a Mapping element. Default to unknown status.
-fn parse_status<'a>(map: &'a Value) -> RoadmapResult<Status> {
- let text = parse_string("status", map);
- match Status::from_text(text) {
- Some(status) => Ok(status),
- _ => Err(format!("unknown status: {:?}", text).into()),
- }
-}
-
-// Get string value from a Mapping field, or empty string if field
-// isn't there.
-fn parse_string<'a>(key_name: &str, map: &'a Value) -> &'a str {
- let key = Value::String(key_name.to_string());
- match map.get(&key) {
- Some(Value::String(s)) => s,
- _ => "",
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::from_yaml;
-
- #[test]
- fn yaml_is_empty() {
- let r = from_yaml("");
- match r {
- Ok(_) => panic!("expected a parse error"),
- _ => (),
- }
- }
-
- #[test]
- fn yaml_is_list() {
- let r = from_yaml("[]");
- match r {
- Ok(_) => panic!("expected a parse error"),
- _ => (),
- }
- }
-
- #[test]
- fn yaml_map_entries_not_maps() {
- let r = from_yaml("foo: []");
- match r {
- Ok(_) => panic!("expected a parse error"),
- _ => (),
- }
- }
-
- #[test]
- fn yaml_unknown_dep() {
- let r = from_yaml("foo: {depends: [bar]}");
- match r {
- Ok(_) => panic!("expected a parse error"),
- _ => (),
- }
- }
-
- #[test]
- fn yaml_unknown_status() {
- let r = from_yaml(r#"foo: {status: "bar"}"#);
- match r {
- Ok(_) => panic!("expected a parse error"),
- _ => (),
- }
- }
-
- #[test]
- fn yaml_happy() {
- let roadmap = from_yaml(
- "
-first:
- label: the first step
-second:
- label: the second step
- depends:
- - first
-",
- )
- .unwrap();
-
- let names: Vec<&str> = roadmap.step_names().collect();
- assert_eq!(names.len(), 2);
- assert!(names.contains(&"first"));
- assert!(names.contains(&"second"));
-
- let first = roadmap.get_step("first").unwrap();
- assert_eq!(first.name(), "first");
- assert_eq!(first.label(), "the first step");
- let deps: Vec<&str> = first.dependencies().collect();
- assert_eq!(deps.len(), 0);
-
- let second = roadmap.get_step("second").unwrap();
- assert_eq!(second.name(), "second");
- assert_eq!(second.label(), "the second step");
- let deps: Vec<&str> = second.dependencies().collect();
- assert_eq!(deps, vec!["first"]);
- }
-}
diff --git a/src/.#parser.rs b/src/.#parser.rs
deleted file mode 120000
index 5d257a5..0000000
--- a/src/.#parser.rs
+++ /dev/null
@@ -1 +0,0 @@
-liw@exolobe1.5169:1568966750 \ No newline at end of file