# 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
```

---
## 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:
```
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
```rust
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:

---
## 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:
```rust
["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](https://gitlab.com/lilo_booter/nestable-rust)