Resolves the 6 differential gap groups in docs/rewrite/notes/review- rv9-codex.md (details in final-Z11.md): - ghostty_os::zig_fmt ports std.fmt.parseInt/parseUnsigned/parseFloat (underscores, 0x/0o/0b prefixes, hex floats, inf/nan) with the Zig std tests and replaces every int/float parse in config, keybind parameters, ssh-cache and desktop detection. - Interior NUL no longer panics in font names and ends C strings like Zig's backing bytes (fontconfig, C config getters, title actions, clipboard callback, relative paths, config-file, shaders, background image, GTK CSS). - GTK new-window arguments are trimmed of ASCII whitespace only. - Command tokenization uses a port of std.process.ArgIteratorGeneral (incl. CR/LF separators) with its std tests. - UTF-8 validation happens where Zig's field parsers do it, so error kinds match (metric modifiers, quick-terminal size, link, ...). A scripted differential run of 202 fields x ~220 hostile/valid values against /usr/bin/ghostty (+validate-config and +show-config: exit code, stdout, stderr) now has zero mismatches besides build-specific defaults (theme resources path, auto-update-channel, gtk-opengl-debug); it also surfaced and fixed background-blur failure state, NaN formatting and NaN/-0 finalize clamps. Regression tests: ghostty-config/tests/ zig_parity.rs. Test Plan: - cargo test --workspace --no-fail-fast (3456 passed, exit 0) - just check-macos (both), just check-windows, just check-wasm
4.2 KiB
4.2 KiB
Z11: RV9 gap groups (Ghostty 1.3.1 parity)
Fixes for the six gap groups in review-rv9-codex.md. No version change, no commit.
Fixes
- Interior NUL in font names.
fontconfig::Pattern::add_string_bytesends the value at the first NUL (the C-string handoff Zig does) instead of failing, sofont-family,font-styleand codepoint-map families no longer hit theassert!indiscovery::to_fc_pattern. Test:discovery::tests::interior_nul_in_font_names_ends_the_c_string. - Numeric grammars. New
ghostty_os::zig_fmt: exact ports ofstd.fmt.parseInt/parseUnsigned(underscores,0b/0o/0xin both cases, sign rules,len > 2prefix gate, Overflow vs InvalidCharacter) andstd.fmt.parseFloat(grammar ofparse.zigincl.validUnderscores, hex floats via a port ofconvertHexincl. the many-digits path,inf/infinity/nan). Decimal values are rounded by Rust's correctly roundedFromStronce the Zig grammar accepted the text. Ported all std tests. Used by: primitive int/float fields (base 0), palette key (u8, base 0, Zig error names), variation values, mouse-scroll bare float, quick-terminalpx/%, window-padding (u32, base 10), duration (parseUnsignedu64), background-blur radius, codepoint/clipboard map hex (base 16), metric modifiers, keybind numeric parameters (base 10 / float), ssh-cache entry timestamp,GIO_LAUNCHED_DESKTOP_FILE_PID. Also found by differential runs: Zig{d}printsnan(RustNaN); finalize clamps use Zig@min/@max/clampNaN and +-0 semantics (cli_args::zig_min/zig_max/zig_clamp); a failedbackground-blurradius parse leavesradius(0 or the previous radius) like Zig's in-place union initialisation. - C strings.
config_capigetters, C action titles/strings (action_c::Keep) and the embedded clipboard write callback now end the C string at the first NUL instead of deleting NUL bytes. - GTK new-window args.
--working-directory=/--title=trim onlystd.ascii.whitespace(space, \t, \n, \r, VT, FF); U+00A0 etc. survive. - Shell tokenizer. New
ghostty_os::arg_iterator::ArgIteratorGeneral(port ofstd.process.ArgIteratorGeneral, includingcomments/single_quotesoptions,skip, NUL terminates).Command::arg_iterator(and so shell-integration detection) use it: space, tab, CR and LF split. Ported the std "response file arg parsing" test plus separator/quote/NUL tests; termio testdetect_shell_splits_on_all_zig_separators. - Parser diagnostics. UTF-8 validation moved to where Zig would notice it:
metric modifiers (
InvalidFormat), quick-terminal size (MissingUnit/InvalidValue),link(NotImplemented), colors/palette (InvalidCharacter), background-blur, keybind trigger (parsed after the action, likeParser.init) and action parameters (known action with bad bytes isInvalidFormat, unknown nameInvalidAction). Other differences found: config-file open errors are printed aserror.FileNotFoundetc.; paths with interior NUL resolve/open as the C string prefix (EncodedOs::to_syscall_path) for relative path expansion,config-file, custom shaders, background image, gtk css.
Differential harness
Script (not committed): for each of the 202 Config.zig fields x ~220 hostile
and valid values, run /usr/bin/ghostty +validate-config --config-file=F and
+show-config (value in $XDG_CONFIG_HOME/ghostty/config) against the Rust
binary and compare exit code, stdout and stderr. Final state: zero mismatches
except theme (resources path differs by install location),
auto-update-channel default (tip vs stable, build channel) and
gtk-opengl-debug (debug build).
Regression tests: crates/ghostty-config/tests/zig_parity.rs,
ghostty_os::zig_fmt::tests, ghostty_os::arg_iterator::tests,
ghostty-config command tests, lib/gtk tests listed above.
Not covered / notes
ghostty-terminalOSC/tmux/kitty parsers also callparseInt(terminal/osc/parsers/*.zig,tmux/*.zig,kitty/*.zig); they are outside the config/input scope of this task and still use Ruststr::parse/from_str_radix.zig_fmtis available for a follow-up.- Windows/macOS behaviour is covered by cross-checks only.