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

Cookbook

Complete examples showing cols in real-world scenarios. See also the examples/ directory in the repository.

lsblk-like output

A realistic example with trees, fractional widths, and multiple output modes:

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

fn main() {
    let mut t = Table::new();
    t.name_set("blockdevices");
    t.termwidth_set(80);
    t.termforce_set(TermForce::Always);
    t.add_column(
        Column::new("NAME")
            .width_fraction(0.25)
            .tree(true)
            .no_extremes(true),
    );
    t.add_column(Column::new("MAJ:MIN").width_fixed(6));
    t.add_column(Column::new("RM").width_fixed(1).right(true));
    t.add_column(Column::new("SIZE").width_fixed(5).right(true));
    t.add_column(Column::new("RO").width_fixed(1).right(true));
    t.add_column(Column::new("TYPE").width_fixed(4));
    t.add_column(Column::new("MOUNTPOINTS").width_fraction(0.1).wrap(true));

    let sda = t.new_line(None);
    t.line_mut(sda)
        .data_set(0, "sda")
        .data_set(1, "8:0")
        .data_set(2, "1")
        .data_set(3, "0B")
        .data_set(4, "0")
        .data_set(5, "disk");

    let nvme = t.new_line(None);
    t.line_mut(nvme)
        .data_set(0, "nvme0n1")
        .data_set(1, "259:0")
        .data_set(2, "0")
        .data_set(3, "931.5G")
        .data_set(4, "0")
        .data_set(5, "disk");

    let p1 = t.new_line(Some(nvme));
    t.line_mut(p1)
        .data_set(0, "nvme0n1p1")
        .data_set(1, "259:1")
        .data_set(2, "0")
        .data_set(3, "600M")
        .data_set(4, "0")
        .data_set(5, "part")
        .data_set(6, "/boot/efi");

    let p2 = t.new_line(Some(nvme));
    t.line_mut(p2)
        .data_set(0, "nvme0n1p2")
        .data_set(1, "259:2")
        .data_set(2, "0")
        .data_set(3, "2G")
        .data_set(4, "0")
        .data_set(5, "part")
        .data_set(6, "/boot");

    let p3 = t.new_line(Some(nvme));
    t.line_mut(p3)
        .data_set(0, "nvme0n1p3")
        .data_set(1, "259:3")
        .data_set(2, "0")
        .data_set(3, "928.9G")
        .data_set(4, "0")
        .data_set(5, "part");

    let luks = t.new_line(Some(p3));
    t.line_mut(luks)
        .data_set(0, "luks-62d09206-d2b0-48d8-9164-a8487c42e31b")
        .data_set(1, "252:0")
        .data_set(2, "0")
        .data_set(3, "928.9G")
        .data_set(4, "0")
        .data_set(5, "crypt")
        .data_set(6, "/home");

    print_table(&t, &mut std::io::stdout().lock()).unwrap();
}

Normal output:

NAME               MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
sda                8:0      1     0B  0 disk  
nvme0n1            259:0    0 931.5G  0 disk  
├─nvme0n1p1        259:1    0   600M  0 part  /boot/efi
├─nvme0n1p2        259:2    0     2G  0 part  /boot
└─nvme0n1p3        259:3    0 928.9G  0 part  
  └─luks-62d09206-d2b0-48d8-9164-a8487c42e31b 252:0    0 928.9G  0 crypt /home

Group members only

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

fn main() {
    let mut t = Table::new();
    t.termwidth_set(40);
    t.termforce_set(TermForce::Always);
    t.headings_set(false);
    t.new_column("NAME");
    t.add_column(Column::new("SIZE").right(true));

    let g = t.new_group();

    let l1 = t.new_line(None);
    t.line_mut(l1).data_set(0, "alpha").data_set(1, "10");

    let l2 = t.new_line(None);
    t.line_mut(l2).data_set(0, "beta").data_set(1, "20");

    let l3 = t.new_line(None);
    t.line_mut(l3).data_set(0, "gamma").data_set(1, "30");

    t.group_add_member(g, l1);
    t.group_add_member(g, l2);
    t.group_add_member(g, l3);

    print_table(&t, &mut std::io::stdout().lock()).unwrap();
}

Output:

┌─alpha   10
├─beta    20
└─gamma   30

Filtering lines before display

use cols::{Table, Filter, print_table_to_string};

fn main() {
    let mut table = Table::new();
    table.new_column("NAME");
    table.new_column("SIZE");

    let data = vec![("sda", "1073741824"), ("sdb", "536870912"), ("sr0", "0")];
    for (name, size) in &data {
        let row = table.new_line(None);
        table.line_mut(row).data_set(0, name).data_set(1, size);
    }

    let filter = Filter::parse("SIZE > 512M").unwrap();

    let mut filtered = Table::new();
    filtered.new_column("NAME");
    filtered.new_column("SIZE");

    for id in table.line_ids() {
        let line = table.line(id);
        let matches = filter.evaluate(|col| match col {
            "NAME" => line.data_get(0).map(String::from),
            "SIZE" => line.data_get(1).map(String::from),
            _ => None,
        }).unwrap();

        if matches {
            let row = filtered.new_line(None);
            filtered.line_mut(row)
                .data_set(0, line.data_get(0).unwrap_or(""))
                .data_set(1, line.data_get(1).unwrap_or(""));
        }
    }

    let output = print_table_to_string(&filtered).unwrap();
    assert!(output.contains("sda"));
    assert!(!output.contains("sr0"));
}