1 use std::sync::{Arc, Mutex};
2 
3 #[macro_use]
4 pub mod default;
5 mod internal;
6 pub mod scoped_branch;
7 
8 pub mod defer;
9 mod test;
10 pub mod tree_config;
11 
12 pub use default::default_tree;
13 use once_cell::sync::Lazy;
14 use scoped_branch::ScopedBranch;
15 use std::collections::BTreeMap;
16 use std::fs::File;
17 use std::io::Write;
18 
19 pub use crate::tree_config::*;
20 
21 /// Reference wrapper for `TreeBuilderBase`
22 #[derive(Debug, Clone)]
23 pub struct TreeBuilder(Arc<Mutex<internal::TreeBuilderBase>>);
24 
25 impl TreeBuilder {
26     /// Returns a new `TreeBuilder` with an empty `Tree`.
27     ///
28     /// # Example
29     ///
30     /// ```
31     /// use debug_tree::TreeBuilder;
32     /// let tree = TreeBuilder::new();
33     /// ```
new() -> TreeBuilder34     pub fn new() -> TreeBuilder {
35         TreeBuilder {
36             0: Arc::new(Mutex::new(internal::TreeBuilderBase::new())),
37         }
38     }
39 
40     /// Set the configuration override for displaying trees
41     ///
42     /// # Example
43     ///
44     /// ```
45     /// use debug_tree::{TreeBuilder, add_branch_to, add_leaf_to, TreeSymbols, TreeConfig};
46     /// let tree = TreeBuilder::new();
47     /// {
48     ///     add_branch_to!(tree, "1");
49     ///     {
50     ///         add_branch_to!(tree, "1.1");
51     ///         add_leaf_to!(tree, "1.1.1");
52     ///         add_leaf_to!(tree, "1.1.2");
53     ///     }
54     ///     add_leaf_to!(tree, "1.2");
55     /// }
56     /// add_leaf_to!(tree, "2");
57     /// tree.set_config_override(TreeConfig::new()
58     ///     .show_first_level()
59     ///     .symbols(TreeSymbols::with_rounded()));
60     /// tree.peek_print();
61     /// assert_eq!("\
62     /// ├╼ 1
63     /// │ ├╼ 1.1
64     /// │ │ ├╼ 1.1.1
65     /// │ │ ╰╼ 1.1.2
66     /// │ ╰╼ 1.2
67     /// ╰╼ 2" , &tree.string());
68     /// ```
set_config_override(&self, config: TreeConfig)69     pub fn set_config_override(&self, config: TreeConfig) {
70         let mut lock = self.0.lock().unwrap();
71         lock.set_config_override(Some(config))
72     }
73 
74     /// Remove the configuration override
75     /// The default configuration will be used instead
remove_config_override(&self)76     pub fn remove_config_override(&self) {
77         self.0.lock().unwrap().set_config_override(None);
78     }
79 
80     /// Update the configuration override for displaying trees
81     /// If an override doesn't yet exist, it is created.
82     ///
83     /// # Example
84     ///
85     /// ```
86     /// use debug_tree::{TreeBuilder, add_branch_to, add_leaf_to, TreeSymbols};
87     /// let tree = TreeBuilder::new();
88     /// {
89     ///     add_branch_to!(tree, "1");
90     ///     {
91     ///         add_branch_to!(tree, "1.1");
92     ///         add_leaf_to!(tree, "1.1.1");
93     ///         add_leaf_to!(tree, "1.1.2");
94     ///     }
95     ///     add_leaf_to!(tree, "1.2");
96     /// }
97     /// add_leaf_to!(tree, "2");
98     /// tree.update_config_override(|x|{
99     ///     x.indent = 3;
100     ///     x.symbols = TreeSymbols::with_rounded();
101     ///     x.show_first_level = true;
102     /// });
103     /// tree.peek_print();
104     /// assert_eq!("\
105     /// ├─╼ 1
106     /// │  ├─╼ 1.1
107     /// │  │  ├─╼ 1.1.1
108     /// │  │  ╰─╼ 1.1.2
109     /// │  ╰─╼ 1.2
110     /// ╰─╼ 2" , &tree.string());
111     /// ```
update_config_override<F: Fn(&mut TreeConfig)>(&self, update: F)112     pub fn update_config_override<F: Fn(&mut TreeConfig)>(&self, update: F) {
113         let mut lock = self.0.lock().unwrap();
114         match lock.config_override_mut() {
115             Some(x) => update(x),
116             None => {
117                 let mut x = TreeConfig::default();
118                 update(&mut x);
119                 lock.set_config_override(Some(x));
120             }
121         }
122     }
123 
124     /// Returns the optional configuration override.
get_config_override(&self) -> Option<TreeConfig>125     pub fn get_config_override(&self) -> Option<TreeConfig> {
126         let lock = self.0.lock().unwrap();
127         lock.config_override().clone()
128     }
129 
130     /// Returns whether a configuration override is set.
has_config_override(&self) -> bool131     pub fn has_config_override(&self) -> bool {
132         let lock = self.0.lock().unwrap();
133         lock.config_override().is_some()
134     }
135 
136     /// Adds a new branch with text, `text` and returns a `ScopedBranch`.
137     /// When the returned `ScopedBranch` goes out of scope, (likely the end of the current block),
138     /// or if its `release()` method is called, the tree will step back out of the added branch.
139     ///
140     /// # Arguments
141     /// * `text` - A string slice to use as the newly added branch's text.
142     ///
143     /// # Examples
144     ///
145     /// Exiting branch when end of scope is reached.
146     /// ```
147     /// use debug_tree::TreeBuilder;
148     /// let tree = TreeBuilder::new();
149     /// {
150     ///     let _branch = tree.add_branch("Branch"); // _branch enters scope
151     ///     // tree is now pointed inside new branch.
152     ///     tree.add_leaf("Child of Branch");
153     ///     // _branch leaves scope, tree moves up to parent branch.
154     /// }
155     /// tree.add_leaf("Sibling of Branch");
156     /// assert_eq!("\
157     /// Branch
158     /// └╼ Child of Branch
159     /// Sibling of Branch" , &tree.string());
160     /// ```
161     ///
162     /// Using `release()` before out of scope.
163     /// ```
164     /// use debug_tree::TreeBuilder;
165     /// let tree = TreeBuilder::new();
166     /// {
167     ///     let mut branch = tree.add_branch("Branch"); // branch enters scope
168     ///     // tree is now pointed inside new branch.
169     ///     tree.add_leaf("Child of Branch");
170     ///     branch.release();
171     ///     tree.add_leaf("Sibling of Branch");
172     ///     // branch leaves scope, but no effect because its `release()` method has already been called
173     /// }
174     /// assert_eq!("\
175     /// Branch
176     /// └╼ Child of Branch
177     /// Sibling of Branch", &tree.string());
178     /// ```
add_branch(&self, text: &str) -> ScopedBranch179     pub fn add_branch(&self, text: &str) -> ScopedBranch {
180         self.add_leaf(text);
181         ScopedBranch::new(self.clone())
182     }
183 
184     /// Adds a new branch with text, `text` and returns a `ScopedBranch`.
185     /// When the returned `ScopedBranch` goes out of scope, (likely the end of the current block),
186     /// or if its `release()` method is called, the tree tree will step back out of the added branch.
187     ///
188     /// # Arguments
189     /// * `text` - A string slice to use as the newly added branch's text.
190     ///
191     /// # Examples
192     ///
193     /// Stepping out of branch when end of scope is reached.
194     /// ```
195     /// use debug_tree::TreeBuilder;
196     /// let tree = TreeBuilder::new();
197     /// {
198     ///     tree.add_leaf("Branch");
199     ///     let _branch = tree.enter_scoped(); // _branch enters scope
200     ///     // tree is now pointed inside new branch.
201     ///     tree.add_leaf("Child of Branch");
202     ///     // _branch leaves scope, tree moves up to parent branch.
203     /// }
204     /// tree.add_leaf("Sibling of Branch");
205     /// assert_eq!("\
206     /// Branch
207     /// └╼ Child of Branch
208     /// Sibling of Branch", &tree.string());
209     /// ```
210     ///
211     /// Using `release()` before out of scope.
212     /// ```
213     /// use debug_tree::TreeBuilder;
214     /// let tree = TreeBuilder::new();
215     /// {
216     ///     tree.add_leaf("Branch");
217     ///     let mut branch = tree.enter_scoped(); // branch enters scope
218     ///     // tree is now pointed inside new branch.
219     ///     tree.add_leaf("Child of Branch");
220     ///     branch.release();
221     ///     tree.add_leaf("Sibling of Branch");
222     ///     // branch leaves scope, but no effect because its `release()` method has already been called
223     /// }
224     /// assert_eq!("\
225     /// Branch
226     /// └╼ Child of Branch
227     /// Sibling of Branch", &tree.string());
228     /// ```
enter_scoped(&self) -> ScopedBranch229     pub fn enter_scoped(&self) -> ScopedBranch {
230         if self.is_enabled() {
231             ScopedBranch::new(self.clone())
232         } else {
233             ScopedBranch::none()
234         }
235     }
236 
237     /// Adds a leaf to current branch with the given text, `text`.
238     ///
239     /// # Arguments
240     /// * `text` - A string slice to use as the newly added leaf's text.
241     ///
242     /// # Example
243     ///
244     /// ```
245     /// use debug_tree::TreeBuilder;
246     /// let tree = TreeBuilder::new();
247     /// tree.add_leaf("New leaf");
248     /// ```
add_leaf(&self, text: &str)249     pub fn add_leaf(&self, text: &str) {
250         let mut x = self.0.lock().unwrap();
251         if x.is_enabled() {
252             x.add_leaf(&text);
253         }
254     }
255 
256     /// Steps into a new child branch.
257     /// Stepping out of the branch requires calling `exit()`.
258     ///
259     /// # Example
260     /// ```
261     /// use debug_tree::TreeBuilder;
262     /// let tree = TreeBuilder::new();
263     /// tree.add_leaf("Branch");
264     /// tree.enter();
265     /// tree.add_leaf("Child of Branch");
266     /// assert_eq!("\
267     /// Branch
268     /// └╼ Child of Branch", &tree.string());
269     /// ```
enter(&self)270     pub fn enter(&self) {
271         let mut x = self.0.lock().unwrap();
272         if x.is_enabled() {
273             x.enter();
274         }
275     }
276 
277     /// Exits the current branch, to the parent branch.
278     /// If no parent branch exists, no action is taken
279     ///
280     /// # Example
281     ///
282     /// ```
283     /// use debug_tree::TreeBuilder;
284     /// let tree = TreeBuilder::new();
285     /// tree.add_leaf("Branch");
286     /// tree.enter();
287     /// tree.add_leaf("Child of Branch");
288     /// tree.exit();
289     /// tree.add_leaf("Sibling of Branch");
290     /// assert_eq!("\
291     /// Branch
292     /// └╼ Child of Branch
293     /// Sibling of Branch", &tree.string());
294     /// ```
exit(&self) -> bool295     pub fn exit(&self) -> bool {
296         let mut x = self.0.lock().unwrap();
297         if x.is_enabled() {
298             x.exit()
299         } else {
300             false
301         }
302     }
303 
304     /// Returns the depth of the current branch
305     /// The initial depth when no branches have been adeed is 0.
306     ///
307     /// # Example
308     ///
309     /// ```
310     /// use debug_tree::TreeBuilder;
311     /// let tree = TreeBuilder::new();
312     /// assert_eq!(0, tree.depth());
313     /// let _b = tree.add_branch("Branch");
314     /// assert_eq!(1, tree.depth());
315     /// let _b = tree.add_branch("Child branch");
316     /// assert_eq!(2, tree.depth());
317     /// ```
depth(&self) -> usize318     pub fn depth(&self) -> usize {
319         self.0.lock().unwrap().depth()
320     }
321 
322     /// Prints the tree without clearing.
323     ///
324     /// # Example
325     ///
326     /// ```
327     /// use debug_tree::TreeBuilder;
328     /// let tree = TreeBuilder::new();
329     /// tree.add_leaf("Leaf");
330     /// tree.peek_print();
331     /// // Leaf
332     /// tree.peek_print();
333     /// // Leaf
334     /// // Leaf 2
335     /// ```
peek_print(&self)336     pub fn peek_print(&self) {
337         self.0.lock().unwrap().peek_print();
338     }
339 
340     /// Prints the tree and then clears it.
341     ///
342     /// # Example
343     ///
344     /// ```
345     /// use debug_tree::TreeBuilder;
346     /// let tree = TreeBuilder::new();
347     /// tree.add_leaf("Leaf");
348     /// tree.print();
349     /// // Leaf
350     /// tree.add_leaf("Leaf 2");
351     /// tree.print();
352     /// // Leaf 2
353     /// ```
print(&self)354     pub fn print(&self) {
355         self.0.lock().unwrap().print();
356     }
357 
358     /// Returns the tree as a string without clearing the tree.
359     ///
360     /// # Example
361     ///
362     /// ```
363     /// use debug_tree::TreeBuilder;
364     /// let tree = TreeBuilder::new();
365     /// tree.add_leaf("Leaf");
366     /// assert_eq!("Leaf", tree.peek_string());
367     /// tree.add_leaf("Leaf 2");
368     /// assert_eq!("Leaf\nLeaf 2", tree.peek_string());
369     /// ```
peek_string(&self) -> String370     pub fn peek_string(&self) -> String {
371         self.0.lock().unwrap().peek_string()
372     }
373 
374     /// Returns the tree as a string and clears the tree.
375     ///
376     /// # Example
377     ///
378     /// ```
379     /// use debug_tree::TreeBuilder;
380     /// let tree = TreeBuilder::new();
381     /// tree.add_leaf("Leaf");
382     /// assert_eq!("Leaf", tree.string());
383     /// tree.add_leaf("Leaf 2");
384     /// assert_eq!("Leaf 2", tree.string());
385     /// ```
string(&self) -> String386     pub fn string(&self) -> String {
387         self.0.lock().unwrap().string()
388     }
389 
390     /// Writes the tree to file without clearing.
391     ///
392     /// # Example
393     ///
394     /// ```
395     /// use debug_tree::TreeBuilder;
396     /// use std::fs::{read_to_string, create_dir};
397     /// use std::io::Read;
398     /// let tree = TreeBuilder::new();
399     /// create_dir("test_out").ok();
400     /// tree.add_leaf("Leaf");
401     /// assert_eq!(tree.peek_string(), "Leaf");
402     /// tree.peek_write("test_out/peek_write.txt");
403     /// assert_eq!(read_to_string("test_out/peek_write.txt").unwrap(), "Leaf");
404     /// assert_eq!(tree.peek_string(), "Leaf");
405     /// ```
peek_write(&self, path: &str) -> std::io::Result<()>406     pub fn peek_write(&self, path: &str) -> std::io::Result<()> {
407         let mut file = File::create(path)?;
408         file.write_all(self.peek_string().as_bytes())
409     }
410 
411     /// Writes the tree to file without clearing.
412     ///
413     /// # Example
414     ///
415     /// ```
416     /// use debug_tree::TreeBuilder;
417     /// use std::io::Read;
418     /// use std::fs::{read_to_string, create_dir};
419     /// let tree = TreeBuilder::new();
420     /// create_dir("test_out").ok();
421     /// tree.add_leaf("Leaf");
422     /// assert_eq!(tree.peek_string(), "Leaf");
423     /// tree.write("test_out/write.txt");
424     /// assert_eq!(read_to_string("test_out/write.txt").unwrap(), "Leaf");
425     /// assert_eq!(tree.peek_string(), "");
426     /// ```
write(&self, path: &str) -> std::io::Result<()>427     pub fn write(&self, path: &str) -> std::io::Result<()> {
428         let mut file = File::create(path)?;
429         file.write_all(self.string().as_bytes())
430     }
431 
432     /// Clears the tree.
433     ///
434     /// # Example
435     ///
436     /// ```
437     /// use debug_tree::TreeBuilder;
438     /// let tree = TreeBuilder::new();
439     /// tree.add_leaf("Leaf");
440     /// assert_eq!("Leaf", tree.peek_string());
441     /// tree.clear();
442     /// assert_eq!("", tree.peek_string());
443     /// ```
clear(&self)444     pub fn clear(&self) {
445         self.0.lock().unwrap().clear()
446     }
447 
448     /// Sets the enabled state of the tree.
449     ///
450     /// If not enabled, the tree will not be modified by adding leaves or branches.
451     /// Additionally, if called using the `add_`... macros, arguments will not be processed.
452     /// This is particularly useful for suppressing output in production, with very little overhead.
453     ///
454     /// # Example
455     /// ```
456     /// #[macro_use]
457     /// use debug_tree::{TreeBuilder, add_leaf_to};
458     /// let mut tree = TreeBuilder::new();
459     /// tree.add_leaf("Leaf 1");
460     /// tree.set_enabled(false);
461     /// add_leaf_to!(tree, "Leaf 2");
462     /// tree.set_enabled(true);
463     /// add_leaf_to!(tree, "Leaf 3");
464     /// assert_eq!("Leaf 1\nLeaf 3", tree.peek_string());
465     /// ```
set_enabled(&self, enabled: bool)466     pub fn set_enabled(&self, enabled: bool) {
467         self.0.lock().unwrap().set_enabled(enabled);
468     }
469 
470     /// Returns the enabled state of the tree.
471     ///
472     /// # Example
473     /// ```
474     /// use debug_tree::TreeBuilder;
475     /// let mut tree = TreeBuilder::new();
476     /// assert_eq!(true, tree.is_enabled());
477     /// tree.set_enabled(false);
478     /// assert_eq!(false, tree.is_enabled());
479     /// ```
is_enabled(&self) -> bool480     pub fn is_enabled(&self) -> bool {
481         self.0.lock().unwrap().is_enabled()
482     }
483 }
484 
485 pub trait AsTree {
as_tree(&self) -> TreeBuilder486     fn as_tree(&self) -> TreeBuilder;
is_tree_enabled(&self) -> bool487     fn is_tree_enabled(&self) -> bool {
488         self.as_tree().is_enabled()
489     }
490 }
491 
492 impl AsTree for TreeBuilder {
as_tree(&self) -> TreeBuilder493     fn as_tree(&self) -> TreeBuilder {
494         self.clone()
495     }
496 }
497 
get_or_add_tree<T: AsRef<str>>(name: T) -> TreeBuilder498 pub(crate) fn get_or_add_tree<T: AsRef<str>>(name: T) -> TreeBuilder {
499     let mut map = TREE_MAP.lock().unwrap();
500     match map.get(name.as_ref()) {
501         Some(x) => x.clone(),
502         _ => {
503             let val = TreeBuilder::new();
504             map.insert(name.as_ref().to_string(), val.clone());
505             val
506         }
507     }
508 }
509 
get_tree<T: AsRef<str>>(name: T) -> Option<TreeBuilder>510 pub(crate) fn get_tree<T: AsRef<str>>(name: T) -> Option<TreeBuilder> {
511     TREE_MAP.lock().unwrap().get(name.as_ref()).cloned()
512 }
513 
514 type TreeMap = BTreeMap<String, TreeBuilder>;
515 
516 static TREE_MAP: Lazy<Arc<Mutex<TreeMap>>> =
517     Lazy::new(|| -> Arc<Mutex<TreeMap>> { Arc::new(Mutex::new(TreeMap::new())) });
518 
519 /// Sets the enabled state of the tree.
520 ///
521 /// # Arguments
522 /// * `name` - The tree name
523 /// * `enabled` - The enabled state
524 ///
set_enabled<T: AsRef<str>>(name: T, enabled: bool)525 pub fn set_enabled<T: AsRef<str>>(name: T, enabled: bool) {
526     let mut map = TREE_MAP.lock().unwrap();
527     match map.get_mut(name.as_ref()) {
528         Some(x) => x.set_enabled(enabled),
529         _ => {
530             let tree = TreeBuilder::new();
531             tree.set_enabled(enabled);
532             map.insert(name.as_ref().to_string(), tree);
533         }
534     }
535 }
536 
537 impl<T: AsRef<str>> AsTree for T {
as_tree(&self) -> TreeBuilder538     fn as_tree(&self) -> TreeBuilder {
539         get_or_add_tree(self)
540     }
541     /// Check if the named tree is enabled and exists
542     /// This does not create a new tree if non-existent
543     ///
544     /// # Arguments
545     /// * `tree_name` - The tree name
546     ///
is_tree_enabled(&self) -> bool547     fn is_tree_enabled(&self) -> bool {
548         get_tree(self).map(|x| x.is_enabled()).unwrap_or(false)
549     }
550 }
551 
552 /// Returns the tree
553 /// If there is no tree then one is created and then returned.
tree<T: AsTree>(tree: T) -> TreeBuilder554 pub fn tree<T: AsTree>(tree: T) -> TreeBuilder {
555     tree.as_tree()
556 }
557 
558 /// Returns the tree named `name`
559 /// If there is no tree named `name` then one is created and then returned.
is_tree_enabled<T: AsTree>(tree: &T) -> bool560 pub fn is_tree_enabled<T: AsTree>(tree: &T) -> bool {
561     tree.is_tree_enabled()
562 }
563 
564 /// Calls [clear](TreeBuilder::clear) for the tree named `name`
565 /// If there is no tree named `name` then one is created
clear<T: AsRef<str>>(name: T)566 pub fn clear<T: AsRef<str>>(name: T) {
567     name.as_tree().clear();
568 }
569 
570 /// Returns [string](TreeBuilder::string) for the tree named `name`
571 /// If there is no tree named `name` then one is created
string<T: AsRef<str>>(name: T) -> String572 pub fn string<T: AsRef<str>>(name: T) -> String {
573     name.as_tree().string()
574 }
575 
576 /// Returns [peek_string](TreeBuilder::peek_string) for the tree named `name`
577 /// If there is no tree named `name` then one is created
peek_string<T: AsRef<str>>(name: T) -> String578 pub fn peek_string<T: AsRef<str>>(name: T) -> String {
579     name.as_tree().peek_string()
580 }
581 
582 /// Calls [print](TreeBuilder::print) for the tree named `name`
583 /// If there is no tree named `name` then one is created
print<T: AsRef<str>>(name: T)584 pub fn print<T: AsRef<str>>(name: T) {
585     name.as_tree().print();
586 }
587 
588 /// Calls [peek_print](TreeBuilder::peek_print)  for the tree named `name`
589 /// If there is no tree named `name` then one is created
peek_print<T: AsRef<str>>(name: T)590 pub fn peek_print<T: AsRef<str>>(name: T) {
591     name.as_tree().peek_print();
592 }
593 
594 /// Calls [write](TreeBuilder::write) for the tree named `name`
595 /// If there is no tree named `name` then one is created
write<T: AsRef<str>, P: AsRef<str>>(name: T, path: P) -> std::io::Result<()>596 pub fn write<T: AsRef<str>, P: AsRef<str>>(name: T, path: P) -> std::io::Result<()> {
597     name.as_tree().write(path.as_ref())
598 }
599 
600 /// Calls [peek_print](TreeBuilder::peek_print)  for the tree named `name`
601 /// If there is no tree named `name` then one is created
peek_write<T: AsRef<str>, P: AsRef<str>>(name: T, path: P) -> std::io::Result<()>602 pub fn peek_write<T: AsRef<str>, P: AsRef<str>>(name: T, path: P) -> std::io::Result<()> {
603     name.as_tree().peek_write(path.as_ref())
604 }
605 
606 /// Adds a leaf to given tree with the given text and formatting arguments
607 ///
608 /// # Arguments
609 /// * `tree` - The tree that the leaf should be added to
610 /// * `text...` - Formatted text arguments, as per `format!(...)`.
611 ///
612 /// # Example
613 ///
614 /// ```
615 /// #[macro_use]
616 /// use debug_tree::{TreeBuilder, add_leaf_to};
617 /// fn main() {
618 ///     let tree = TreeBuilder::new();
619 ///     add_leaf_to!(tree, "A {} leaf", "new");
620 ///     assert_eq!("A new leaf", &tree.peek_string());
621 /// }
622 /// ```
623 #[macro_export]
624 macro_rules! add_leaf_to {
625     ($tree:expr, $($arg:tt)*) => (if $crate::is_tree_enabled(&$tree) {
626         use $crate::AsTree;
627         $tree.as_tree().add_leaf(&format!($($arg)*))
628     });
629 }
630 
631 /// Adds a leaf to given tree with the given `value` argument
632 ///
633 /// # Arguments
634 /// * `tree` - The tree that the leaf should be added to
635 /// * `value` - An expression that implements the `Display` trait.
636 ///
637 /// # Example
638 ///
639 /// ```
640 /// #[macro_use]
641 /// use debug_tree::{TreeBuilder, add_leaf_value_to};
642 /// fn main() {
643 ///     let tree = TreeBuilder::new();
644 ///     let value = add_leaf_value_to!(tree, 5 * 4 * 3 * 2);
645 ///     assert_eq!(120, value);
646 ///     assert_eq!("120", &tree.peek_string());
647 /// }
648 /// ```
649 #[macro_export]
650 macro_rules! add_leaf_value_to {
651     ($tree:expr, $value:expr) => {{
652         let v = $value;
653         if $crate::is_tree_enabled(&$tree) {
654             use $crate::AsTree;
655             $tree.as_tree().add_leaf(&format!("{}", &v));
656         }
657         v
658     }};
659 }
660 
661 /// Adds a scoped branch to given tree with the given text and formatting arguments
662 /// The branch will be exited at the end of the current block.
663 ///
664 /// # Arguments
665 /// * `tree` - The tree that the leaf should be added to
666 /// * `text...` - Formatted text arguments, as per `format!(...)`.
667 ///
668 /// # Example
669 ///
670 /// ```
671 /// #[macro_use]
672 /// use debug_tree::{TreeBuilder, add_branch_to, add_leaf_to};
673 /// fn main() {
674 ///     let tree = TreeBuilder::new();
675 ///     {
676 ///         add_branch_to!(tree, "New {}", "Branch"); // _branch enters scope
677 ///         // tree is now pointed inside new branch.
678 ///         add_leaf_to!(tree, "Child of {}", "Branch");
679 ///         // Block ends, so tree exits the current branch.
680 ///     }
681 ///     add_leaf_to!(tree, "Sibling of {}", "Branch");
682 ///     assert_eq!("\
683 /// New Branch
684 /// └╼ Child of Branch
685 /// Sibling of Branch" , &tree.string());
686 /// }
687 /// ```
688 #[macro_export]
689 macro_rules! add_branch_to {
690     ($tree:expr) => {
691         let _debug_tree_branch = if $crate::is_tree_enabled(&$tree) {
692             use $crate::AsTree;
693             $tree.as_tree().enter_scoped()
694         } else {
695             $crate::scoped_branch::ScopedBranch::none()
696         };
697     };
698     ($tree:expr, $($arg:tt)*) => {
699         let _debug_tree_branch = if $crate::is_tree_enabled(&$tree) {
700             use $crate::AsTree;
701             $tree.as_tree().add_branch(&format!($($arg)*))
702         } else {
703             $crate::scoped_branch::ScopedBranch::none()
704         };
705     };
706 }
707 
708 /// Calls `function` with argument, `tree`, at the end of the current scope
709 /// The function will only be executed if the tree is enabled when this macro is called
710 #[macro_export]
711 macro_rules! defer {
712     ($function:expr) => {
713         let _debug_tree_defer = {
714             use $crate::AsTree;
715             if $crate::default::default_tree().is_enabled() {
716                 use $crate::AsTree;
717                 $crate::defer::DeferredFn::new($crate::default::default_tree(), $function)
718             } else {
719                 $crate::defer::DeferredFn::none()
720             }
721         };
722     };
723     ($tree:expr, $function:expr) => {
724         let _debug_tree_defer = {
725             use $crate::AsTree;
726             if $tree.as_tree().is_enabled() {
727                 $crate::defer::DeferredFn::new($tree.as_tree(), $function)
728             } else {
729                 $crate::defer::DeferredFn::none()
730             }
731         };
732     };
733 }
734 
735 /// Calls [print](TreeBuilder::print) on `tree` at the end of the current scope.
736 /// The function will only be executed if the tree is enabled when this macro is called
737 #[macro_export]
738 macro_rules! defer_print {
739     () => {
740         $crate::defer!(|x| {
741             x.print();
742         })
743     };
744     ($tree:expr) => {
745         $crate::defer!($tree, |x| {
746             x.print();
747         })
748     };
749 }
750 
751 /// Calls [peek_print](TreeBuilder::peek_print) on `tree` at the end of the current scope.
752 /// The function will only be executed if the tree is enabled when this macro is called
753 #[macro_export]
754 macro_rules! defer_peek_print {
755     () => {
756         $crate::defer!(|x| {
757             x.peek_print();
758         })
759     };
760     ($tree:expr) => {
761         $crate::defer!($tree, |x| {
762             x.peek_print();
763         })
764     };
765 }
766 
767 /// Calls [write](TreeBuilder::write) on `tree` at the end of the current scope.
768 /// The function will only be executed if the tree is enabled when this macro is called
769 #[macro_export]
770 macro_rules! defer_write {
771     ($tree:expr, $path:expr) => {
772         $crate::defer!($tree, |x| {
773             if let Err(err) = x.write($path) {
774                 eprintln!("error during `defer_write`: {}", err);
775             }
776         })
777     };
778     ($path:expr) => {
779         $crate::defer!(|x| {
780             if let Err(err) = x.write($path) {
781                 eprintln!("error during `defer_write`: {}", err);
782             }
783         })
784     };
785 }
786 
787 /// Calls [peek_write](TreeBuilder::peek_write) on `tree` at the end of the current scope.
788 /// The function will only be executed if the tree is enabled when this macro is called
789 #[macro_export]
790 macro_rules! defer_peek_write {
791     ($tree:expr, $path:expr) => {
792         $crate::defer!($tree, |x| {
793             if let Err(err) = x.peek_write($path) {
794                 eprintln!("error during `defer_peek_write`: {}", err);
795             }
796         })
797     };
798     ($path:expr) => {
799         $crate::defer!(|x| {
800             if let Err(err) = x.peek_write($path) {
801                 eprintln!("error during `defer_peek_write`: {}", err);
802             }
803         })
804     };
805 }
806