vtty/lib.rs
1// Copyright © Fangdun Tsai <fundon@pindash.io>
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Zero-allocation, panic-free DEC VT500 terminal parser with UTF-8 decoding
5//! and `no_std` support.
6//!
7//! ## Usage
8//!
9//! ```rust,ignore
10//! use vtty::{Parser, Perform};
11//!
12//! struct Screen;
13//!
14//! impl Perform for Screen {
15//! fn print_bytes(&mut self, s: &[u8]) { /* printable ASCII run */ }
16//! fn print(&mut self, c: char) { /* non-ASCII code point */ }
17//! fn execute(&mut self, b: u8) { /* \n \t \x1b … */ }
18//! fn csi_dispatch(&mut self, params: &[i32], sep: u16, intermediates: &[u8], final_byte: u8) {
19//! /* CSI Ps ; Ps final */
20//! }
21//! fn osc_dispatch(&mut self, params: &[&[u8]], bell: bool) { /* OSC */ }
22//! }
23//!
24//! let mut parser = Parser::new();
25//! parser.advance(&mut screen, b"\x1b[1;31mhello\x1b[0m");
26//!
27//! // With the `simd-transcode` feature enabled, opt into SIMD scanning,
28//! // validation and UTF-8→UTF-32 transcode:
29//! let mut parser = Parser::with_simd();
30//! parser.advance(&mut screen, b"\x1b[1;31mhello\x1b[0m");
31//! ```
32//!
33//! Also available: `Event`/`Recording` (owned enum API), `State` (byte-cursor
34//! sink with line/cursor geometry), `Reply` (query reply builder), and
35//! `ColorId`, `SgrFlags`, `TermFlags`, `KittyFlags`, `MouseButton`, `Charset`, `Cap`.
36//!
37//! ## Design
38//!
39//! - **Panic-free** — `#![forbid(unsafe_code)]`; malformed PTY input never
40//! crashes.
41//! - **Zero-allocation hot path** — one `print_bytes` per ASCII run, one
42//! `print_codepoints` per non-ASCII run; CSI/OSC/DCS state is inline.
43//! - **`no_std` by default** — optional `simd` (scanning + validation) and
44//! `simd-transcode` (UTF-8→UTF-32) features, enabled per parser.
45//! - **W3C-correct UTF-8** — maximal-subpart substitution; 8-bit clean
46//! (DEC “anywhere”).
47//!
48//! ## Test
49//!
50//! ```bash
51//! cargo test -p vtty
52//! cargo test -p vtty --test vt_differential -- --nocapture # parity vs vte
53//! ```
54#![forbid(unsafe_code)]
55#![cfg_attr(not(feature = "simd"), no_std)]
56#![expect(
57 clippy::cast_possible_truncation,
58 reason = "Terminal cell/pixel math truncates widths and coordinates to fixed-size types where the range is known-safe"
59)]
60// The parser must never panic on untrusted input (a malformed PTY stream is
61// normal, not exceptional). These lints keep `unwrap`/`expect`/`panic` out.
62#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
63#![warn(missing_debug_implementations)]
64#![deny(missing_docs)]
65
66extern crate alloc;
67
68mod charset;
69mod color;
70mod hex;
71mod keyboard;
72mod mode;
73mod mouse;
74mod parser;
75mod perform;
76mod recording;
77mod reply;
78#[cfg(feature = "simd")]
79mod simd;
80mod state;
81mod style;
82mod table;
83mod termcap;
84mod utf8;
85#[cfg(feature = "simd-transcode")]
86mod utf8_tables;
87
88pub use charset::{Charset, Charsets, dec_special_graphics};
89pub use color::{ColorId, DEFAULT_BG_ID, DEFAULT_FG_ID};
90pub use hex::{hex_decode, hex_encode};
91pub use keyboard::KittyFlags;
92pub use mode::{MOUSE_MASK, TermFlags};
93pub use mouse::{MouseButton, MouseTracking};
94pub use parser::Parser;
95pub use perform::Perform;
96pub use recording::{Event, Recording};
97pub use reply::Reply;
98pub use state::State;
99pub use style::{CursorStyle, SgrFlags, StyleFlags, UnderlineStyle};
100pub use termcap::{Cap, CapValue};