lipgloss_tree/children.rs
1//! Node and tree data structures for building hierarchical content.
2//!
3//! This module provides the core data structures for representing tree nodes
4//! and collections of children. It supports styling, filtering, and complex
5//! tree operations with Go lipgloss compatibility.
6
7use lipgloss::Style;
8use std::fmt;
9
10/// Helper trait to enable cloning boxed trait objects for Node.
11///
12/// This trait provides the mechanism for cloning `Box<dyn Node>` objects,
13/// which is necessary for tree operations that need to duplicate node structures.
14/// It's automatically implemented for any type that implements `Node + Clone`.
15///
16/// # Implementation Note
17///
18/// This trait is automatically implemented via a blanket implementation,
19/// so you typically don't need to implement it manually.
20pub trait CloneNode {
21 /// Creates a cloned copy of this node as a boxed trait object.
22 ///
23 /// # Returns
24 ///
25 /// A new `Box<dyn Node>` containing a clone of this node.
26 fn clone_node(&self) -> Box<dyn Node>;
27}
28
29impl<T> CloneNode for T
30where
31 T: 'static + Node + Clone,
32{
33 fn clone_node(&self) -> Box<dyn Node> {
34 Box::new(self.clone())
35 }
36}
37
38/// Trait defining a node in a tree structure.
39///
40/// `Node` represents an individual element in a tree that can have a value,
41/// children, visibility state, and various styling options. It supports both
42/// simple leaf nodes and complex tree nodes with nested children.
43///
44/// # Core Functionality
45///
46/// - **Value**: Each node has a string value that represents its content
47/// - **Children**: Nodes can have child nodes forming a hierarchical structure
48/// - **Visibility**: Nodes can be hidden from rendering
49/// - **Styling**: Nodes support custom enumerators, indenters, and styling functions
50///
51/// # Examples
52///
53/// ```rust
54/// use lipgloss_tree::{Tree, Leaf, Node, Children};
55///
56/// // Create a simple leaf node
57/// let leaf = Leaf::new("Hello", false);
58/// assert_eq!(leaf.value(), "Hello");
59/// assert!(!leaf.hidden());
60///
61/// // Create a tree node with children
62/// let tree = Tree::new()
63/// .root("Parent")
64/// .child(vec!["Child 1".into(), "Child 2".into()]);
65/// assert_eq!(tree.value(), "Parent");
66/// assert_eq!(tree.children().length(), 2);
67/// ```
68pub trait Node: fmt::Display + CloneNode {
69 /// Returns the string value of this node.
70 ///
71 /// The value is the textual content that will be displayed when
72 /// the tree is rendered.
73 ///
74 /// # Returns
75 ///
76 /// The node's value as a `String`
77 fn value(&self) -> String;
78
79 /// Returns the children of this node.
80 ///
81 /// Children are returned as a boxed trait object to allow for
82 /// different implementations of the `Children` trait.
83 ///
84 /// # Returns
85 ///
86 /// A `Box<dyn Children>` containing this node's children
87 fn children(&self) -> Box<dyn Children>;
88
89 /// Returns whether this node is hidden from rendering.
90 ///
91 /// Hidden nodes are not displayed in the tree output and are
92 /// typically filtered out during rendering.
93 ///
94 /// # Returns
95 ///
96 /// `true` if the node is hidden, `false` otherwise
97 fn hidden(&self) -> bool;
98
99 /// Sets the visibility state of this node.
100 ///
101 /// # Arguments
102 ///
103 /// * `hidden` - `true` to hide the node, `false` to show it
104 fn set_hidden(&mut self, hidden: bool);
105
106 /// Updates the value of this node.
107 ///
108 /// # Arguments
109 ///
110 /// * `value` - The new string value for this node
111 fn set_value(&mut self, value: String);
112
113 // Optional per-node renderer overrides. Default to None.
114
115 /// Returns the custom enumerator function for this node, if any.
116 ///
117 /// The enumerator function generates branch characters (like ├──, └──)
118 /// for this specific node, overriding the default renderer behavior.
119 ///
120 /// # Returns
121 ///
122 /// An optional reference to the node's custom enumerator function
123 fn get_enumerator(&self) -> Option<&crate::Enumerator> {
124 None
125 }
126
127 /// Returns the custom indenter function for this node, if any.
128 ///
129 /// The indenter function generates indentation strings for child content
130 /// under this node, overriding the default renderer behavior.
131 ///
132 /// # Returns
133 ///
134 /// An optional reference to the node's custom indenter function
135 fn get_indenter(&self) -> Option<&crate::Indenter> {
136 None
137 }
138
139 /// Returns the base item style for this node, if any.
140 ///
141 /// The base item style is applied to the node's content before any
142 /// style functions are applied.
143 ///
144 /// # Returns
145 ///
146 /// An optional reference to the node's base item style
147 fn get_item_style(&self) -> Option<&Style> {
148 None
149 }
150
151 /// Returns the base enumerator style for this node, if any.
152 ///
153 /// The base enumerator style is applied to the node's branch characters
154 /// before any style functions are applied.
155 ///
156 /// # Returns
157 ///
158 /// An optional reference to the node's base enumerator style
159 fn get_enumerator_style(&self) -> Option<&Style> {
160 None
161 }
162
163 /// Returns the item style function for this node, if any.
164 ///
165 /// The item style function provides dynamic styling based on the node's
166 /// position and context within its parent's children.
167 ///
168 /// # Returns
169 ///
170 /// An optional reference to the node's item style function
171 fn get_item_style_func(&self) -> Option<&crate::StyleFunc> {
172 None
173 }
174
175 /// Returns the enumerator style function for this node, if any.
176 ///
177 /// The enumerator style function provides dynamic styling for branch
178 /// characters based on the node's position and context.
179 ///
180 /// # Returns
181 ///
182 /// An optional reference to the node's enumerator style function
183 fn get_enumerator_style_func(&self) -> Option<&crate::StyleFunc> {
184 None
185 }
186}
187
188impl Clone for NodeChildren {
189 fn clone(&self) -> Self {
190 let mut cloned = NodeChildren::new();
191 for i in 0..self.length() {
192 if let Some(n) = self.at(i) {
193 cloned.append(n.clone_node());
194 }
195 }
196 cloned
197 }
198}
199
200/// A filtered view of children that applies start/end bounds and optional hidden filtering.
201///
202/// `Slice` provides a window into a larger children collection, allowing you to
203/// view only a subset of children within specified bounds. It can also optionally
204/// skip hidden nodes during iteration.
205///
206/// # Examples
207///
208/// ```rust,ignore
209/// // Internal usage only - not part of public API
210/// let slice = Slice::new(children, 1, 5, true); // Skip hidden nodes
211/// ```
212#[allow(dead_code)]
213struct Slice {
214 /// The underlying children collection
215 data: Box<dyn Children>,
216 /// Starting index (inclusive)
217 start: usize,
218 /// Ending index (exclusive)
219 end: usize,
220 /// Whether to skip hidden nodes
221 skip_hidden: bool,
222}
223
224#[allow(dead_code)]
225impl Slice {
226 /// Creates a new slice view of the given children collection.
227 ///
228 /// # Arguments
229 ///
230 /// * `data` - The underlying children collection to slice
231 /// * `start` - Starting index (inclusive)
232 /// * `end` - Ending index (exclusive)
233 /// * `skip_hidden` - Whether to filter out hidden nodes
234 ///
235 /// # Returns
236 ///
237 /// A new `Slice` that provides a filtered view of the children
238 fn new(data: Box<dyn Children>, start: usize, end: usize, skip_hidden: bool) -> Self {
239 Self {
240 data,
241 start,
242 end,
243 skip_hidden,
244 }
245 }
246}
247
248impl Children for Slice {
249 fn at(&self, index: usize) -> Option<&dyn Node> {
250 let mut j = 0usize;
251 let upper = self.end.min(self.data.length());
252 for i in self.start..upper {
253 if let Some(node) = self.data.at(i) {
254 if self.skip_hidden && node.hidden() {
255 continue;
256 }
257 if j == index {
258 return Some(node);
259 }
260 j += 1;
261 }
262 }
263 None
264 }
265
266 fn length(&self) -> usize {
267 let mut count = 0usize;
268 let upper = self.end.min(self.data.length());
269 for i in self.start..upper {
270 if let Some(node) = self.data.at(i) {
271 if self.skip_hidden && node.hidden() {
272 continue;
273 }
274 count += 1;
275 }
276 }
277 count
278 }
279}
280
281/// Trait defining a collection of child nodes in a tree structure.
282///
283/// `Children` provides the interface for accessing and querying collections
284/// of tree nodes. Implementations can provide different storage strategies,
285/// filtering capabilities, or views of the underlying data.
286///
287/// # Examples
288///
289/// ```rust
290/// use lipgloss_tree::{NodeChildren, Children, Leaf, Node};
291///
292/// let mut children = NodeChildren::new();
293/// children.append(Box::new(Leaf::new("Item 1", false)));
294/// children.append(Box::new(Leaf::new("Item 2", false)));
295///
296/// assert_eq!(children.length(), 2);
297/// assert_eq!(children.at(0).unwrap().value(), "Item 1");
298/// ```
299pub trait Children {
300 /// Returns the node at the given index.
301 ///
302 /// # Arguments
303 ///
304 /// * `index` - The zero-based index of the desired node
305 ///
306 /// # Returns
307 ///
308 /// An optional reference to the node at the given index,
309 /// or `None` if the index is out of bounds
310 fn at(&self, index: usize) -> Option<&dyn Node>;
311
312 /// Returns the total number of children in this collection.
313 ///
314 /// # Returns
315 ///
316 /// The count of child nodes as a `usize`
317 fn length(&self) -> usize;
318}
319
320/// A concrete implementation of the `Children` trait using a vector of boxed nodes.
321///
322/// `NodeChildren` is the primary implementation for storing and managing
323/// collections of tree nodes. It provides efficient access, modification,
324/// and iteration over child nodes.
325///
326/// # Examples
327///
328/// ```rust
329/// use lipgloss_tree::{NodeChildren, Leaf, Children};
330///
331/// let mut children = NodeChildren::new();
332/// children.append(Box::new(Leaf::new("First", false)));
333/// children.append(Box::new(Leaf::new("Second", false)));
334///
335/// assert_eq!(children.length(), 2);
336/// ```
337pub struct NodeChildren {
338 /// Vector storing the child nodes as boxed trait objects
339 nodes: Vec<Box<dyn Node>>,
340}
341
342impl NodeChildren {
343 /// Creates a new empty `NodeChildren` collection.
344 ///
345 /// # Examples
346 ///
347 /// ```rust
348 /// use lipgloss_tree::{NodeChildren, Children};
349 ///
350 /// let children = NodeChildren::new();
351 /// assert_eq!(children.length(), 0);
352 /// ```
353 pub fn new() -> Self {
354 Self { nodes: Vec::new() }
355 }
356
357 /// Creates a `NodeChildren` collection from a vector of boxed nodes.
358 ///
359 /// # Arguments
360 ///
361 /// * `nodes` - A vector of boxed nodes to initialize the collection with
362 ///
363 /// # Examples
364 ///
365 /// ```rust
366 /// use lipgloss_tree::{NodeChildren, Leaf, Children};
367 ///
368 /// let nodes = vec![
369 /// Box::new(Leaf::new("A", false)) as Box<dyn lipgloss_tree::Node>,
370 /// Box::new(Leaf::new("B", false)) as Box<dyn lipgloss_tree::Node>,
371 /// ];
372 /// let children = NodeChildren::from_nodes(nodes);
373 /// assert_eq!(children.length(), 2);
374 /// ```
375 pub fn from_nodes(nodes: Vec<Box<dyn Node>>) -> Self {
376 Self { nodes }
377 }
378
379 /// Appends a child node to the end of the collection.
380 ///
381 /// # Arguments
382 ///
383 /// * `child` - The boxed node to add to the collection
384 ///
385 /// # Examples
386 ///
387 /// ```rust
388 /// use lipgloss_tree::{NodeChildren, Leaf, Children};
389 ///
390 /// let mut children = NodeChildren::new();
391 /// children.append(Box::new(Leaf::new("New Item", false)));
392 /// assert_eq!(children.length(), 1);
393 /// ```
394 pub fn append(&mut self, child: Box<dyn Node>) {
395 self.nodes.push(child);
396 }
397
398 /// Removes and returns the child node at the given index.
399 ///
400 /// # Arguments
401 ///
402 /// * `index` - The zero-based index of the node to remove
403 ///
404 /// # Returns
405 ///
406 /// The removed node if the index was valid, or `None` if out of bounds
407 ///
408 /// # Examples
409 ///
410 /// ```rust
411 /// use lipgloss_tree::{NodeChildren, Leaf, Children};
412 ///
413 /// let mut children = NodeChildren::new();
414 /// children.append(Box::new(Leaf::new("Remove me", false)));
415 ///
416 /// let removed = children.remove(0);
417 /// assert!(removed.is_some());
418 /// assert_eq!(children.length(), 0);
419 /// ```
420 pub fn remove(&mut self, index: usize) -> Option<Box<dyn Node>> {
421 if index < self.nodes.len() {
422 Some(self.nodes.remove(index))
423 } else {
424 None
425 }
426 }
427
428 /// Returns a mutable reference to the boxed node at the given index.
429 ///
430 /// This allows you to modify the node in place or replace it entirely.
431 ///
432 /// # Arguments
433 ///
434 /// * `index` - The zero-based index of the desired node
435 ///
436 /// # Returns
437 ///
438 /// A mutable reference to the boxed node, or `None` if the index is out of bounds
439 ///
440 /// # Examples
441 ///
442 /// ```rust
443 /// use lipgloss_tree::{NodeChildren, Leaf, Node};
444 ///
445 /// let mut children = NodeChildren::new();
446 /// children.append(Box::new(Leaf::new("Original", false)));
447 ///
448 /// if let Some(node) = children.at_mut(0) {
449 /// node.set_value("Modified".to_string());
450 /// }
451 /// ```
452 pub fn at_mut(&mut self, index: usize) -> Option<&mut Box<dyn Node>> {
453 self.nodes.get_mut(index)
454 }
455}
456
457impl Default for NodeChildren {
458 /// Creates a default (empty) `NodeChildren` collection.
459 ///
460 /// Equivalent to `NodeChildren::new()` - creates an empty collection
461 /// with no child nodes.
462 fn default() -> Self {
463 Self::new()
464 }
465}
466
467impl Children for NodeChildren {
468 fn at(&self, index: usize) -> Option<&dyn Node> {
469 self.nodes.get(index).map(|node| node.as_ref())
470 }
471
472 fn length(&self) -> usize {
473 self.nodes.len()
474 }
475}
476
477/// A terminal node in the tree that contains a value but no children.
478///
479/// `Leaf` represents the simplest type of tree node - one that holds a string
480/// value and a visibility flag, but cannot have child nodes. This is useful
481/// for representing individual items in a tree structure.
482///
483/// # Examples
484///
485/// ```rust
486/// use lipgloss_tree::{Leaf, Node, Children};
487///
488/// let leaf = Leaf::new("Hello, World!", false);
489/// assert_eq!(leaf.value(), "Hello, World!");
490/// assert!(!leaf.hidden());
491/// assert_eq!(leaf.children().length(), 0);
492///
493/// println!("{}", leaf); // Outputs: Hello, World!
494/// ```
495#[derive(Debug, Clone)]
496pub struct Leaf {
497 /// The textual content of this leaf node
498 value: String,
499 /// Whether this leaf is hidden from rendering
500 hidden: bool,
501}
502
503impl Leaf {
504 /// Creates a new leaf node with the given value and visibility.
505 ///
506 /// # Arguments
507 ///
508 /// * `value` - The content for this leaf (anything convertible to String)
509 /// * `hidden` - Whether this leaf should be hidden from rendering
510 ///
511 /// # Examples
512 ///
513 /// ```rust
514 /// use lipgloss_tree::{Leaf, Node};
515 ///
516 /// let visible_leaf = Leaf::new("Visible", false);
517 /// let hidden_leaf = Leaf::new("Hidden", true);
518 ///
519 /// assert!(!visible_leaf.hidden());
520 /// assert!(hidden_leaf.hidden());
521 /// ```
522 pub fn new(value: impl Into<String>, hidden: bool) -> Self {
523 Self {
524 value: value.into(),
525 hidden,
526 }
527 }
528}
529
530impl Node for Leaf {
531 fn value(&self) -> String {
532 self.value.clone()
533 }
534
535 fn children(&self) -> Box<dyn Children> {
536 Box::new(NodeChildren::new())
537 }
538
539 fn hidden(&self) -> bool {
540 self.hidden
541 }
542
543 fn set_hidden(&mut self, hidden: bool) {
544 self.hidden = hidden;
545 }
546
547 fn set_value(&mut self, value: String) {
548 self.value = value;
549 }
550
551 fn get_enumerator(&self) -> Option<&crate::Enumerator> {
552 None
553 }
554
555 fn get_indenter(&self) -> Option<&crate::Indenter> {
556 None
557 }
558}
559
560impl fmt::Display for Leaf {
561 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
562 write!(f, "{}", self.value)
563 }
564}
565
566/// A tree node that can contain both a value and child nodes.
567///
568/// `Tree` is the main building block for creating hierarchical tree structures.
569/// Unlike `Leaf` nodes, trees can have children and support advanced features
570/// like custom styling, enumerators, indenters, and offset-based child filtering.
571///
572/// # Key Features
573///
574/// - **Hierarchical structure**: Can contain child nodes forming a tree
575/// - **Custom styling**: Support for root, item, and enumerator styling
576/// - **Custom rendering**: Override enumerators and indenters per-node
577/// - **Child filtering**: Use offsets to display only a subset of children
578/// - **Builder pattern**: Fluent API for easy tree construction
579///
580/// # Examples
581///
582/// ```rust
583/// use lipgloss_tree::Tree;
584///
585/// let tree = Tree::new()
586/// .root("My Project")
587/// .child(vec![
588/// "file1.txt".into(),
589/// "file2.txt".into(),
590/// Tree::new()
591/// .root("subfolder")
592/// .child(vec!["nested.txt".into()])
593/// .into(),
594/// ]);
595///
596/// println!("{}", tree);
597/// ```
598///
599/// This creates a tree structure like:
600/// ```text
601/// My Project
602/// ├── file1.txt
603/// ├── file2.txt
604/// ├── subfolder
605/// │ └── nested.txt
606/// ```
607#[derive(Clone)]
608pub struct Tree {
609 /// The root value of this tree node
610 value: String,
611 /// Whether this tree node is hidden from rendering
612 hidden: bool,
613 /// Offset bounds [start, end] for filtering children
614 offset: [usize; 2],
615 /// Collection of child nodes
616 children: NodeChildren,
617
618 // Style and rendering properties
619 /// Custom enumerator function for this tree
620 enumerator: Option<crate::Enumerator>,
621 /// Custom indenter function for this tree
622 indenter: Option<crate::Indenter>,
623 /// Style applied to the root value
624 root_style: Option<Style>,
625 /// Base style applied to all child items
626 item_style: Option<Style>,
627 /// Base style applied to all enumerators
628 enumerator_style: Option<Style>,
629 /// Dynamic styling function for items
630 item_style_func: Option<crate::StyleFunc>,
631 /// Dynamic styling function for enumerators
632 enumerator_style_func: Option<crate::StyleFunc>,
633}
634
635impl Tree {
636 /// Creates a new empty tree with default settings.
637 ///
638 /// The tree starts with no root value, no children, and default
639 /// rendering settings.
640 ///
641 /// # Examples
642 ///
643 /// ```rust
644 /// use lipgloss_tree::{Tree, Node, Children};
645 ///
646 /// let tree = Tree::new();
647 /// assert!(tree.value().is_empty());
648 /// assert_eq!(tree.children().length(), 0);
649 /// ```
650 pub fn new() -> Self {
651 Self {
652 value: String::new(),
653 hidden: false,
654 offset: [0, 0],
655 children: NodeChildren::new(),
656 // CRITICAL FIX: Set default enumerator and indenter so trees don't inherit
657 // from parent List's list_indenter. This prevents spacing conflicts when
658 // trees are nested in lists with 2-space indentation.
659 enumerator: Some(crate::default_enumerator),
660 indenter: Some(crate::default_indenter),
661 root_style: None,
662 item_style: None,
663 enumerator_style: None,
664 item_style_func: None,
665 enumerator_style_func: None,
666 }
667 }
668
669 /// Sets the root value of this tree.
670 ///
671 /// The root value is displayed at the top of the tree when rendered.
672 /// If no root is set, the tree will start directly with its children.
673 ///
674 /// # Arguments
675 ///
676 /// * `root` - The root value (anything convertible to String)
677 ///
678 /// # Examples
679 ///
680 /// ```rust
681 /// use lipgloss_tree::{Tree, Node};
682 ///
683 /// let tree = Tree::new().root("My Root");
684 /// assert_eq!(tree.value(), "My Root");
685 /// ```
686 pub fn root(mut self, root: impl Into<String>) -> Self {
687 self.value = root.into();
688 self
689 }
690
691 /// Sets the visibility of this tree.
692 ///
693 /// Hidden trees are not rendered in the output, but their children
694 /// may still be visible depending on the rendering context.
695 ///
696 /// # Arguments
697 ///
698 /// * `hide` - `true` to hide this tree, `false` to show it
699 ///
700 /// # Examples
701 ///
702 /// ```rust
703 /// use lipgloss_tree::{Tree, Node};
704 ///
705 /// let hidden_tree = Tree::new().root("Hidden").hide(true);
706 /// assert!(hidden_tree.hidden());
707 /// ```
708 pub fn hide(mut self, hide: bool) -> Self {
709 self.hidden = hide;
710 self
711 }
712
713 /// Sets the offset range for displaying children.
714 ///
715 /// This allows you to display only a subset of the tree's children,
716 /// which is useful for pagination or filtering large trees.
717 ///
718 /// # Arguments
719 ///
720 /// * `start` - Starting index (inclusive) for child display
721 /// * `end` - Ending index (exclusive) for child display
722 ///
723 /// # Examples
724 ///
725 /// ```rust
726 /// use lipgloss_tree::Tree;
727 ///
728 /// let tree = Tree::new()
729 /// .child(vec!["A".into(), "B".into(), "C".into(), "D".into()])
730 /// .offset(1, 3); // Will only show children B and C
731 /// ```
732 ///
733 /// # Note
734 ///
735 /// If `start > end`, the values will be swapped. If `end` exceeds the
736 /// number of children, it will be clamped to the children count.
737 pub fn offset(mut self, start: usize, end: usize) -> Self {
738 let (start, end) = if start > end {
739 (end, start)
740 } else {
741 (start, end)
742 };
743
744 let end = if end > self.children.length() {
745 self.children.length()
746 } else {
747 end
748 };
749
750 self.offset = [start, end];
751 self
752 }
753
754 /// Adds multiple children to this tree.
755 ///
756 /// This method accepts a vector of boxed nodes and appends them all
757 /// to the tree's children collection. It matches Go's `Child(...any)` method
758 /// for API compatibility.
759 ///
760 /// # Arguments
761 ///
762 /// * `children` - A vector of boxed nodes to add as children
763 ///
764 /// # Examples
765 ///
766 /// ```rust
767 /// use lipgloss_tree::{Tree, Node, Children};
768 ///
769 /// let tree = Tree::new()
770 /// .root("Parent")
771 /// .child(vec![
772 /// "Child 1".into(),
773 /// "Child 2".into(),
774 /// Tree::new().root("Nested").into(),
775 /// ]);
776 ///
777 /// assert_eq!(tree.children().length(), 3);
778 /// ```
779 pub fn child(mut self, children: Vec<Box<dyn Node>>) -> Self {
780 for child in children {
781 self.children.append(child);
782 }
783 self
784 }
785
786 /// Adds a single child to this tree.
787 ///
788 /// This is a convenience method for adding one child at a time,
789 /// accepting anything that can be converted into a boxed node.
790 ///
791 /// # Arguments
792 ///
793 /// * `child` - A node (or convertible value) to add as a child
794 ///
795 /// # Examples
796 ///
797 /// ```rust
798 /// use lipgloss_tree::{Tree, Leaf, Node, Children};
799 ///
800 /// let tree = Tree::new()
801 /// .root("Parent")
802 /// .add_child("String child")
803 /// .add_child(Leaf::new("Leaf child", false))
804 /// .add_child(Tree::new().root("Tree child"));
805 ///
806 /// assert_eq!(tree.children().length(), 3);
807 /// ```
808 pub fn add_child(mut self, child: impl Into<Box<dyn Node>>) -> Self {
809 self.children.append(child.into());
810 self
811 }
812
813 /// Sets a custom enumerator function for this tree.
814 ///
815 /// The enumerator generates branch characters (like ├──, └──) based on
816 /// each child's position. This overrides the default enumerator for this tree.
817 ///
818 /// # Arguments
819 ///
820 /// * `enumerator` - A function that takes `(children, index)` and returns a string
821 ///
822 /// # Examples
823 ///
824 /// ```rust
825 /// use lipgloss_tree::Tree;
826 ///
827 /// let tree = Tree::new()
828 /// .root("Custom")
829 /// .enumerator(|children, i| {
830 /// if i == children.length() - 1 {
831 /// "╰──".to_string() // Rounded last branch
832 /// } else {
833 /// "├──".to_string() // Standard branch
834 /// }
835 /// })
836 /// .child(vec!["A".into(), "B".into()]);
837 /// ```
838 pub fn enumerator(mut self, enumerator: crate::Enumerator) -> Self {
839 self.enumerator = Some(enumerator);
840 self
841 }
842
843 /// Sets a custom indenter function for this tree.
844 ///
845 /// The indenter generates indentation strings for nested child content.
846 /// This overrides the default indenter for this tree.
847 ///
848 /// # Arguments
849 ///
850 /// * `indenter` - A function that takes `(children, index)` and returns an indentation string
851 ///
852 /// # Examples
853 ///
854 /// ```rust
855 /// use lipgloss_tree::Tree;
856 ///
857 /// let tree = Tree::new()
858 /// .indenter(|children, i| {
859 /// if i == children.length() - 1 {
860 /// " ".to_string() // Spaces for last child
861 /// } else {
862 /// "│ ".to_string() // Vertical line for continuing
863 /// }
864 /// });
865 /// ```
866 pub fn indenter(mut self, indenter: crate::Indenter) -> Self {
867 self.indenter = Some(indenter);
868 self
869 }
870
871 /// Sets the styling for the root value of this tree.
872 ///
873 /// # Arguments
874 ///
875 /// * `style` - The lipgloss `Style` to apply to the root
876 ///
877 /// # Examples
878 ///
879 /// ```rust
880 /// use lipgloss_tree::Tree;
881 /// use lipgloss::Style;
882 ///
883 /// let tree = Tree::new()
884 /// .root("Styled Root")
885 /// .root_style(Style::new().bold(true).foreground("blue"));
886 /// ```
887 pub fn root_style(mut self, style: Style) -> Self {
888 self.root_style = Some(style);
889 self
890 }
891
892 /// Sets the base style applied to all child items.
893 ///
894 /// This style is applied to item content before any style functions.
895 ///
896 /// # Arguments
897 ///
898 /// * `style` - The lipgloss `Style` to apply to all items
899 ///
900 /// # Examples
901 ///
902 /// ```rust
903 /// use lipgloss_tree::Tree;
904 /// use lipgloss::Style;
905 ///
906 /// let tree = Tree::new()
907 /// .child(vec!["Item 1".into(), "Item 2".into()])
908 /// .item_style(Style::new().foreground("green"));
909 /// ```
910 pub fn item_style(mut self, style: Style) -> Self {
911 self.item_style = Some(style);
912 self
913 }
914
915 /// Sets the base style applied to all enumerators (branch characters).
916 ///
917 /// This style is applied to enumerators before any style functions.
918 ///
919 /// # Arguments
920 ///
921 /// * `style` - The lipgloss `Style` to apply to all enumerators
922 ///
923 /// # Examples
924 ///
925 /// ```rust
926 /// use lipgloss_tree::Tree;
927 /// use lipgloss::Style;
928 ///
929 /// let tree = Tree::new()
930 /// .child(vec!["Item 1".into(), "Item 2".into()])
931 /// .enumerator_style(Style::new().foreground("yellow"));
932 /// ```
933 pub fn enumerator_style(mut self, style: Style) -> Self {
934 self.enumerator_style = Some(style);
935 self
936 }
937
938 /// Sets a dynamic styling function for child items.
939 ///
940 /// The function receives the children collection and the current index,
941 /// allowing for context-aware styling decisions.
942 ///
943 /// # Arguments
944 ///
945 /// * `func` - A function that takes `(children, index)` and returns a `Style`
946 ///
947 /// # Examples
948 ///
949 /// ```rust
950 /// use lipgloss_tree::Tree;
951 /// use lipgloss::Style;
952 ///
953 /// let tree = Tree::new()
954 /// .child(vec!["First".into(), "Second".into(), "Third".into()])
955 /// .item_style_func(|_children, i| {
956 /// if i % 2 == 0 {
957 /// Style::new().foreground("red")
958 /// } else {
959 /// Style::new().foreground("blue")
960 /// }
961 /// });
962 /// ```
963 pub fn item_style_func(mut self, func: crate::StyleFunc) -> Self {
964 self.item_style_func = Some(func);
965 self
966 }
967
968 /// Sets a dynamic styling function for enumerators (branch characters).
969 ///
970 /// The function receives the children collection and the current index,
971 /// allowing for context-aware styling of branch characters.
972 ///
973 /// # Arguments
974 ///
975 /// * `func` - A function that takes `(children, index)` and returns a `Style`
976 ///
977 /// # Examples
978 ///
979 /// ```rust
980 /// use lipgloss_tree::{Tree, Children};
981 /// use lipgloss::Style;
982 ///
983 /// let tree = Tree::new()
984 /// .child(vec!["Item 1".into(), "Item 2".into()])
985 /// .enumerator_style_func(|children, i| {
986 /// if i == children.length() - 1 {
987 /// Style::new().foreground("red") // Last item in red
988 /// } else {
989 /// Style::new().foreground("green") // Others in green
990 /// }
991 /// });
992 /// ```
993 pub fn enumerator_style_func(mut self, func: crate::StyleFunc) -> Self {
994 self.enumerator_style_func = Some(func);
995 self
996 }
997
998 /// Returns the custom enumerator function for this tree.
999 ///
1000 /// The enumerator function generates branch characters (like ├──, └──) for
1001 /// this tree's children based on their position in the collection. This
1002 /// allows for custom tree rendering styles.
1003 ///
1004 /// # Returns
1005 ///
1006 /// An optional reference to the enumerator function. Returns `Some` if a
1007 /// custom enumerator has been set with [`Tree::enumerator`], or `None`
1008 /// if using the default enumerator.
1009 ///
1010 /// # Examples
1011 ///
1012 /// ```rust
1013 /// use lipgloss_tree::Tree;
1014 ///
1015 /// let tree = Tree::new()
1016 /// .enumerator(|children, i| {
1017 /// if i == children.length() - 1 {
1018 /// "└──".to_string()
1019 /// } else {
1020 /// "├──".to_string()
1021 /// }
1022 /// });
1023 ///
1024 /// assert!(tree.get_enumerator().is_some());
1025 /// ```
1026 pub fn get_enumerator(&self) -> Option<&crate::Enumerator> {
1027 self.enumerator.as_ref()
1028 }
1029
1030 /// Returns the custom indenter function for this tree.
1031 ///
1032 /// The indenter function generates indentation strings for nested content
1033 /// under this tree's children. This determines how deeply nested items
1034 /// are visually offset in the rendered output.
1035 ///
1036 /// # Returns
1037 ///
1038 /// An optional reference to the indenter function. Returns `Some` if a
1039 /// custom indenter has been set with [`Tree::indenter`], or `None`
1040 /// if using the default indenter.
1041 ///
1042 /// # Examples
1043 ///
1044 /// ```rust
1045 /// use lipgloss_tree::Tree;
1046 ///
1047 /// let tree = Tree::new()
1048 /// .indenter(|children, i| {
1049 /// if i == children.length() - 1 {
1050 /// " ".to_string() // Spaces for last child
1051 /// } else {
1052 /// "│ ".to_string() // Vertical line continuing
1053 /// }
1054 /// });
1055 ///
1056 /// assert!(tree.get_indenter().is_some());
1057 /// ```
1058 pub fn get_indenter(&self) -> Option<&crate::Indenter> {
1059 self.indenter.as_ref()
1060 }
1061
1062 /// Returns the styling configuration for this tree's root value.
1063 ///
1064 /// The root style is applied to the tree's main value when rendered,
1065 /// allowing for custom colors, formatting, and visual effects on the
1066 /// top-level tree node.
1067 ///
1068 /// # Returns
1069 ///
1070 /// An optional reference to the root style. Returns `Some` if a custom
1071 /// style has been set with [`Tree::root_style`], or `None` if using
1072 /// the default (unstyled) appearance.
1073 ///
1074 /// # Examples
1075 ///
1076 /// ```rust
1077 /// use lipgloss_tree::Tree;
1078 /// use lipgloss::Style;
1079 ///
1080 /// let tree = Tree::new()
1081 /// .root("Project Root")
1082 /// .root_style(Style::new().bold(true).foreground("blue"));
1083 ///
1084 /// assert!(tree.get_root_style().is_some());
1085 /// ```
1086 pub fn get_root_style(&self) -> Option<&Style> {
1087 self.root_style.as_ref()
1088 }
1089
1090 /// Returns the dynamic styling function for this tree's child items.
1091 ///
1092 /// The item style function provides context-aware styling based on each
1093 /// child's position within the tree. It receives the children collection
1094 /// and the current child's index, allowing for complex styling logic.
1095 ///
1096 /// # Returns
1097 ///
1098 /// An optional reference to the item style function. Returns `Some` if a
1099 /// custom function has been set with [`Tree::item_style_func`], or `None`
1100 /// if using the default (no dynamic styling).
1101 ///
1102 /// # Examples
1103 ///
1104 /// ```rust
1105 /// use lipgloss_tree::Tree;
1106 /// use lipgloss::Style;
1107 ///
1108 /// let tree = Tree::new()
1109 /// .child(vec!["Item 1".into(), "Item 2".into()])
1110 /// .item_style_func(|_children, i| {
1111 /// if i % 2 == 0 {
1112 /// Style::new().foreground("red")
1113 /// } else {
1114 /// Style::new().foreground("blue")
1115 /// }
1116 /// });
1117 ///
1118 /// assert!(tree.get_item_style_func().is_some());
1119 /// ```
1120 pub fn get_item_style_func(&self) -> Option<&crate::StyleFunc> {
1121 self.item_style_func.as_ref()
1122 }
1123
1124 /// Returns the dynamic styling function for this tree's branch characters.
1125 ///
1126 /// The enumerator style function provides context-aware styling for the
1127 /// branch characters (like ├──, └──) based on each child's position. It
1128 /// receives the children collection and current index for styling decisions.
1129 ///
1130 /// # Returns
1131 ///
1132 /// An optional reference to the enumerator style function. Returns `Some`
1133 /// if a custom function has been set with [`Tree::enumerator_style_func`],
1134 /// or `None` if using the default (no dynamic styling).
1135 ///
1136 /// # Examples
1137 ///
1138 /// ```rust
1139 /// use lipgloss_tree::{Tree, Children};
1140 /// use lipgloss::Style;
1141 ///
1142 /// let tree = Tree::new()
1143 /// .child(vec!["First".into(), "Last".into()])
1144 /// .enumerator_style_func(|children, i| {
1145 /// if i == children.length() - 1 {
1146 /// Style::new().foreground("red") // Last item
1147 /// } else {
1148 /// Style::new().foreground("green") // Others
1149 /// }
1150 /// });
1151 ///
1152 /// assert!(tree.get_enumerator_style_func().is_some());
1153 /// ```
1154 pub fn get_enumerator_style_func(&self) -> Option<&crate::StyleFunc> {
1155 self.enumerator_style_func.as_ref()
1156 }
1157
1158 /// Returns the base styling configuration for this tree's child items.
1159 ///
1160 /// The item style is applied to all child item content before any
1161 /// dynamic style functions are applied. This provides a consistent
1162 /// base appearance for all children in the tree.
1163 ///
1164 /// # Returns
1165 ///
1166 /// An optional reference to the base item style. Returns `Some` if a
1167 /// custom style has been set with [`Tree::item_style`], or `None`
1168 /// if using the default (unstyled) appearance.
1169 ///
1170 /// # Examples
1171 ///
1172 /// ```rust
1173 /// use lipgloss_tree::Tree;
1174 /// use lipgloss::Style;
1175 ///
1176 /// let tree = Tree::new()
1177 /// .child(vec!["Item 1".into(), "Item 2".into()])
1178 /// .item_style(Style::new().foreground("green").italic(true));
1179 ///
1180 /// assert!(tree.get_item_style().is_some());
1181 /// ```
1182 pub fn get_item_style(&self) -> Option<&Style> {
1183 self.item_style.as_ref()
1184 }
1185
1186 /// Returns the base styling configuration for this tree's branch characters.
1187 ///
1188 /// The enumerator style is applied to all branch characters (like ├──, └──)
1189 /// before any dynamic style functions are applied. This provides consistent
1190 /// base styling for all tree branch elements.
1191 ///
1192 /// # Returns
1193 ///
1194 /// An optional reference to the base enumerator style. Returns `Some` if a
1195 /// custom style has been set with [`Tree::enumerator_style`], or `None`
1196 /// if using the default (unstyled) appearance.
1197 ///
1198 /// # Examples
1199 ///
1200 /// ```rust
1201 /// use lipgloss_tree::Tree;
1202 /// use lipgloss::Style;
1203 ///
1204 /// let tree = Tree::new()
1205 /// .child(vec!["Item 1".into(), "Item 2".into()])
1206 /// .enumerator_style(Style::new().foreground("yellow").bold(true));
1207 ///
1208 /// assert!(tree.get_enumerator_style().is_some());
1209 /// ```
1210 pub fn get_enumerator_style(&self) -> Option<&Style> {
1211 self.enumerator_style.as_ref()
1212 }
1213}
1214
1215impl Default for Tree {
1216 /// Creates a default tree instance.
1217 ///
1218 /// Equivalent to `Tree::new()` - creates an empty tree with no root value,
1219 /// no children, and default rendering settings.
1220 fn default() -> Self {
1221 Self::new()
1222 }
1223}
1224
1225impl Node for Tree {
1226 fn value(&self) -> String {
1227 self.value.clone()
1228 }
1229
1230 fn children(&self) -> Box<dyn Children> {
1231 // Return a subset of children based on offset, cloning nodes to preserve structure
1232 let start = self.offset[0];
1233 let end = if self.offset[1] == 0 {
1234 self.children.length()
1235 } else {
1236 self.children.length().saturating_sub(self.offset[1])
1237 };
1238
1239 let mut filtered_children = NodeChildren::new();
1240 for i in start..end.min(self.children.length()) {
1241 if let Some(node) = self.children.at(i) {
1242 if node.hidden() {
1243 continue;
1244 }
1245 filtered_children.append(node.clone_node());
1246 }
1247 }
1248 Box::new(filtered_children)
1249 }
1250
1251 fn hidden(&self) -> bool {
1252 self.hidden
1253 }
1254
1255 fn set_hidden(&mut self, hidden: bool) {
1256 self.hidden = hidden;
1257 }
1258
1259 fn set_value(&mut self, value: String) {
1260 self.value = value;
1261 }
1262
1263 fn get_enumerator(&self) -> Option<&crate::Enumerator> {
1264 self.enumerator.as_ref()
1265 }
1266
1267 fn get_indenter(&self) -> Option<&crate::Indenter> {
1268 self.indenter.as_ref()
1269 }
1270
1271 fn get_item_style(&self) -> Option<&Style> {
1272 self.item_style.as_ref()
1273 }
1274
1275 fn get_enumerator_style(&self) -> Option<&Style> {
1276 self.enumerator_style.as_ref()
1277 }
1278
1279 fn get_item_style_func(&self) -> Option<&crate::StyleFunc> {
1280 self.item_style_func.as_ref()
1281 }
1282
1283 fn get_enumerator_style_func(&self) -> Option<&crate::StyleFunc> {
1284 self.enumerator_style_func.as_ref()
1285 }
1286}
1287
1288impl fmt::Display for Tree {
1289 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1290 let mut renderer = crate::renderer::Renderer::new()
1291 .enumerator(self.enumerator.unwrap_or(crate::default_enumerator))
1292 .indenter(self.indenter.unwrap_or(crate::default_indenter));
1293
1294 // Build a TreeStyle snapshot from this Tree and apply to renderer
1295 let style = crate::renderer::TreeStyle {
1296 enumerator_func: self
1297 .enumerator_style_func
1298 .unwrap_or(|_, _| Style::new().padding_right(1)),
1299 item_func: self.item_style_func.unwrap_or(|_, _| Style::new()),
1300 root: self.root_style.clone().unwrap_or_default(),
1301 enumerator_base: self.enumerator_style.clone(),
1302 item_base: self.item_style.clone(),
1303 };
1304 renderer = renderer.style(style);
1305
1306 let output = renderer.render(self, true, "");
1307 write!(f, "{}", output)
1308 }
1309}
1310
1311// Direct conversions to Box<dyn Node> for the simplified API
1312impl From<&str> for Box<dyn Node> {
1313 fn from(s: &str) -> Self {
1314 Box::new(Leaf::new(s.to_string(), false))
1315 }
1316}
1317
1318impl From<String> for Box<dyn Node> {
1319 fn from(s: String) -> Self {
1320 Box::new(Leaf::new(s, false))
1321 }
1322}
1323
1324impl From<Tree> for Box<dyn Node> {
1325 fn from(tree: Tree) -> Self {
1326 Box::new(tree)
1327 }
1328}
1329
1330impl From<Leaf> for Box<dyn Node> {
1331 fn from(leaf: Leaf) -> Self {
1332 Box::new(leaf)
1333 }
1334}
1335
1336/// Creates a new tree with the specified root value.
1337///
1338/// This is a convenience function equivalent to `Tree::new().root(root)`.
1339///
1340/// # Arguments
1341///
1342/// * `root` - The root value for the tree (anything convertible to String)
1343///
1344/// # Returns
1345///
1346/// A new `Tree` instance with the specified root value
1347///
1348/// # Examples
1349///
1350/// ```rust
1351/// use lipgloss_tree::{root, Node, Children};
1352///
1353/// let tree = root("My Project")
1354/// .child(vec!["file1.txt".into(), "file2.txt".into()]);
1355///
1356/// assert_eq!(tree.value(), "My Project");
1357/// assert_eq!(tree.children().length(), 2);
1358/// ```
1359pub fn root(root: impl Into<String>) -> Tree {
1360 Tree::new().root(root)
1361}
1362
1363/// Creates a `NodeChildren` collection from string slice data.
1364///
1365/// This is a convenience function for quickly creating a collection of
1366/// leaf nodes from string data. Each string becomes a visible leaf node.
1367///
1368/// # Arguments
1369///
1370/// * `data` - A slice of string references to convert into leaf nodes
1371///
1372/// # Returns
1373///
1374/// A `NodeChildren` collection containing a leaf node for each string
1375///
1376/// # Examples
1377///
1378/// ```rust
1379/// use lipgloss_tree::{new_string_data, Children, Node};
1380///
1381/// let children = new_string_data(&["Item 1", "Item 2", "Item 3"]);
1382/// assert_eq!(children.length(), 3);
1383/// assert_eq!(children.at(0).unwrap().value(), "Item 1");
1384/// ```
1385pub fn new_string_data(data: &[&str]) -> NodeChildren {
1386 let mut result = NodeChildren::new();
1387 for &item in data {
1388 result.append(Box::new(Leaf::new(item, false)));
1389 }
1390 result
1391}
1392
1393/// A filtered view of children that applies a predicate function.
1394///
1395/// `Filter` wraps a children collection and applies a filtering function
1396/// to determine which children should be visible. Only children that pass
1397/// the filter predicate are accessible through the `Children` interface.
1398///
1399/// # Examples
1400///
1401/// ```rust
1402/// use lipgloss_tree::{Filter, new_string_data, Children};
1403///
1404/// let data = new_string_data(&["A", "B", "C", "D"]);
1405/// let filtered = Filter::new(Box::new(data))
1406/// .filter(|i| i % 2 == 0); // Only even indices
1407///
1408/// assert_eq!(filtered.length(), 2); // Only "A" and "C" are visible
1409/// ```
1410pub struct Filter {
1411 /// The underlying children collection to filter
1412 data: Box<dyn Children>,
1413 /// Optional predicate function for filtering
1414 filter: Option<Box<dyn Fn(usize) -> bool>>,
1415}
1416
1417impl Filter {
1418 /// Creates a new filter with no filtering applied.
1419 ///
1420 /// Initially, all children from the underlying data will be visible.
1421 /// Use the `filter()` method to apply filtering logic.
1422 ///
1423 /// # Arguments
1424 ///
1425 /// * `data` - The children collection to wrap and filter
1426 ///
1427 /// # Examples
1428 ///
1429 /// ```rust
1430 /// use lipgloss_tree::{Filter, new_string_data, Children};
1431 ///
1432 /// let data = new_string_data(&["Item 1", "Item 2"]);
1433 /// let filter = Filter::new(Box::new(data));
1434 /// assert_eq!(filter.length(), 2); // No filtering applied yet
1435 /// ```
1436 pub fn new(data: Box<dyn Children>) -> Self {
1437 Self { data, filter: None }
1438 }
1439
1440 /// Sets the filtering predicate function.
1441 ///
1442 /// The function receives the index of each child in the underlying
1443 /// collection and should return `true` for children that should be
1444 /// visible, `false` for children that should be hidden.
1445 ///
1446 /// # Arguments
1447 ///
1448 /// * `f` - A predicate function that takes an index and returns a boolean
1449 ///
1450 /// # Examples
1451 ///
1452 /// ```rust
1453 /// use lipgloss_tree::{Filter, new_string_data, Children, Node};
1454 ///
1455 /// let data = new_string_data(&["A", "B", "C", "D", "E"]);
1456 /// let filtered = Filter::new(Box::new(data))
1457 /// .filter(|i| i >= 2); // Only show items at index 2 and higher
1458 ///
1459 /// assert_eq!(filtered.length(), 3); // "C", "D", "E"
1460 /// assert_eq!(filtered.at(0).unwrap().value(), "C");
1461 /// ```
1462 pub fn filter<F>(mut self, f: F) -> Self
1463 where
1464 F: Fn(usize) -> bool + 'static,
1465 {
1466 self.filter = Some(Box::new(f));
1467 self
1468 }
1469}
1470
1471impl Children for Filter {
1472 fn at(&self, index: usize) -> Option<&dyn Node> {
1473 if let Some(ref filter_func) = self.filter {
1474 let mut j = 0;
1475 for i in 0..self.data.length() {
1476 if filter_func(i) {
1477 if j == index {
1478 return self.data.at(i);
1479 }
1480 j += 1;
1481 }
1482 }
1483 None
1484 } else {
1485 self.data.at(index)
1486 }
1487 }
1488
1489 fn length(&self) -> usize {
1490 if let Some(ref filter_func) = self.filter {
1491 let mut count = 0;
1492 for i in 0..self.data.length() {
1493 if filter_func(i) {
1494 count += 1;
1495 }
1496 }
1497 count
1498 } else {
1499 self.data.length()
1500 }
1501 }
1502}