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

Streaming

The standard print_table API requires building the entire table in memory before printing. For large or unbounded datasets, the streaming writer lets you output rows immediately as data arrives.

Basic usage

Configure columns on a Table as usual, then create a streaming writer. The writer prints the header (if enabled) and any opening syntax automatically. Build rows with begin_row, populate them with set, then call finish to flush each row. Call close when done.

use cols::{Table, Column};

fn main() {
    let mut table = Table::new();
    table.add_column(Column::new("NAME").width_fixed(10));
    table.add_column(Column::new("SIZE").width_fixed(6).right(true));

    let stdout = std::io::stdout();
    let mut out = stdout.lock();
    let mut w = table.streaming_writer(&mut out).unwrap();

    w.begin_row(None).set("NAME", "sda").set("SIZE", "100G").finish().unwrap();
    w.begin_row(None).set("NAME", "sdb").set("SIZE", "50G").last(true).finish().unwrap();

    w.close().unwrap();
}

Setting cell data

Use set() to populate cells. It accepts both column names and indices via the ColumnKey trait:

row.set("NAME", "sda");  // by column name
row.set(0, "sda");       // by column index

Both can be mixed freely on the same row.

Output modes

The streaming writer supports all output modes. Set the mode on the table before creating the writer:

table.output_mode_set(OutputMode::Json);
table.name_set("devices");
let mut w = table.streaming_writer(&mut out).unwrap();

For Normal and Markdown modes, columns should have fixed width hints (width_fixed) since the writer can’t scan all data upfront to calculate widths.

Tree streaming

Pass a parent RowId to begin_row to build tree hierarchies incrementally. Call .last(true) on the row builder to mark a row as the last child of its parent – this controls whether a └─ (last) or ├─ (more siblings) connector is drawn.

use cols::{Table, Column};

fn main() {
    let mut table = Table::new();
    table.headings_set(false);
    table.add_column(Column::new("NAME").width_fixed(20).tree(true));
    table.add_column(Column::new("SIZE").width_fixed(8).right(true));

    let stdout = std::io::stdout();
    let mut out = stdout.lock();
    let mut w = table.streaming_writer(&mut out).unwrap();

    let root = w.begin_row(None)
        .set("NAME", "sda").set("SIZE", "500G")
        .last(true)
        .finish().unwrap();

    w.begin_row(Some(root))
        .set("NAME", "sda1").set("SIZE", "256M")
        .finish().unwrap();

    w.begin_row(Some(root))
        .set("NAME", "sda2").set("SIZE", "250G")
        .last(true)
        .finish().unwrap();

    w.close().unwrap();
}

Output:

sda                       500G
├─sda1                    256M
└─sda2                    250G

This is particularly useful for recursive directory walkers, process trees, or any case where the data is discovered incrementally.

Limitations

  • Sorting is not supported in streaming mode (it requires all data).
  • Group rendering is not supported.
  • Auto-sized columns (no width hint) work for Raw, CSV, Export, ShellVar, and JSON modes, but Normal and Markdown modes need fixed widths since the writer can’t pre-scan the data.