mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-15 03:52:39 +00:00
inspector: terminal tab
This commit is contained in:
@@ -62,6 +62,11 @@ need_scroll_to_selected: bool = false,
|
||||
/// Flag indicating whether the selection was made by keyboard
|
||||
is_keyboard_selection: bool = false,
|
||||
|
||||
/// Windows
|
||||
windows: struct {
|
||||
terminal: inspector.terminal.Window = .{},
|
||||
} = .{},
|
||||
|
||||
/// Enum representing keyboard navigation actions
|
||||
const KeyAction = enum {
|
||||
down,
|
||||
@@ -229,6 +234,8 @@ pub fn render(self: *Inspector) void {
|
||||
{
|
||||
self.surface.renderer_state.mutex.lock();
|
||||
defer self.surface.renderer_state.mutex.unlock();
|
||||
const t = self.surface.renderer_state.terminal;
|
||||
self.windows.terminal.render(t);
|
||||
self.renderScreenWindow();
|
||||
self.renderModesWindow();
|
||||
self.renderKeyboardWindow();
|
||||
@@ -257,7 +264,7 @@ fn setupLayout(self: *Inspector, dock_id_main: cimgui.c.ImGuiID) void {
|
||||
_ = self;
|
||||
|
||||
// Our initial focus
|
||||
cimgui.c.ImGui_SetWindowFocusStr(window_screen);
|
||||
cimgui.c.ImGui_SetWindowFocusStr(inspector.terminal.Window.name);
|
||||
|
||||
// Setup our initial layout.
|
||||
const dock_id: struct {
|
||||
@@ -285,6 +292,7 @@ fn setupLayout(self: *Inspector, dock_id_main: cimgui.c.ImGuiID) void {
|
||||
cimgui.ImGui_DockBuilderDockWindow(window_keyboard, dock_id.left);
|
||||
cimgui.ImGui_DockBuilderDockWindow(window_termio, dock_id.left);
|
||||
cimgui.ImGui_DockBuilderDockWindow(window_screen, dock_id.left);
|
||||
cimgui.ImGui_DockBuilderDockWindow(inspector.terminal.Window.name, dock_id.left);
|
||||
cimgui.ImGui_DockBuilderDockWindow(window_imgui_demo, dock_id.left);
|
||||
cimgui.ImGui_DockBuilderDockWindow(window_size, dock_id.right);
|
||||
cimgui.ImGui_DockBuilderFinish(dock_id_main);
|
||||
|
||||
@@ -4,6 +4,7 @@ pub const cursor = @import("cursor.zig");
|
||||
pub const key = @import("key.zig");
|
||||
pub const page = @import("page.zig");
|
||||
pub const termio = @import("termio.zig");
|
||||
pub const terminal = @import("terminal.zig");
|
||||
|
||||
pub const Cell = cell.Cell;
|
||||
pub const Inspector = @import("Inspector.zig");
|
||||
|
||||
215
src/inspector/terminal.zig
Normal file
215
src/inspector/terminal.zig
Normal file
@@ -0,0 +1,215 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const cimgui = @import("dcimgui");
|
||||
const terminal = @import("../terminal/main.zig");
|
||||
const Terminal = terminal.Terminal;
|
||||
const widgets = @import("widgets.zig");
|
||||
|
||||
/// Window to show terminal state information.
|
||||
pub const Window = struct {
|
||||
/// Window name/id.
|
||||
pub const name = "Terminal";
|
||||
|
||||
// Render
|
||||
pub fn render(self: *Window, t: *Terminal) void {
|
||||
_ = self;
|
||||
|
||||
// Start our window. If we're collapsed we do nothing.
|
||||
defer cimgui.c.ImGui_End();
|
||||
if (!cimgui.c.ImGui_Begin(
|
||||
name,
|
||||
null,
|
||||
cimgui.c.ImGuiWindowFlags_NoFocusOnAppearing,
|
||||
)) return;
|
||||
|
||||
if (cimgui.c.ImGui_CollapsingHeader(
|
||||
"General",
|
||||
cimgui.c.ImGuiTreeNodeFlags_DefaultOpen,
|
||||
)) {
|
||||
_ = cimgui.c.ImGui_BeginTable(
|
||||
"table_general",
|
||||
2,
|
||||
cimgui.c.ImGuiTableFlags_None,
|
||||
);
|
||||
defer cimgui.c.ImGui_EndTable();
|
||||
|
||||
{
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Working Directory");
|
||||
cimgui.c.ImGui_SameLine();
|
||||
widgets.helpMarker("The current working directory reported by the shell.");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
if (t.pwd.items.len > 0) {
|
||||
cimgui.c.ImGui_Text(
|
||||
"%.*s",
|
||||
t.pwd.items.len,
|
||||
t.pwd.items.ptr,
|
||||
);
|
||||
} else {
|
||||
cimgui.c.ImGui_TextDisabled("(none)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Focused");
|
||||
cimgui.c.ImGui_SameLine();
|
||||
widgets.helpMarker("Whether the terminal itself is currently focused.");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
var value: bool = t.flags.focused;
|
||||
_ = cimgui.c.ImGui_Checkbox("##focused", &value);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Previous Char");
|
||||
cimgui.c.ImGui_SameLine();
|
||||
widgets.helpMarker("The previously printed character, used only for the REP sequence.");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
if (t.previous_char) |c| {
|
||||
cimgui.c.ImGui_Text("U+%04X", @as(u32, c));
|
||||
} else {
|
||||
cimgui.c.ImGui_TextDisabled("(none)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cimgui.c.ImGui_CollapsingHeader(
|
||||
"Layout",
|
||||
cimgui.c.ImGuiTreeNodeFlags_DefaultOpen,
|
||||
)) {
|
||||
_ = cimgui.c.ImGui_BeginTable(
|
||||
"table_layout",
|
||||
2,
|
||||
cimgui.c.ImGuiTableFlags_None,
|
||||
);
|
||||
defer cimgui.c.ImGui_EndTable();
|
||||
|
||||
{
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Grid");
|
||||
cimgui.c.ImGui_SameLine();
|
||||
widgets.helpMarker("The size of the terminal grid in columns and rows.");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text(
|
||||
"%dc x %dr",
|
||||
t.cols,
|
||||
t.rows,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Pixels");
|
||||
cimgui.c.ImGui_SameLine();
|
||||
widgets.helpMarker("The size of the terminal grid in pixels.");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text(
|
||||
"%dw x %dh",
|
||||
t.width_px,
|
||||
t.height_px,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Scroll Region");
|
||||
cimgui.c.ImGui_SameLine();
|
||||
widgets.helpMarker("The scrolling region boundaries (top, bottom, left, right).");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_PushItemWidth(cimgui.c.ImGui_CalcTextSize("00000").x);
|
||||
defer cimgui.c.ImGui_PopItemWidth();
|
||||
|
||||
var override = t.scrolling_region;
|
||||
var changed = false;
|
||||
|
||||
cimgui.c.ImGui_AlignTextToFramePadding();
|
||||
cimgui.c.ImGui_Text("T:");
|
||||
cimgui.c.ImGui_SameLine();
|
||||
if (cimgui.c.ImGui_InputScalar(
|
||||
"##scroll_top",
|
||||
cimgui.c.ImGuiDataType_U16,
|
||||
&override.top,
|
||||
)) {
|
||||
override.top = @min(override.top, t.rows -| 1);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
cimgui.c.ImGui_SameLine();
|
||||
cimgui.c.ImGui_Text("B:");
|
||||
cimgui.c.ImGui_SameLine();
|
||||
if (cimgui.c.ImGui_InputScalar(
|
||||
"##scroll_bottom",
|
||||
cimgui.c.ImGuiDataType_U16,
|
||||
&override.bottom,
|
||||
)) {
|
||||
override.bottom = @min(override.bottom, t.rows -| 1);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
cimgui.c.ImGui_SameLine();
|
||||
cimgui.c.ImGui_Text("L:");
|
||||
cimgui.c.ImGui_SameLine();
|
||||
if (cimgui.c.ImGui_InputScalar(
|
||||
"##scroll_left",
|
||||
cimgui.c.ImGuiDataType_U16,
|
||||
&override.left,
|
||||
)) {
|
||||
override.left = @min(override.left, t.cols -| 1);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
cimgui.c.ImGui_SameLine();
|
||||
cimgui.c.ImGui_Text("R:");
|
||||
cimgui.c.ImGui_SameLine();
|
||||
if (cimgui.c.ImGui_InputScalar(
|
||||
"##scroll_right",
|
||||
cimgui.c.ImGuiDataType_U16,
|
||||
&override.right,
|
||||
)) {
|
||||
override.right = @min(override.right, t.cols -| 1);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// If we modified it then update our scrolling region
|
||||
// directly.
|
||||
if (changed and
|
||||
override.top < override.bottom and
|
||||
override.left < override.right)
|
||||
{
|
||||
t.scrolling_region = override;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // cursor
|
||||
}
|
||||
};
|
||||
14
src/inspector/widgets.zig
Normal file
14
src/inspector/widgets.zig
Normal file
@@ -0,0 +1,14 @@
|
||||
const cimgui = @import("dcimgui");
|
||||
|
||||
/// Draws a "(?)" disabled text marker that shows some help text
|
||||
/// on hover.
|
||||
pub fn helpMarker(text: [:0]const u8) void {
|
||||
cimgui.c.ImGui_TextDisabled("(?)");
|
||||
if (!cimgui.c.ImGui_BeginItemTooltip()) return;
|
||||
defer cimgui.c.ImGui_EndTooltip();
|
||||
|
||||
cimgui.c.ImGui_PushTextWrapPos(cimgui.c.ImGui_GetFontSize() * 35.0);
|
||||
defer cimgui.c.ImGui_PopTextWrapPos();
|
||||
|
||||
cimgui.c.ImGui_TextUnformatted(text.ptr);
|
||||
}
|
||||
Reference in New Issue
Block a user