Skip to main content

ansi/
lib.rs

1//! ansi: ANSI/VT terminal output as data, on the Rust standard library
2//! alone. Zero dependencies.
3//!
4//! Three tightly-related capabilities, all pure bytes in / bytes out:
5//!
6//! * **Build** styled output: [`Style`] + [`Color`] render to SGR escape
7//!   sequences, absolutely ([`Style::sgr`]) or as a minimal transition from a
8//!   previous style ([`Style::transition_to`]).
9//! * **Parse** a terminal byte stream incrementally: [`Parser::feed`] accepts
10//!   chunks split at *any* byte boundary (mid-escape, mid-UTF-8) and yields
11//!   [`Token`]s (text runs, C0 controls, CSI/ESC/OSC sequences).
12//!   [`Parser::feed_with`] is the same machine without the allocation: it
13//!   hands a closure borrowed [`Event`]s instead.
14//! * **Render by diff**: [`Screen`] is a grid of styled [`Cell`]s;
15//!   [`Screen::diff`] emits the minimal cursor-move/SGR/text bytes that turn
16//!   one screen into another, and [`Screen::render_full`] repaints from
17//!   scratch.
18//!
19//! ```
20//! use ansi::{Color, Style};
21//!
22//! let style = Style { bold: true, fg: Color::Indexed(2), ..Style::default() };
23//! assert_eq!(style.sgr(), "\x1b[0;1;32m");
24//!
25//! let mut p = ansi::Parser::new();
26//! let tokens = p.feed(b"hi\x1b[1;31mred");
27//! assert_eq!(tokens.len(), 3); // Text("hi"), Csi(SGR 1;31), Text("red")
28//! ```
29//!
30//! There is no I/O here: no raw mode, no stdin/stdout, no PTY. Those are the
31//! `rawterm` and `pty` crates' concerns; this crate turns bytes into meaning
32//! and meaning into bytes.
33
34mod history;
35mod marks;
36mod parse;
37mod screen;
38mod style;
39
40pub use marks::{MarkKind, MarkScanner, ShellMark};
41pub use parse::{Event, Parser, Token, Utf8Decoder};
42pub use screen::{Cell, CellWidth, Cursor, Screen};
43pub use style::{Color, Style};