tty#
Terminal styling and layout widgets for OCaml CLI applications.
╭──────────────────────────────────────────────────────────────────╮
│ │
│ ████████╗████████╗██╗ ██╗ │
│ ╚══██╔══╝╚══██╔══╝╚██╗ ██╔╝ │
│ ██║ ██║ ╚████╔╝ │
│ ██║ ██║ ╚██╔╝ │
│ ██║ ██║ ██║ │
│ ╚═╝ ╚═╝ ╚═╝ │
│ │
│ Type-safe terminal styling and layout widgets for OCaml │
│ │
╰──────────────────────────────────────────────────────────────────╯
What it looks like#
Tables#
╭──────────┬────────┬─────────┬──────────┬─────────┬───────────╮
│ Target │ Inst. │ Execs │ Paths │ Crashes │ Exec/s │
├──────────┼────────┼─────────┼──────────┼─────────┼───────────┤
│ cbort │ 3 │ 1.2M │ 847 │ 0 │ 4,521 │
│ yamlrw │ 3 │ 890K │ 1,203 │ 2 │ 3,102 │
│ jsonwt │ 2 │ 2.1M │ 412 │ 0 │ 6,847 │
╰──────────┴────────┴─────────┴──────────┴─────────┴───────────╯
Trees#
src
├── lib
│ ├── tty.ml
│ ├── style.ml
│ └── table.ml
├── bin
│ └── main.ml
└── test
└── test_tty.ml
Panels#
╭─────────────────────── Status ───────────────────────╮
│ │
│ ✓ All systems operational │
│ ✓ Database connected │
│ ✓ Cache warmed │
│ │
╰──────────────────────────────────────────────────────╯
Border Styles#
ASCII: Single: Rounded: Heavy:
+-------+ ┌───────┐ ╭───────╮ ┏━━━━━━━┓
| hello | │ hello │ │ hello │ ┃ hello ┃
+-------+ └───────┘ ╰───────╯ ┗━━━━━━━┛
Double:
╔═══════╗
║ hello ║
╚═══════╝
Features#
- Composable styles:
Style.(bold + fg Color.red + underline) - Full color support: ANSI 16, 256-color palette, true color (RGB/hex)
- Tables: Headers, alignment, multiple border styles
- Trees: Directory-style tree rendering with guides
- Panels: Bordered boxes with titles
- Unicode-aware: Proper width calculation for CJK and emoji
Installation#
opam install tty
Quick Start#
Styled Text#
open Tty
(* Compose styles with + *)
let success = Style.(bold + fg Color.green)
let error = Style.(bold + fg Color.red)
let warning = Style.(fg Color.yellow)
let () =
Fmt.pr "%a@." (Style.styled success Fmt.string) "✓ Build passed";
Fmt.pr "%a@." (Style.styled error Fmt.string) "✗ Tests failed";
Fmt.pr "%a@." (Style.styled warning Fmt.string) "⚠ Deprecation warning"
Tables#
open Tty
let () =
let table = Table.(
of_rows ~border:Border.rounded
[ column "Name"; column ~align:`Right "Size"; column "Modified" ]
[
[ Span.text "README.md"; Span.text "2.4K"; Span.text "2 hours ago" ];
[ Span.text "src/"; Span.text "4.0K"; Span.text "yesterday" ];
[ Span.text "Makefile"; Span.text "892"; Span.text "3 days ago" ];
]
) in
Table.pp Format.std_formatter table
Output:
╭───────────┬──────┬─────────────╮
│ Name │ Size │ Modified │
├───────────┼──────┼─────────────┤
│ README.md │ 2.4K │ 2 hours ago │
│ src/ │ 4.0K │ yesterday │
│ Makefile │ 892 │ 3 days ago │
╰───────────┴──────┴─────────────╯
Trees#
open Tty
let () =
let tree = Tree.of_tree (
Node (Span.text "myproject", [
Node (Span.text "src", [
Node (Span.text "main.ml", []);
Node (Span.text "lib.ml", []);
]);
Node (Span.text "test", [
Node (Span.text "test_main.ml", []);
]);
Node (Span.text "dune-project", []);
])
) in
Tree.pp Format.std_formatter tree
Output:
myproject
├── src
│ ├── main.ml
│ └── lib.ml
├── test
│ └── test_main.ml
└── dune-project
Panels#
open Tty
let () =
let panel = Panel.create
~border:Border.rounded
~title:(Span.text "Summary")
(Span.text "Processed 1,234 files\nFound 42 issues\nFixed 38 automatically")
in
Panel.pp Format.std_formatter panel
Output:
╭─────────────────────── Summary ────────────────────────╮
│ Processed 1,234 files │
│ Found 42 issues │
│ Fixed 38 automatically │
╰────────────────────────────────────────────────────────╯
Colors#
open Tty
(* ANSI 16 colors *)
let red = Color.red
let bright_blue = Color.bright_blue
(* RGB colors *)
let coral = Color.rgb 255 127 80
let teal = Color.rgb 0 128 128
(* Hex colors *)
let purple = Color.hex "#8B5CF6"
let orange = Color.hex "F97316"
(* 256-color palette *)
let pink = Color.palette 213
(* Use in styles *)
let gradient_style = Style.(fg coral + bg (Color.rgb 30 30 30))
Styles#
Available style attributes:
| Attribute | Example |
|---|---|
bold |
bold text |
faint |
dimmed text |
italic |
italic text |
underline |
underlined text |
blink |
blinking text |
reverse |
inverted colors |
strikethrough |
|
fg color |
coloured foreground |
bg color |
coloured background |
(* Combine any attributes *)
let fancy = Style.(bold + italic + underline + fg Color.cyan + bg Color.black)
API Reference#
| Module | Description |
|---|---|
Tty.Color |
ANSI, RGB, hex, and 256-palette colors |
Tty.Style |
Composable text styles |
Tty.Span |
Styled text spans |
Tty.Border |
Border styles (ascii, single, double, rounded) |
Tty.Table |
Tables with headers and alignment |
Tty.Tree |
Tree rendering with guides |
Tty.Panel |
Bordered panels with titles |
Tty.Width |
Unicode-aware string width calculation |
Related Work#
- Rich - Python library for rich text and beautiful formatting. Primary inspiration.
- lipgloss - Go library for terminal styling. Inspiration for composable style API.
- printbox - OCaml library for printing nested boxes, tables and trees.
- progress - Terminal progress bars for OCaml.
- notty - OCaml library for declarative terminal graphics.
Licence#
MIT License. See LICENSE.md for details.