Ports the parts of Ghostty's IO layer that don't depend on the terminal: - pty.zig: pty pair, window size, mode, child-side setsid/TIOCSCTTY; master is CLOEXEC with IUTF8 set - Command.zig: fork/execvpe with Ghostty's exact child setup (stdio dup2, best-effort chdir, rlimit restore, os/runtime pre-exec hooks, cgroup handling) and exit status decoding - shell_integration.zig for bash/zsh/fish/elvish/nushell plus feature flags; scripts copied verbatim to resources/shell-integration/ - terminfo generator for xterm-ghostty, byte-identical to Zig's encode output (golden file produced with the real Zig code) This crate opts into unsafe_code = "deny" (fork/exec need it) with allow + SAFETY comments on minimal items. Integration left: config-derived option types are local stand-ins; cgroup D-Bus scope creation is a closure hook; Exec/Termio/Thread/ stream_handler wait for ghostty-terminal. Pty now closes both fds on drop (Zig never auto-closed the slave) - to re-check when wiring Exec. Test Plan: - cargo test -p ghostty-termio (52 tests, incl. real pty spawn test expecting "hi\r\n31 97\r\n" from `echo hi; stty size`)
35 lines
1.0 KiB
Rust
35 lines
1.0 KiB
Rust
//! The terminfo source emitted by the Rust port must be byte-identical to the
|
|
|
|
#![allow(clippy::unwrap_used)]
|
|
//! output of the Zig `terminfo/ghostty.zig` `encode` (golden file generated
|
|
//! with the Zig reference implementation).
|
|
|
|
use ghostty_termio::terminfo;
|
|
|
|
#[test]
|
|
fn terminfo_source_matches_zig_output() {
|
|
let expected = include_str!("data/xterm-ghostty.terminfo");
|
|
assert_eq!(expected, terminfo::ghostty.encode_to_string());
|
|
}
|
|
|
|
#[test]
|
|
fn terminfo_compiles_with_tic_if_available() {
|
|
let Ok(dir) = std::env::var("CARGO_TARGET_TMPDIR") else {
|
|
return;
|
|
};
|
|
let src = std::path::Path::new(&dir).join("xterm-ghostty.src");
|
|
std::fs::write(&src, terminfo::ghostty.encode_to_string()).unwrap();
|
|
let out = std::path::Path::new(&dir).join("terminfo-out");
|
|
let _ = std::fs::create_dir_all(&out);
|
|
let Ok(status) = std::process::Command::new("tic")
|
|
.arg("-x")
|
|
.arg("-o")
|
|
.arg(&out)
|
|
.arg(&src)
|
|
.status()
|
|
else {
|
|
return; // tic not installed
|
|
};
|
|
assert!(status.success());
|
|
}
|