nestable 0.2.3

Unicode-aware text table rendering with support for nested tables
Documentation

nestable

A small Rust library for rendering text tables in the terminal.

Supports:

  • multi-line cells
  • Unicode (including emoji)
  • ANSI styling (colours, bold, etc.) on column, row or cell basis
  • alignment on column, row or cell basis
  • nested tables (via pre-rendering)

Demonstration

There is a demo to be found in examples/demo.rs. To build and run it, use:

cargo run --example demo

demo


Command Line Utility

Despite being mostly developed as a rust library with minimal ddependencies, it also provides a nestable command line tool which can render CSV inputs from stdin and can be used as follows:

cat file.csv | nestable

This provides incredibly limited functionality at the moment will be fleshed out with a proper implementation of RFC-4180 at a later point.

Library Example

use nestable::*;

fn main() {
    #[rustfmt::skip]
    let table = Table::new()
        .add_rows([
            ["Language", "Text"],
            ["English", "nestable\nrendering tables\nacross multiple lines"],
            ["Japanese", "ネスタブル\n複数行にわたる\nテーブル表示 🙂"],
            ["Chinese\n(Simplified)", "可嵌套表格\n支持多行文本\n终端显示"],
            ["Korean", "중첩 가능한 테이블\n여러 줄 텍스트\n터미널 출력"],
            ["Persian", "جداول تو در تو\nمتن چند خطی\nخروجی ترمینال"],
            ["Sanskrit", "नेस्टेबल टेबल्स\nबहुपङ्क्तिः पाठः\nटर्मिनल आउटपुट"],
        ]);

    let cwd = std::env::current_dir()
        .map(|p| p.to_string_lossy().to_string())
        .unwrap_or_else(|_| "<unknown>".to_string());

    let user = std::env::var("USER")
        .map(|p| p.to_string())
        .unwrap_or_else(|_| "<unknown>".to_string());

    #[rustfmt::skip]
    let system = Table::new()
        .add_rows( [
            ["Property", "Value"],
            ["OS", std::env::consts::OS],
            ["Architecture", std::env::consts::ARCH],
            ["Directory", &cwd],
            ["User", &user],
        ]);

    #[rustfmt::skip]
    let nested = Table::new()
        .add_rows([
            vec!["System Details", "Unicode Demo"],
            vec![&system.to_string(), &table.to_string()],
        ]);

    print!("{}", nested);
}

Example output:

demo


Design

This crate uses a simple two-phase approach:

  1. Input model Rows are defined as collections of strings.

  2. Layout model Cells are split into lines, widths are computed, and a layout is derived before rendering.

Rendering is then performed from the computed layout.


ANSI handling

  • ANSI escape sequences are preserved in output
  • Display width is calculated while ignoring ANSI sequences
  • Non-SGR escape sequences are not supported and may be ignored or warned about

Nested tables

Nested tables are supported by rendering them to strings:

["outer", &inner.to_string()]

Note: nested tables are rendered independently and are not resized based on the outer table.


Limitations

  • No automatic text wrapping
  • Layout is content-driven (columns expand to fit content)
  • No column/row alignment options (yet)
  • No true column spanning (only implicit “fill to end” behaviour)
  • ANSI parsing is minimal (focused on common styling sequences)

Styling

Several predefined styles are available:

  • GLYPHS_ROUNDED
  • GLYPHS_SQUARE
  • GLYPHS_NO_BORDER
  • GLYPHS_NO_ROW_SEPARATOR
  • ASCII_BORDER
  • ASCII_NO_BORDER
  • ASCII_NO_ROW_SEPARATOR

Optionally, the first row can be inverted.

Example:

use nestable::*;

let table = Table::new()
    .add_rows([
        ["a", "b"],
        ["c", "d"],
	])
	.set_table_style(styles::GLYPHS_ROUNDED)
	.set_inverted_header(false);

println!("{}", table);

License

MIT

Author

Charles Yates

Contributing / Feedback

Questions, suggestions, and bug reports are welcome via GitLab issues.

glilab nestable-rust repo