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

Output Modes

One of the key strengths of cols is that the same table can be rendered in multiple formats without rebuilding it. This is how tools like lsblk offer --json, --raw, and --export flags from a single data model. Set the output mode before printing:

use cols::OutputMode;

table.output_mode_set(OutputMode::Json);

Normal

The default. Human-readable columnar output with padding and alignment.

NAME         SIZE
sda          100G
sdb           50G

Raw

Compact, separator-delimited, no padding. Good for piping to awk or cut.

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

fn main() {
    let mut t = Table::new();
    t.output_mode_set(OutputMode::Raw);
    t.new_column("NAME");
    t.new_column("SIZE");

    let l1 = t.new_line(None);
    t.line_mut(l1).data_set(0, "sda").data_set(1, "100G");
    let l2 = t.new_line(None);
    t.line_mut(l2).data_set(0, "sdb").data_set(1, "50G");

    print_table(&t, &mut std::io::stdout().lock()).unwrap();
}
NAME SIZE
sda 100G
sdb 50G

Export

NAME="value" pairs, one line per row. Useful for shell eval:

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

fn main() {
    let mut t = Table::new();
    t.output_mode_set(OutputMode::Export);
    t.new_column("NAME");
    t.new_column("SIZE");

    let l1 = t.new_line(None);
    t.line_mut(l1).data_set(0, "sda").data_set(1, "100G");
    let l2 = t.new_line(None);
    t.line_mut(l2).data_set(0, "sdb").data_set(1, "50G");

    print_table(&t, &mut std::io::stdout().lock()).unwrap();
}
NAME="sda" SIZE="100G"
NAME="sdb" SIZE="50G"

ShellVar

Like Export, but column names are sanitized for shell variables (non-alphanumeric characters become _):

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

fn main() {
    let mut t = Table::new();
    t.output_mode_set(OutputMode::ShellVar);
    t.add_column(Column::new("MAJ:MIN"));
    t.new_column("NAME");
    t.new_column("SIZE");

    let r1 = t.new_line(None);
    t.line_mut(r1)
        .data_set(0, "8:0")
        .data_set(1, "sda")
        .data_set(2, "100G");
    let r2 = t.new_line(None);
    t.line_mut(r2)
        .data_set(0, "8:1")
        .data_set(1, "sda1")
        .data_set(2, "50G");

    print_table(&t, &mut std::io::stdout().lock()).unwrap();
}
MAJ_MIN="8:0" NAME="sda" SIZE="100G"
MAJ_MIN="8:1" NAME="sda1" SIZE="50G"

JSON

Structured JSON output. The table name becomes the top-level key:

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

fn main() {
    let mut t = Table::new();
    t.name_set("devices");
    t.output_mode_set(OutputMode::Json);
    t.new_column("NAME");
    t.new_column("SIZE");

    let l1 = t.new_line(None);
    t.line_mut(l1).data_set(0, "sda").data_set(1, "100G");
    let l2 = t.new_line(None);
    t.line_mut(l2).data_set(0, "sdb").data_set(1, "50G");

    print_table(&t, &mut std::io::stdout().lock()).unwrap();
}
{
   "devices": [
      {
         "name": "sda",
         "size": "100G"
      },
      {
         "name": "sdb",
         "size": "50G"
      }
   ]
}

JSON keys

Column names are lowercased for JSON object keys (e.g. "NAME" becomes "name"). To use a custom key, set it on the column:

Column::new("MAJ_MIN").json_key("majmin")

JSON types

By default all values are strings. Set a JSON type on the column to control serialization:

use cols::{Column, JsonType};

Column::new("COUNT").json_type(JsonType::Number);    // 42
Column::new("LOAD").json_type(JsonType::Float);      // 3.14
Column::new("ACTIVE").json_type(JsonType::Boolean);  // true
Column::new("TAGS").json_type(JsonType::ArrayString); // ["a", "b"]

BooleanOptional renders as null when the cell is empty, instead of false.

CSV

RFC 4180-compliant CSV output. Fields containing commas, quotes, or newlines are automatically quoted.

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

fn main() {
    let mut t = Table::new();
    t.output_mode_set(OutputMode::Csv);
    t.new_column("NAME");
    t.new_column("SIZE");

    let l1 = t.new_line(None);
    t.line_mut(l1).data_set(0, "sda").data_set(1, "100G");
    let l2 = t.new_line(None);
    t.line_mut(l2).data_set(0, "sdb").data_set(1, "50G");

    print_table(&t, &mut std::io::stdout().lock()).unwrap();
}
NAME,SIZE
sda,100G
sdb,50G

Markdown

Pipe-delimited markdown table with aligned columns. Pipes and backslashes in data are escaped; newlines become <br>.

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

fn main() {
    let mut t = Table::new();
    t.output_mode_set(OutputMode::Markdown);
    t.new_column("NAME");
    t.add_column(Column::new("SIZE").right(true));

    let l1 = t.new_line(None);
    t.line_mut(l1).data_set(0, "sda").data_set(1, "100G");
    let l2 = t.new_line(None);
    t.line_mut(l2).data_set(0, "sdb").data_set(1, "50G");

    print_table(&t, &mut std::io::stdout().lock()).unwrap();
}
| NAME | SIZE |
| ---- | ---: |
| sda  | 100G |
| sdb  |  50G |

Configuration

Additional settings that affect output:

table.headings_set(false);                  // suppress the header row
table.column_separator_set("|");            // between columns (default: " ")
table.line_separator_set("\n");             // between rows (default: "\n")
table.line_separator_enabled_set(false);    // suppress line separators entirely
table.encoding_set(false);                  // pass control characters through raw
table.ascii_set(true);                      // ASCII symbols instead of Unicode