From 528164d6e69234a3f4cc3a527e9d8844c07ebe85 Mon Sep 17 00:00:00 2001 From: Charlie Ozinga Date: Thu, 11 May 2017 23:29:41 -0600 Subject: [PATCH] Fix nested arrays, emit compact in-line --- parser/src/emitter.rs | 112 +++++++++++++++++++++++--------------- parser/tests/spec_test.rs | 2 + 2 files changed, 70 insertions(+), 44 deletions(-) diff --git a/parser/src/emitter.rs b/parser/src/emitter.rs index ba0bf7e..065d46b 100644 --- a/parser/src/emitter.rs +++ b/parser/src/emitter.rs @@ -3,6 +3,15 @@ use std::convert::From; use std::error::Error; use yaml::{Hash, Yaml}; +/// If the emitter should output in 'compact inline notation' form, as +/// described for block +/// [sequences](http://www.yaml.org/spec/1.2/spec.html#id2797382) and +/// [mappings](http://www.yaml.org/spec/1.2/spec.html#id2798057). In +/// this form, blocks cannot have any properties (such as anchors or +/// tags), which should be OK, because this emitter doesn't (currently) +/// emit those anyways. +pub const COMPACT: bool = true; + #[derive(Copy, Clone, Debug)] pub enum EmitError { FmtError(fmt::Error), @@ -174,16 +183,16 @@ impl<'a> YamlEmitter<'a> { if v.is_empty() { try!(write!(self.writer, "[]")); } else { + self.level += 1; for (cnt, x) in v.iter().enumerate() { if cnt > 0 { try!(write!(self.writer, "\n")); + try!(self.write_indent()); } - try!(self.write_indent()); - self.level += 1; - try!(write!(self.writer, "- ")); - try!(self.emit_node(x)); - self.level -= 1; + try!(write!(self.writer, "-")); + try!(self.emit_val(true, x)); } + self.level -= 1; } Ok(()) } @@ -203,51 +212,57 @@ impl<'a> YamlEmitter<'a> { try!(self.write_indent()); } if complex_key { - try!(write!(self.writer, "? ")); - self.level += 1; - try!(self.emit_node(k)); - self.level -= 1; + try!(write!(self.writer, "?")); + try!(self.emit_val(true, k)); try!(write!(self.writer, "\n")); try!(self.write_indent()); + try!(write!(self.writer, ":")); + try!(self.emit_val(true, v)); } else { try!(self.emit_node(k)); - } - match *v { - Yaml::Array(ref v) => { - if complex_key { self.level += 1; } - if v.is_empty() { - try!(write!(self.writer, ": ")); - } else { - try!(write!(self.writer, ":\n")); - } - try!(self.emit_array(v)); - if complex_key { self.level -= 1; } - } - Yaml::Hash(ref h) => { - if complex_key { self.level += 1; } - if h.is_empty() { - try!(write!(self.writer, ": ")); - } else { - try!(write!(self.writer, ":\n")); - self.level += 1; - try!(self.write_indent()); - self.level -= 1; - } - try!(self.emit_hash(h)); - if complex_key { self.level -= 1; } - } - _ => { - if complex_key { self.level += 1; } - try!(write!(self.writer, ": ")); - try!(self.emit_node(v)); - if complex_key { self.level -= 1; } - } + try!(write!(self.writer, ":")); + try!(self.emit_val(false, v)); } } self.level -= 1; } Ok(()) } + + /// Emit a yaml as a hash or array value: i.e., which should appear + /// following a ":" or "-", either after a space, or on a new line. + /// If `inline` is true, then the preceeding characters are distinct + /// and short enough to respects the COMPACT constant. + fn emit_val(&mut self, inline: bool, val: &Yaml) -> EmitResult { + match *val { + Yaml::Array(ref v) => { + if (inline && COMPACT) || v.is_empty() { + try!(write!(self.writer, " ")); + } else { + try!(write!(self.writer, "\n")); + self.level += 1; + try!(self.write_indent()); + self.level -= 1; + } + self.emit_array(v) + }, + Yaml::Hash(ref h) => { + if (inline && COMPACT) || h.is_empty() { + try!(write!(self.writer, " ")); + } else { + try!(write!(self.writer, "\n")); + self.level += 1; + try!(self.write_indent()); + self.level -= 1; + } + self.emit_hash(h) + }, + _ => { + try!(write!(self.writer, " ")); + self.emit_node(val) + } + } + } } /// Check if the string requires quoting. @@ -406,15 +421,24 @@ y: string with spaces"#; #[test] fn test_empty_and_nested() { - let s = r#"--- + let s = if COMPACT { r#"--- a: b: c: hello d: {} e: -- f -- g -- h: []"#; + - f + - g + - h: []"# } else { r#"--- +a: + b: + c: hello + d: {} +e: + - f + - g + - + h: []"# }; let docs = YamlLoader::load_from_str(&s).unwrap(); let doc = &docs[0]; diff --git a/parser/tests/spec_test.rs b/parser/tests/spec_test.rs index 3e5d043..1896d17 100644 --- a/parser/tests/spec_test.rs +++ b/parser/tests/spec_test.rs @@ -136,6 +136,8 @@ fn test_mapvec_legal() { // - 6 // ``` + println!("{}", out_str); + YamlLoader::load_from_str(&out_str).unwrap(); }