| extern crate pretty; | |
| use pretty::{BoxAllocator, DocAllocator, DocBuilder}; | |
| use std::io; | |
| use std::str; | |
| #[derive(Clone, Debug)] | |
| pub struct Forest<'a>(&'a [Tree<'a>]); | |
| impl<'a> Forest<'a> { | |
| fn forest(forest: &'a [Tree<'a>]) -> Forest<'a> { | |
| Forest(forest) | |
| } | |
| fn nil() -> Forest<'a> { | |
| Forest(&[]) | |
| } | |
| fn bracket<'b, D, A>(&'b self, allocator: &'b D) -> DocBuilder<'b, D, A> | |
| where | |
| D: DocAllocator<'b, A>, | |
| D::Doc: Clone, | |
| A: Clone, | |
| { | |
| if (self.0).len() == 0 { | |
| allocator.nil() | |
| } else { | |
| allocator | |
| .text("[") | |
| .append(allocator.newline().append(self.pretty(allocator)).nest(2)) | |
| .append(allocator.newline()) | |
| .append(allocator.text("]")) | |
| } | |
| } | |
| fn pretty<'b, D, A>(&'b self, allocator: &'b D) -> DocBuilder<'b, D, A> | |
| where | |
| D: DocAllocator<'b, A>, | |
| D::Doc: Clone, | |
| A: Clone, | |
| { | |
| let forest = self.0; | |
| let separator = allocator.text(",").append(allocator.newline()); | |
| allocator.intersperse( | |
| forest.into_iter().map(|tree| tree.pretty(allocator)), | |
| separator, | |
| ) | |
| } | |
| } | |
| #[derive(Clone, Debug)] | |
| pub struct Tree<'a> { | |
| node: String, | |
| forest: Forest<'a>, | |
| } | |
| impl<'a> Tree<'a> { | |
| pub fn node(node: &str) -> Tree<'a> { | |
| Tree { | |
| node: node.to_string(), | |
| forest: Forest::nil(), | |
| } | |
| } | |
| pub fn node_with_forest(node: &str, forest: &'a [Tree<'a>]) -> Tree<'a> { | |
| Tree { | |
| node: node.to_string(), | |
| forest: Forest::forest(forest), | |
| } | |
| } | |
| pub fn pretty<'b, D, A>(&'b self, allocator: &'b D) -> DocBuilder<'b, D, A> | |
| where | |
| D: DocAllocator<'b, A>, | |
| D::Doc: Clone, | |
| A: Clone, | |
| { | |
| allocator | |
| .text(&self.node[..]) | |
| .append((self.forest).bracket(allocator)) | |
| .group() | |
| } | |
| } | |
| #[allow(dead_code)] | |
| pub fn main() { | |
| let allocator = BoxAllocator; | |
| let bbbbbbs = [Tree::node("ccc"), Tree::node("dd")]; | |
| let ffffs = [Tree::node("gg"), Tree::node("hhh"), Tree::node("ii")]; | |
| let aaas = [ | |
| Tree::node_with_forest("bbbbbb", &bbbbbbs), | |
| Tree::node("eee"), | |
| Tree::node_with_forest("ffff", &ffffs), | |
| ]; | |
| let example = Tree::node_with_forest("aaaa", &aaas); | |
| let err_msg = "<buffer is not a utf-8 encoded string>"; | |
| // try writing to stdout | |
| { | |
| print!("\nwriting to stdout directly:\n"); | |
| let mut out = io::stdout(); | |
| example.pretty::<_, ()>(&allocator).1.render(70, &mut out) | |
| // try writing to memory | |
| }.and_then(|()| { | |
| print!("\nwriting to string then printing:\n"); | |
| let mut mem = Vec::new(); | |
| example | |
| .pretty::<_, ()>(&allocator) | |
| .1 | |
| .render(70, &mut mem) | |
| // print to console from memory | |
| .map(|()| { | |
| let res = str::from_utf8(&mem).unwrap_or(err_msg); | |
| println!("{}", res) | |
| }) | |
| // print an error if anything failed | |
| }) | |
| .unwrap_or_else(|err| println!("error: {}", err)); | |
| } |