Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tree Rendering

Many system tools need to display hierarchical data. cols supports this natively: mark one column as the tree column, create lines with a parent, and the print engine draws the connectors automatically. Tree depth is factored into the width calculation, so columns stay aligned regardless of nesting level.

To draw the trees, cols uses Unicode characters (this is the default), but you can enable an ASCII-only mode if you need.

Unicode (default)

use cols::{Table, Column, print_table};

fn main() {
    let mut t = Table::new();
    t.termwidth_set(40);
    t.add_column(Column::new("NAME").tree(true));

    let root = t.new_line(None);
    t.line_mut(root).data_set(0, "root");

    let c1 = t.new_line(Some(root));
    t.line_mut(c1).data_set(0, "child1");

    let c2 = t.new_line(Some(root));
    t.line_mut(c2).data_set(0, "child2");

    print_table(&t, &mut std::io::stdout().lock()).unwrap();
}
NAME
root
├─child1
└─child2

ASCII mode

use cols::{Table, Column, print_table};

fn main() {
    let mut t = Table::new();
    t.termwidth_set(40);
    t.ascii_set(true);
    t.add_column(Column::new("NAME").tree(true));
    t.add_column(Column::new("SIZE").right(true));

    let root = t.new_line(None);
    t.line_mut(root).data_set(0, "root").data_set(1, "100");

    let c1 = t.new_line(Some(root));
    t.line_mut(c1).data_set(0, "child1").data_set(1, "50");

    let c2 = t.new_line(Some(root));
    t.line_mut(c2).data_set(0, "child2").data_set(1, "30");

    let gc = t.new_line(Some(c1));
    t.line_mut(gc).data_set(0, "grandchild").data_set(1, "20");

    print_table(&t, &mut std::io::stdout().lock()).unwrap();
}
NAME           SIZE
root            100
|-child1         50
| `-grandchild   20
`-child2         30

Deep trees

The print engine handles arbitrary depth. Each level adds indentation:

root
├─child
│ └─grandchild
│   └─great-grandchild
└─sibling

Reparenting

Move a line to a different parent:

table.add_child(new_parent, child);  // removes from old parent automatically
table.remove_child(parent, child);   // detach without reattaching

How it works

The print engine does a depth-first walk from root lines at print time. Lines are stored in insertion order internally — the tree structure is defined by the parent/child relationships, not the storage order.