1use std::fmt::Display;
6
7pub struct PrintTree {
10 level: u32,
12
13 queued_item: Option<String>,
16}
17
18impl PrintTree {
19 pub fn new(title: impl Display) -> PrintTree {
20 println!("\u{250c} {title}");
21 PrintTree {
22 level: 1,
23 queued_item: None,
24 }
25 }
26
27 pub fn new_level(&mut self, queued_title: String) {
29 self.flush_queued_item("\u{251C}\u{2500}");
30
31 self.print_level_prefix();
32
33 let items: Vec<&str> = queued_title.split('\n').collect();
34 println!("\u{251C}\u{2500} {}", items[0]);
35 for i in 1..items.len() {
36 self.print_level_child_indentation();
37 print!("{}", items[i]);
38 if i < items.len() {
39 println!();
40 }
41 }
42
43 self.level += 1;
44 }
45
46 pub fn end_level(&mut self) {
48 self.flush_queued_item("\u{2514}\u{2500}");
49 self.level -= 1;
50 }
51
52 pub fn add_item(&mut self, text: String) {
54 self.flush_queued_item("\u{251C}\u{2500}");
55 self.queued_item = Some(text);
56 }
57
58 fn print_level_prefix(&self) {
59 for _ in 0..self.level {
60 print!("\u{2502} ");
61 }
62 }
63
64 fn print_level_child_indentation(&self) {
65 for _ in 0..(self.level + 1) {
66 print!("\u{2502} ");
67 }
68 print!("{}", " ".repeat(7));
69 }
70
71 fn flush_queued_item(&mut self, prefix: &str) {
72 if let Some(queued_item) = self.queued_item.take() {
73 self.print_level_prefix();
74 let items: Vec<&str> = queued_item.split('\n').collect();
75 println!("{} {}", prefix, items[0]);
76 for i in 1..items.len() {
77 self.print_level_child_indentation();
78 print!("{}", items[i]);
79 if i < items.len() {
80 println!();
81 }
82 }
83 }
84 }
85}
86
87impl Drop for PrintTree {
88 fn drop(&mut self) {
89 self.flush_queued_item("\u{2514}\u{2500}");
90 }
91}