27 releases (12 breaking)

Uses new Rust 2024

0.13.1 Dec 12, 2025
0.12.0 Dec 12, 2025
0.11.0 Oct 7, 2025

#1007 in Parser implementations

Download history 53/week @ 2025-11-09 236/week @ 2025-11-16 288/week @ 2025-11-23 95/week @ 2025-11-30 379/week @ 2025-12-07 200/week @ 2025-12-14 146/week @ 2025-12-21 126/week @ 2025-12-28 265/week @ 2026-01-04 293/week @ 2026-01-11 192/week @ 2026-01-18 352/week @ 2026-01-25 395/week @ 2026-02-01 173/week @ 2026-02-08 240/week @ 2026-02-15 179/week @ 2026-02-22

1,000 downloads per month
Used in 6 crates (via fast-strip-ansi)

Apache-2.0 OR MIT

125KB
3K SLoC

A streaming push parser for the VT/xterm protocol.

Use VTPushParser::feed_with to feed bytes into the parser, handling the VTEvents as they are emitted.

use vt_push_parser::VTPushParser;
use vt_push_parser::event::VTEvent;

let mut parser = VTPushParser::new();
let mut output = String::new();
parser.feed_with(b"\x1b[32mHello, world!\x1b[0m", &mut |event: VTEvent| {
    output.push_str(&format!("{:?}", event));
});
assert_eq!(output, "Csi('32', '', 'm')Raw('Hello, world!')Csi('0', '', 'm')");

Interest

The parser can be configured to only emit certain types of events by setting the INTEREST parameter. Other event types will be parsed and discarded.

For example, to only emit CSI (and Raw) events:

use vt_push_parser::{VTPushParser, VT_PARSER_INTEREST_CSI};

let mut parser = VTPushParser::new_with_interest::<VT_PARSER_INTEREST_CSI>();

Input parsing

This crate is designed to be used for parsing terminal output, but it can also be used for parsing input. Input is not always well-formed, however and may contain mode-switching escapes that require the parser to turn off its normal parsing behaviours (ie: bracketed-paste mode, xterm mouse events, etc).

The capture::VTCapturePushParser is useful for parsing input that may work in this way.


vt-push-parser

A streaming push parser for the VT protocol.

This crate provides a push parser that can be fed bytes and will emit events as they are parsed. You can easily use this as part of a push or pull pipeline.

Zero-alloc

This crate will eventually be zero-alloc, but currently it is not zero-alloc in all cases.

Example

use vt_push_parser::{VTPushParser, event::VTEvent};

let mut parser = VTPushParser::new();

// Parse ANSI colored text
parser.feed_with(b"\x1b[32mHello\x1b[0m, world!", |event: VTEvent| {
    match event {
        VTEvent::Csi(csi) if csi.final_byte == b'm' => {
            println!("SGR sequence: {:?}", csi.params);
        }
        VTEvent::Raw(text) => {
            println!("Text: {}", String::from_utf8_lossy(text));
        }
        _ => {}
    }
});

Dependencies

~245KB