feat(cli): port ghostty +action CLI commands

Ports ZIG/src/cli into ghostty-cli: action detection/dispatch with
per-action --help, and the actions help, version, list-actions,
list-colors, list-keybinds, list-themes (plain listing plus an
interactive ratatui browser mirroring Ghostty's libvaxis UI),
show-config, validate-config, edit-config, crash-report (listing),
ssh-cache and boo (235 embedded frames).

Verified byte-for-byte against the installed Ghostty 1.3.1 for stdout,
stderr and exit codes of most actions, incl. tty output in a pty at
widths 20-200. Known differences: +list-colors --plain prints all 782
colors (Ghostty truncates at 617 because it never flushes), +version
has placeholder build info until build_info::set is wired up.

Deferred: list-fonts, show-face (need font discovery integration) and
new-window (needs GTK IPC); they return NotYetAvailable for now.

Test Plan:
- cargo test -p ghostty-cli (86 tests)
- cargo run -p ghostty-cli --example cli -- +list-keybinds --plain
  and diff against `ghostty +list-keybinds --plain`
This commit is contained in:
ddidderr committed 2026-10-11 22:22:01 +02:00
1 parent a97ae04f1d
commit 6286e02f07
46 files changed
+7135 -6

No files matched your search

+78
View File
@@ -0,0 +1,78 @@
//! `+show-face` (ZIG/src/cli/show_face.zig).
//!
//! DEFERRED: needs the font crate (collection / codepoint resolver). Only the
//! options and help are ported; running the action reports that it is not
//! available.
use ghostty_config::{config_enum, config_struct, diagnostics::DiagnosticList};
use crate::error::Error;
config_enum! {
/// Font style (Zig: `font.Style`).
pub enum Style {
Regular => "regular",
Bold => "bold",
Italic => "italic",
BoldItalic => "bold_italic",
}
}
config_enum! {
/// Font presentation (Zig: `font.Presentation`).
pub enum Presentation {
Text => "text",
Emoji => "emoji",
}
}
config_struct! {
pub struct Options {
/// The codepoint to search for.
"cp" => cp: Option<u32> = None,
/// Search for all of the codepoints in the string.
"string" => string: Option<String> = None,
/// Font style to search for.
"style" => style: Style = Style::Regular,
/// If specified, force text or emoji presentation.
"presentation" => presentation: Option<Presentation> = None,
}
extra {
// Enable arg parsing diagnostics so that we don't get an error if
// there is a "normal" config setting on the cli.
diagnostics: DiagnosticList = DiagnosticList::default(),
}
}
cli_options!(Options, help, diagnostics);
/// The `show-face` command shows what font face Ghostty will use to render a
/// specific codepoint. Note that this command does not take into consideration
/// grapheme clustering or any other Unicode features that might modify the
/// presentation of a codepoint, so this may show a different font face than
/// Ghostty uses to render a codepoint in a terminal session.
///
/// Flags:
///
/// * `--cp`: Find the face for a single codepoint. The codepoint may be specified
/// in decimal (`--cp=65`), hexadecimal (`--cp=0x41`), octal (`--cp=0o101`), or
/// binary (`--cp=0b1000001`).
///
/// * `--string`: Find the face for all of the codepoints in a string. The
/// string must be a valid UTF-8 sequence.
///
/// * `--style`: Search for a specific style. Valid options are `regular`, `bold`,
/// `italic`, and `bold_italic`.
///
/// * `--presentation`: If set, force searching for a specific presentation
/// style. Valid options are `text` and `emoji`. If unset, the presentation
/// style of a codepoint will be inferred from the Unicode standard.
pub fn run(args: &[String]) -> Result<u8, Error> {
let mut opts = Options::default();
crate::parse_options(&mut opts, args)?;
// TODO(integration): port the face lookup once ghostty-font lands.
Err(Error::NotYetAvailable("show-face"))
}