Files
ghostty-rs/crates/ghostty-inspector/src/widgets/style.rs
T
ddidderr d1a5e55198 feat(inspector): port the terminal inspector
Ports ZIG/src/inspector (the Dear ImGui terminal inspector) as the
ghostty-inspector crate using dear-imgui-rs + dear-imgui-glow (imgui-rs
lacks a safe docking API): screen, modes, keyboard events, terminal IO
/ VT sequence log with filtering, cell inspector with picking, page
list, renderer and size/font info, with Ghostty's docking layout. The
crate denies unsafe except a single dock.rs module wrapping DockBuilder.

GTK: imgui_widget, inspector_widget and inspector_window classes with
their blueprints replace the former no-op; ctrl+shift+i toggles the
inspector window.

Core: activate/deactivate hooks, key event and mouse recording, and VT
stream recording in termio while an inspector is active, as in Zig;
overlay features reach the renderer through an InspectorHook on the
render state. The debug input replay hook gained inspector-screenshot/
click/scroll steps used to verify all tabs in the real app.

Deviations: font size scales with the display scale instead of Zig's
fixed 16*2; pop-out dock splits apply one frame later; DCS/APC
descriptions are approximated.

Test Plan:
- cargo test -p ghostty-inspector (15 incl. headless full-UI draw)
- cargo test -p ghostty-core --test e2e_inspector (4)
2026-10-12 04:39:14 +02:00

133 lines
3.8 KiB
Rust

//! Style table (ZIG/src/inspector/widgets/style.zig).
use dear_imgui_rs::{ColorDisplayMode, ColorEditFlags, ColorEditOptions, TableFlags, Ui};
use ghostty_terminal::style::{Color, Style};
use ghostty_vt::color::{Palette, Rgb};
use super::help_marker;
pub(crate) fn rgb_f32(rgb: Rgb) -> [f32; 3] {
[
f32::from(rgb.r) / 255.0,
f32::from(rgb.g) / 255.0,
f32::from(rgb.b) / 255.0,
]
}
/// Render a style as a table.
pub fn table(ui: &Ui, st: &Style, palette: Option<&Palette>) {
if let Some(_t) = ui.begin_table_with_flags("style", 2, TableFlags::NONE) {
{
ui.table_next_row();
ui.table_set_column_index(0);
ui.text("Foreground");
ui.same_line();
help_marker(ui, "The foreground (text) color");
ui.table_set_column_index(1);
color(ui, "fg", st.fg_color, palette);
}
{
ui.table_next_row();
ui.table_set_column_index(0);
ui.text("Background");
ui.same_line();
help_marker(ui, "The background (cell) color");
ui.table_set_column_index(1);
color(ui, "bg", st.bg_color, palette);
}
{
ui.table_next_row();
ui.table_set_column_index(0);
ui.text("Underline");
ui.same_line();
help_marker(ui, "The underline color, if underlines are enabled.");
ui.table_set_column_index(1);
color(ui, "underline", st.underline_color, palette);
}
let style_flags: [(&str, bool, &str); 7] = [
(
"bold",
st.flags.bold,
"Text will be rendered with bold weight.",
),
(
"italic",
st.flags.italic,
"Text will be rendered in italic style.",
),
(
"faint",
st.flags.faint,
"Text will be rendered with reduced intensity.",
),
("blink", st.flags.blink, "Text will blink."),
(
"inverse",
st.flags.inverse,
"Foreground and background colors are swapped.",
),
(
"invisible",
st.flags.invisible,
"Text will be invisible (hidden).",
),
(
"strikethrough",
st.flags.strikethrough,
"Text will have a line through it.",
),
];
for (name, set, help) in style_flags {
if !set {
continue;
}
ui.table_next_row();
{
ui.table_set_column_index(0);
ui.text(name);
ui.same_line();
help_marker(ui, help);
}
{
ui.table_set_column_index(1);
ui.text("true");
}
}
}
ui.text_disabled("(Any styles not shown are not currently set)");
}
fn hex_color_edit(ui: &Ui, rgb: Rgb) {
let mut data = rgb_f32(rgb);
ui.color_edit3_config("color_fg", &mut data)
.flags(
ColorEditOptions::new()
.flags(ColorEditFlags::NO_PICKER | ColorEditFlags::NO_LABEL)
.display_mode(ColorDisplayMode::Hex),
)
.build();
}
/// Render a style color.
pub fn color(ui: &Ui, id: &str, c: Color, palette: Option<&Palette>) {
let _id = ui.push_id(id);
match c {
Color::None => ui.text("default"),
Color::Palette(idx) => {
ui.text(format!("Palette {idx}"));
if let Some(p) = palette {
hex_color_edit(ui, p[usize::from(idx)]);
}
}
Color::Rgb(rgb) => hex_color_edit(ui, rgb),
}
}