Ports the parsing half of ZIG/src/terminal into the ghostty-vt crate: - Parser state machine with a compile-time generated parse table and the UTF-8 decoder - OSC parser incl. all sub-parsers (titles, colors, clipboard, hyperlinks, semantic prompts/OSC 133, OSC 9 / ConEmu, iTerm2, kitty clipboard, color and text-sizing protocols, context signals) - CSI, SGR, modes table with save/restore, charsets, ansi, device status, mouse shapes, APC, DCS (incl. XTGETTCAP), tmux control-mode parser - color palette / X11 color names, kitty color and graphics command parser Deviations from Zig (documented in docs/rewrite/notes/ghostty-vt-W*.md): parser actions own their payloads instead of borrowing parser buffers; OSC strings are Vec<u8>; non-exhaustive Zig enums gain an Other(raw) variant; tmux regexes replaced by equivalent hand-written matchers. Known follow-up: semantic_prompt.rs carries local copies of the printf-q and percent decoders that belong in ghostty-os. Test Plan: - cargo test -p ghostty-vt: 395 passed, 1 ignored (skipped in Zig too) - cargo clippy -p ghostty-vt --all-targets -- -D warnings: clean
2.2 KiB
2.2 KiB
ghostty-vt W1 notes
Ported (Zig -> Rust, under crates/ghostty-vt/src)
- Parser.zig -> parser.rs (
Parser,State,TransitionAction,Action,Csi/Esc/Dcs,MAX_PARAMS,SepList) - parse_table.zig -> parse_table.rs (
TABLE, built byconst fn; identical rule order) - UTF8Decoder.zig -> utf8_decoder.rs (
Utf8Decoder::next -> (Option<u32>, bool)) - osc.zig -> osc/mod.rs; osc/encoding.zig -> osc/encoding.rs; osc/parsers/.zig -> osc/parsers/.rs (all 15)
- color.zig -> color.rs; x11_color.zig -> x11_color.rs (res/rgb.txt copied,
include_str!, lazy map); kitty/color.zig -> kitty/color.rs
Deviations / API notes
Actionowns its data (fixed inline arrays) rather than borrowing from the parser: usecsi.params(),csi.intermediates(),csi.final_,csi.params_sep.Print(u32).Parser::nextreturns[Option<Action>; 3].Parser::new();parser.osc_parser.allocis abool("allocator available", Zig?Allocator). Stream must setosc_parser.alloc = trueas stream.zig does, otherwise OSC 4/5/10-19/104/110-119/133/21 are rejected like in Zig.- OSC
Commandis a Rust enum (osc::Command,osc::KeyviaCommand::key());[:0]const u8fields areVec<u8>(no NUL, not necessarily UTF-8).Parser::endreturns an ownedOption<Command>. - Fixed buffer (MAX_BUF=2048, one byte reserved for NUL where Zig writes one) vs allocating writer = one
Vec<u8>with an optional cap.Parser::data()(reserves NUL) /buffered()(does not) replacewriter.buffered(). Remaining edge: osc9/iterm2/text_sizing usedata()even where Zig writes no NUL for some sub-commands (only differs at exactly 2048 payload bytes). - semantic_prompt:
Optionenum isOptionKey;printf_q_decode/url_percent_decodelocal copies (TODO(integration): move to/consume from ghostty-os string_encoding).color::Rgb(aliasRGB);DynamicRgb.overrideisoverride_. - Clippy: test modules
#![allow(clippy::unwrap_used)].
Skipped tests
ghostty.h Command.ProgressReport.State(C ABI),refAllDecls/test { _ = ... }comptime-reference tests, comptime@sizeOf(Command)assert.- One iterm2 test is
SkipZigTestin Zig; kept as#[ignore]. - Extra tests added: osc_112 in color parser, printf-q decode in semantic_prompt.