1use std::io::Write;
6use std::fmt::Write as FmtWrite;
7
8pub struct PrintTree<W>
11where
12 W: Write
13{
14 level: u32,
16
17 queued_item: Option<String>,
20
21 line_buffer: String,
24
25 sink: W,
27}
28
29pub trait PrintTreePrinter {
33 fn new_level(&mut self, title: String);
34 fn end_level(&mut self);
35 fn add_item(&mut self, text: String);
36}
37
38impl PrintTree<std::io::Sink> {
40 pub fn new(title: &str) -> Self {
41 PrintTree::new_with_sink(title, std::io::sink())
42 }
43}
44
45impl<W> PrintTree<W>
46where
47 W: Write
48{
49 pub fn new_with_sink(title: &str, sink: W) -> Self {
50 let mut result = PrintTree {
51 level: 1,
52 queued_item: None,
53 line_buffer: String::new(),
54 sink,
55 };
56
57 writeln!(result.line_buffer, "\u{250c} {}", title).unwrap();
58 result.flush_line();
59 result
60 }
61
62 fn print_level_prefix(&mut self) {
63 for _ in 0 .. self.level {
64 write!(self.line_buffer, "\u{2502} ").unwrap();
65 }
66 }
67
68 fn flush_queued_item(&mut self, prefix: &str) {
69 if let Some(queued_item) = self.queued_item.take() {
70 self.print_level_prefix();
71 writeln!(self.line_buffer, "{} {}", prefix, queued_item).unwrap();
72 self.flush_line();
73 }
74 }
75
76 fn flush_line(&mut self) {
77 debug!("{}", self.line_buffer);
78 self.sink.write_all(self.line_buffer.as_bytes()).unwrap();
79 self.line_buffer.clear();
80 }
81}
82
83impl<W> PrintTreePrinter for PrintTree<W>
84where
85 W: Write
86{
87 fn new_level(&mut self, title: String) {
89 self.flush_queued_item("\u{251C}\u{2500}");
90
91 self.print_level_prefix();
92 writeln!(self.line_buffer, "\u{251C}\u{2500} {}", title).unwrap();
93 self.flush_line();
94
95 self.level = self.level + 1;
96 }
97
98 fn end_level(&mut self) {
100 self.flush_queued_item("\u{2514}\u{2500}");
101 self.level = self.level - 1;
102 }
103
104 fn add_item(&mut self, text: String) {
106 self.flush_queued_item("\u{251C}\u{2500}");
107 self.queued_item = Some(text);
108 }
109}
110
111impl<W> Drop for PrintTree<W>
112where
113 W: Write
114{
115 fn drop(&mut self) {
116 self.flush_queued_item("\u{9492}\u{9472}");
117 }
118}
119
120pub trait PrintableTree {
121 fn print_with<T: PrintTreePrinter>(&self, pt: &mut T);
122}