1 use once_cell::sync::Lazy;
2 use std::sync::{Arc, Mutex};
3 
4 #[derive(Debug, Clone)]
5 pub struct TreeSymbols {
6     /// A vertical base of the tree (│)
7     pub continued: &'static str,
8 
9     /// Symbol for joining the first branch in a group (├)
10     pub join_first: &'static str,
11 
12     /// Symbol for joining the last branch in a group (└)
13     pub join_last: &'static str,
14 
15     /// Symbol for joining a branch that is not first or last in its group (├)
16     pub join_inner: &'static str,
17 
18     /// Symbol for joining a branch if it is the only one in its group (├)
19     pub join_only: &'static str,
20 
21     /// A repeated branch token (─)
22     pub branch: &'static str,
23 
24     /// End of a leaf (╼)
25     pub leaf: &'static str,
26 
27     pub multiline_first: Option<&'static str>,
28     pub multiline_continued: Option<&'static str>,
29 }
30 
31 #[derive(Debug, Clone)]
32 pub struct TreeConfig {
33     pub symbols: TreeSymbols,
34 
35     /// Aside from the first branch, `indent` is equal to the number of spaces a child branch is
36     /// shifted from its parent.
37     pub indent: usize,
38 
39     pub show_first_level: bool,
40 }
41 impl TreeSymbols {
new() -> Self42     pub fn new() -> Self {
43         Self {
44             continued: "│",
45             join_first: "├",
46             join_inner: "├",
47             join_last: "└",
48             join_only: "└",
49             branch: "─",
50             leaf: "╼ ",
51             multiline_first: None,
52             multiline_continued: None,
53         }
54     }
with_pipes() -> Self55     pub fn with_pipes() -> Self {
56         Self {
57             continued: "║",
58             join_first: "╠",
59             join_inner: "╠",
60             join_last: "╚",
61             join_only: "╚",
62             branch: "═",
63             leaf: "╼ ",
64             multiline_first: None,
65             multiline_continued: None,
66         }
67     }
with_thick() -> Self68     pub fn with_thick() -> Self {
69         Self {
70             continued: "┃",
71             join_first: "┣",
72             join_inner: "┣",
73             join_last: "┗",
74             join_only: "┗",
75             branch: "━",
76             leaf: "╼ ",
77             multiline_first: None,
78             multiline_continued: None,
79         }
80     }
with_rounded() -> Self81     pub fn with_rounded() -> Self {
82         Self {
83             continued: "│",
84             join_first: "├",
85             join_inner: "├",
86             join_last: "╰",
87             join_only: "╰",
88             branch: "─",
89             leaf: "╼ ",
90             multiline_first: None,
91             multiline_continued: None,
92         }
93     }
with_dashed() -> Self94     pub fn with_dashed() -> Self {
95         Self {
96             continued: "┊",
97             join_first: "┊",
98             join_inner: "┊",
99             join_last: "'",
100             join_only: "'",
101             branch: "╌",
102             leaf: "- ",
103             multiline_first: None,
104             multiline_continued: None,
105         }
106     }
107 
continued(mut self, sym: &'static str) -> Self108     pub fn continued(mut self, sym: &'static str) -> Self {
109         self.continued = sym;
110         self
111     }
join_first(mut self, sym: &'static str) -> Self112     pub fn join_first(mut self, sym: &'static str) -> Self {
113         self.join_first = sym;
114         self
115     }
join_inner(mut self, sym: &'static str) -> Self116     pub fn join_inner(mut self, sym: &'static str) -> Self {
117         self.join_inner = sym;
118         self
119     }
join_last(mut self, sym: &'static str) -> Self120     pub fn join_last(mut self, sym: &'static str) -> Self {
121         self.join_last = sym;
122         self
123     }
join_only(mut self, sym: &'static str) -> Self124     pub fn join_only(mut self, sym: &'static str) -> Self {
125         self.join_only = sym;
126         self
127     }
128 
branch(mut self, sym: &'static str) -> Self129     pub fn branch(mut self, sym: &'static str) -> Self {
130         self.branch = sym;
131         self
132     }
leaf(mut self, sym: &'static str) -> Self133     pub fn leaf(mut self, sym: &'static str) -> Self {
134         self.leaf = sym;
135         self
136     }
multiline_first(mut self, sym: &'static str) -> Self137     pub fn multiline_first(mut self, sym: &'static str) -> Self {
138         self.multiline_first = Some(sym);
139         self
140     }
multiline_continued(mut self, sym: &'static str) -> Self141     pub fn multiline_continued(mut self, sym: &'static str) -> Self {
142         self.multiline_continued = Some(sym);
143         self
144     }
145 }
146 
147 impl TreeConfig {
new() -> Self148     pub fn new() -> Self {
149         Self {
150             symbols: TreeSymbols::new(),
151             indent: 2,
152             show_first_level: false,
153         }
154     }
with_symbols(symbols: TreeSymbols) -> Self155     pub fn with_symbols(symbols: TreeSymbols) -> Self {
156         Self {
157             symbols,
158             indent: 2,
159             show_first_level: false,
160         }
161     }
indent(mut self, x: usize) -> Self162     pub fn indent(mut self, x: usize) -> Self {
163         self.indent = x;
164         self
165     }
show_first_level(mut self) -> Self166     pub fn show_first_level(mut self) -> Self {
167         self.show_first_level = true;
168         self
169     }
hide_first_level(mut self) -> Self170     pub fn hide_first_level(mut self) -> Self {
171         self.show_first_level = false;
172         self
173     }
symbols(mut self, x: TreeSymbols) -> Self174     pub fn symbols(mut self, x: TreeSymbols) -> Self {
175         self.symbols = x;
176         self
177     }
178 }
179 
180 impl Default for TreeSymbols {
default() -> Self181     fn default() -> Self {
182         tree_config_symbols()
183     }
184 }
185 impl Default for TreeConfig {
default() -> Self186     fn default() -> Self {
187         tree_config()
188     }
189 }
190 
191 static DEFAULT_CONFIG: Lazy<Arc<Mutex<TreeConfig>>> =
192     Lazy::new(|| -> Arc<Mutex<TreeConfig>> { Arc::new(Mutex::new(TreeConfig::new())) });
193 
194 /// Set the default tree config
set_tree_config(x: TreeConfig)195 pub fn set_tree_config(x: TreeConfig) {
196     *DEFAULT_CONFIG.lock().unwrap() = x;
197 }
198 
199 /// The default tree config
tree_config() -> TreeConfig200 pub fn tree_config() -> TreeConfig {
201     DEFAULT_CONFIG.lock().unwrap().clone()
202 }
203 
204 /// Set the default tree symbols config
set_tree_config_symbols(x: TreeSymbols)205 pub fn set_tree_config_symbols(x: TreeSymbols) {
206     DEFAULT_CONFIG.lock().unwrap().symbols = x;
207 }
208 
209 /// The default tree symbols config
tree_config_symbols() -> TreeSymbols210 pub fn tree_config_symbols() -> TreeSymbols {
211     DEFAULT_CONFIG.lock().unwrap().symbols.clone()
212 }
213 
214 /// The default tree symbols config
update_tree_config<F: FnMut(&mut TreeConfig)>(mut update: F)215 pub fn update_tree_config<F: FnMut(&mut TreeConfig)>(mut update: F) {
216     let mut x = DEFAULT_CONFIG.lock().unwrap();
217     update(&mut x);
218 }
219 
220 /// The default tree symbols config
update_tree_config_symbols<F: FnMut(&mut TreeSymbols)>(mut update: F)221 pub fn update_tree_config_symbols<F: FnMut(&mut TreeSymbols)>(mut update: F) {
222     let mut x = DEFAULT_CONFIG.lock().unwrap();
223     update(&mut x.symbols);
224 }
225