inspector: add basic termio seq filter

This commit is contained in:
Mitchell Hashimoto
2023-10-24 21:15:00 -07:00
parent ccb1cea49a
commit dc11513c1b
2 changed files with 55 additions and 9 deletions

View File

@ -115,15 +115,15 @@ pub fn init(surface: *Surface) !Inspector {
var vt_events = try inspector.termio.VTEventRing.init(surface.alloc, 2); var vt_events = try inspector.termio.VTEventRing.init(surface.alloc, 2);
errdefer vt_events.deinit(surface.alloc); errdefer vt_events.deinit(surface.alloc);
var vt_handler = inspector.termio.VTHandler.init(surface);
errdefer vt_handler.deinit();
return .{ return .{
.surface = surface, .surface = surface,
.key_events = key_buf, .key_events = key_buf,
.vt_events = vt_events, .vt_events = vt_events,
.vt_stream = .{ .vt_stream = .{
.handler = .{ .handler = vt_handler,
.surface = surface,
},
.parser = .{ .parser = .{
.osc_parser = .{ .osc_parser = .{
.alloc = surface.alloc, .alloc = surface.alloc,
@ -144,6 +144,8 @@ pub fn deinit(self: *Inspector) void {
var it = self.vt_events.iterator(.forward); var it = self.vt_events.iterator(.forward);
while (it.next()) |v| v.deinit(self.surface.alloc); while (it.next()) |v| v.deinit(self.surface.alloc);
self.vt_events.deinit(self.surface.alloc); self.vt_events.deinit(self.surface.alloc);
self.vt_stream.handler.deinit();
self.vt_stream.deinit(); self.vt_stream.deinit();
} }
} }
@ -1108,7 +1110,8 @@ fn renderTermioWindow(self: *Inspector) void {
)) { )) {
defer cimgui.c.igEndPopup(); defer cimgui.c.igEndPopup();
cimgui.c.igText("Selected filters will only affect future events."); cimgui.c.igText("Changed filter settings will only affect future events.");
cimgui.c.igSeparator(); cimgui.c.igSeparator();
{ {
@ -1137,6 +1140,20 @@ fn renderTermioWindow(self: *Inspector) void {
} }
} // Filter kind table } // Filter kind table
cimgui.c.igSeparator();
cimgui.c.igText(
"Filter by string. Empty displays all, \"abc\" finds lines\n" ++
"containing \"abc\", \"abc,xyz\" finds lines containing \"abc\"\n" ++
"or \"xyz\", \"-abc\" excludes lines containing \"abc\".",
);
_ = cimgui.c.ImGuiTextFilter_Draw(
self.vt_stream.handler.filter_text,
"##filter_text",
0,
);
cimgui.c.igSeparator();
if (cimgui.c.igButton("Close", .{ .x = 0, .y = 0 })) { if (cimgui.c.igButton("Close", .{ .x = 0, .y = 0 })) {
cimgui.c.igCloseCurrentPopup(); cimgui.c.igCloseCurrentPopup();
} }

View File

@ -1,11 +1,12 @@
const std = @import("std"); const std = @import("std");
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const cimgui = @import("cimgui");
const terminal = @import("../terminal/main.zig"); const terminal = @import("../terminal/main.zig");
const CircBuf = @import("../circ_buf.zig").CircBuf; const CircBuf = @import("../circ_buf.zig").CircBuf;
const Surface = @import("../Surface.zig"); const Surface = @import("../Surface.zig");
/// The stream handler for our inspector. /// The stream handler for our inspector.
pub const Stream = terminal.Stream(Handler); pub const Stream = terminal.Stream(VTHandler);
/// VT event circular buffer. /// VT event circular buffer.
pub const VTEventRing = CircBuf(VTEvent, undefined); pub const VTEventRing = CircBuf(VTEvent, undefined);
@ -49,21 +50,41 @@ pub const VTEvent = struct {
pub fn deinit(self: *VTEvent, alloc: Allocator) void { pub fn deinit(self: *VTEvent, alloc: Allocator) void {
alloc.free(self.str); alloc.free(self.str);
} }
/// Returns true if the event passes the given filter.
pub fn passFilter(
self: *const VTEvent,
filter: *cimgui.c.ImGuiTextFilter,
) bool {
return cimgui.c.ImGuiTextFilter_PassFilter(filter, self.str.ptr, null);
}
}; };
/// Our VT stream handler. /// Our VT stream handler.
const Handler = struct { pub const VTHandler = struct {
/// The surface that the inspector is attached to. We use this instead /// The surface that the inspector is attached to. We use this instead
/// of the inspector because this is pointer-stable. /// of the inspector because this is pointer-stable.
surface: *Surface, surface: *Surface,
/// Exclude certain actions by tag. /// Exclude certain actions by tag.
filter_exclude: ActionTagSet = ActionTagSet.initMany(&.{.print}), filter_exclude: ActionTagSet = ActionTagSet.initMany(&.{.print}),
filter_text: *cimgui.c.ImGuiTextFilter,
const ActionTagSet = std.EnumSet(terminal.Parser.Action.Tag); const ActionTagSet = std.EnumSet(terminal.Parser.Action.Tag);
pub fn init(surface: *Surface) VTHandler {
return .{
.surface = surface,
.filter_text = cimgui.c.ImGuiTextFilter_ImGuiTextFilter(""),
};
}
pub fn deinit(self: *VTHandler) void {
cimgui.c.ImGuiTextFilter_destroy(self.filter_text);
}
/// 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: *VTHandler, action: terminal.Parser.Action) !bool {
const insp = self.surface.inspector orelse return false; const insp = self.surface.inspector orelse return false;
// We ignore certain action types that are too noisy. // We ignore certain action types that are too noisy.
@ -76,8 +97,16 @@ const Handler = struct {
// We return true because we did "handle" it by ignoring it. // We return true because we did "handle" it by ignoring it.
if (self.filter_exclude.contains(std.meta.activeTag(action))) return true; if (self.filter_exclude.contains(std.meta.activeTag(action))) return true;
// Build our event
const alloc = self.surface.alloc; const alloc = self.surface.alloc;
const ev = try VTEvent.init(alloc, action); var ev = try VTEvent.init(alloc, action);
errdefer ev.deinit(alloc);
// Check if the event passes the filter
if (!ev.passFilter(self.filter_text)) {
ev.deinit(alloc);
return true;
}
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) {