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)
This commit is contained in:
1 parent
b192fdb046
commit
d1a5e55198
25 files changed
+6693
No files matched your search
@@ -0,0 +1,132 @@
|
||||
//! 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),
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user