mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 00:36:07 +03:00
inspector: format termio a little better, incomplete
This commit is contained in:
@ -1108,7 +1108,7 @@ fn renderTermioWindow(self: *Inspector) void {
|
|||||||
|
|
||||||
_ = cimgui.c.igBeginTable(
|
_ = cimgui.c.igBeginTable(
|
||||||
"table_vt_events",
|
"table_vt_events",
|
||||||
1,
|
2,
|
||||||
cimgui.c.ImGuiTableFlags_RowBg |
|
cimgui.c.ImGuiTableFlags_RowBg |
|
||||||
cimgui.c.ImGuiTableFlags_Borders,
|
cimgui.c.ImGuiTableFlags_Borders,
|
||||||
.{ .x = 0, .y = 0 },
|
.{ .x = 0, .y = 0 },
|
||||||
@ -1116,6 +1116,19 @@ fn renderTermioWindow(self: *Inspector) void {
|
|||||||
);
|
);
|
||||||
defer cimgui.c.igEndTable();
|
defer cimgui.c.igEndTable();
|
||||||
|
|
||||||
|
cimgui.c.igTableSetupColumn(
|
||||||
|
"Kind",
|
||||||
|
cimgui.c.ImGuiTableColumnFlags_WidthFixed,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
cimgui.c.igTableSetupColumn(
|
||||||
|
"Description",
|
||||||
|
cimgui.c.ImGuiTableColumnFlags_WidthStretch,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
var it = self.vt_events.iterator(.reverse);
|
var it = self.vt_events.iterator(.reverse);
|
||||||
while (it.next()) |ev| {
|
while (it.next()) |ev| {
|
||||||
// Need to push an ID so that our selectable is unique.
|
// Need to push an ID so that our selectable is unique.
|
||||||
@ -1124,7 +1137,8 @@ fn renderTermioWindow(self: *Inspector) void {
|
|||||||
|
|
||||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||||
|
cimgui.c.igText("%s", @tagName(ev.kind).ptr);
|
||||||
|
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||||
cimgui.c.igText("%s", ev.str.ptr);
|
cimgui.c.igText("%s", ev.str.ptr);
|
||||||
}
|
}
|
||||||
} // table
|
} // table
|
||||||
|
@ -12,11 +12,40 @@ pub const VTEventRing = CircBuf(VTEvent, undefined);
|
|||||||
|
|
||||||
/// VT event
|
/// VT event
|
||||||
pub const VTEvent = struct {
|
pub const VTEvent = struct {
|
||||||
|
/// Kind of event, for filtering
|
||||||
|
kind: Kind,
|
||||||
|
|
||||||
/// The formatted string of the event. This is allocated. We format the
|
/// The formatted string of the event. This is allocated. We format the
|
||||||
/// event for now because there is so much data to copy if we wanted to
|
/// event for now because there is so much data to copy if we wanted to
|
||||||
/// store the raw event.
|
/// store the raw event.
|
||||||
str: [:0]const u8,
|
str: [:0]const u8,
|
||||||
|
|
||||||
|
const Kind = enum { print, execute, csi, esc, osc, dcs, apc };
|
||||||
|
|
||||||
|
/// Initiaze the event information for the given parser action.
|
||||||
|
pub fn init(alloc: Allocator, action: terminal.Parser.Action) !VTEvent {
|
||||||
|
var buf = std.ArrayList(u8).init(alloc);
|
||||||
|
defer buf.deinit();
|
||||||
|
try encodeAction(buf.writer(), action);
|
||||||
|
const str = try buf.toOwnedSliceSentinel(0);
|
||||||
|
errdefer alloc.free(str);
|
||||||
|
|
||||||
|
const kind: Kind = switch (action) {
|
||||||
|
.print => .print,
|
||||||
|
.execute => .execute,
|
||||||
|
.csi_dispatch => .csi,
|
||||||
|
.esc_dispatch => .esc,
|
||||||
|
.osc_dispatch => .osc,
|
||||||
|
.dcs_hook, .dcs_put, .dcs_unhook => .dcs,
|
||||||
|
.apc_start, .apc_put, .apc_end => .apc,
|
||||||
|
};
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.kind = kind,
|
||||||
|
.str = str,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *VTEvent, alloc: Allocator) void {
|
pub fn deinit(self: *VTEvent, alloc: Allocator) void {
|
||||||
alloc.free(self.str);
|
alloc.free(self.str);
|
||||||
}
|
}
|
||||||
@ -31,13 +60,15 @@ const Handler = struct {
|
|||||||
/// This is called with every single terminal action.
|
/// This is called with every single terminal action.
|
||||||
pub fn handleManually(self: *Handler, action: terminal.Parser.Action) !bool {
|
pub fn handleManually(self: *Handler, action: terminal.Parser.Action) !bool {
|
||||||
const insp = self.surface.inspector orelse return false;
|
const insp = self.surface.inspector orelse return false;
|
||||||
const alloc = self.surface.alloc;
|
|
||||||
const formatted = try std.fmt.allocPrintZ(alloc, "{}", .{action});
|
|
||||||
errdefer alloc.free(formatted);
|
|
||||||
|
|
||||||
const ev: VTEvent = .{
|
// We ignore certain action types that are too noisy.
|
||||||
.str = formatted,
|
switch (action) {
|
||||||
};
|
.dcs_put, .apc_put => return false,
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
const alloc = self.surface.alloc;
|
||||||
|
const ev = try VTEvent.init(alloc, action);
|
||||||
|
|
||||||
const max_capacity = 100;
|
const max_capacity = 100;
|
||||||
insp.vt_events.append(ev) catch |err| switch (err) {
|
insp.vt_events.append(ev) catch |err| switch (err) {
|
||||||
@ -59,3 +90,64 @@ const Handler = struct {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Encode a parser action as a string that we show in the logs.
|
||||||
|
fn encodeAction(writer: anytype, action: terminal.Parser.Action) !void {
|
||||||
|
switch (action) {
|
||||||
|
.print => try encodePrint(writer, action),
|
||||||
|
.execute => try encodeExecute(writer, action),
|
||||||
|
.csi_dispatch => |v| try encodeCSI(writer, v),
|
||||||
|
.esc_dispatch => |v| try encodeEsc(writer, v),
|
||||||
|
.osc_dispatch => |v| try encodeOSC(writer, v),
|
||||||
|
else => try writer.print("{}", .{action}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encodePrint(writer: anytype, action: terminal.Parser.Action) !void {
|
||||||
|
const ch = action.print;
|
||||||
|
try writer.print("'{u}' (U+{X})", .{ ch, ch });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encodeExecute(writer: anytype, action: terminal.Parser.Action) !void {
|
||||||
|
const ch = action.execute;
|
||||||
|
switch (ch) {
|
||||||
|
0x00 => try writer.writeAll("NUL"),
|
||||||
|
0x01 => try writer.writeAll("SOH"),
|
||||||
|
0x02 => try writer.writeAll("STX"),
|
||||||
|
0x03 => try writer.writeAll("ETX"),
|
||||||
|
0x04 => try writer.writeAll("EOT"),
|
||||||
|
0x05 => try writer.writeAll("ENQ"),
|
||||||
|
0x06 => try writer.writeAll("ACK"),
|
||||||
|
0x07 => try writer.writeAll("BEL"),
|
||||||
|
0x08 => try writer.writeAll("BS"),
|
||||||
|
0x09 => try writer.writeAll("HT"),
|
||||||
|
0x0A => try writer.writeAll("LF"),
|
||||||
|
0x0B => try writer.writeAll("VT"),
|
||||||
|
0x0C => try writer.writeAll("FF"),
|
||||||
|
0x0D => try writer.writeAll("CR"),
|
||||||
|
0x0E => try writer.writeAll("SO"),
|
||||||
|
0x0F => try writer.writeAll("SI"),
|
||||||
|
else => try writer.writeAll("?"),
|
||||||
|
}
|
||||||
|
try writer.print(" (0x{X})", .{ch});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encodeCSI(writer: anytype, csi: terminal.Parser.Action.CSI) !void {
|
||||||
|
for (csi.intermediates) |v| try writer.print("{c} ", .{v});
|
||||||
|
for (csi.params, 0..) |v, i| {
|
||||||
|
if (i != 0) try writer.writeByte(';');
|
||||||
|
try writer.print("{d}", .{v});
|
||||||
|
}
|
||||||
|
if (csi.intermediates.len > 0 or csi.params.len > 0) try writer.writeByte(' ');
|
||||||
|
try writer.writeByte(csi.final);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encodeEsc(writer: anytype, esc: terminal.Parser.Action.ESC) !void {
|
||||||
|
for (esc.intermediates) |v| try writer.print("{c} ", .{v});
|
||||||
|
try writer.writeByte(esc.final);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encodeOSC(writer: anytype, osc: terminal.osc.Command) !void {
|
||||||
|
// TODO: field values
|
||||||
|
try writer.print("{s} ", .{@tagName(osc)});
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user