From dc11513c1bf1497c326e09e6bfc4dac56ed0d70f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 24 Oct 2023 21:15:00 -0700 Subject: [PATCH] inspector: add basic termio seq filter --- src/inspector/Inspector.zig | 27 ++++++++++++++++++++++----- src/inspector/termio.zig | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/inspector/Inspector.zig b/src/inspector/Inspector.zig index 1043bff31..56ecd8521 100644 --- a/src/inspector/Inspector.zig +++ b/src/inspector/Inspector.zig @@ -115,15 +115,15 @@ pub fn init(surface: *Surface) !Inspector { var vt_events = try inspector.termio.VTEventRing.init(surface.alloc, 2); errdefer vt_events.deinit(surface.alloc); + var vt_handler = inspector.termio.VTHandler.init(surface); + errdefer vt_handler.deinit(); + return .{ .surface = surface, .key_events = key_buf, .vt_events = vt_events, .vt_stream = .{ - .handler = .{ - .surface = surface, - }, - + .handler = vt_handler, .parser = .{ .osc_parser = .{ .alloc = surface.alloc, @@ -144,6 +144,8 @@ pub fn deinit(self: *Inspector) void { var it = self.vt_events.iterator(.forward); while (it.next()) |v| v.deinit(self.surface.alloc); self.vt_events.deinit(self.surface.alloc); + + self.vt_stream.handler.deinit(); self.vt_stream.deinit(); } } @@ -1108,7 +1110,8 @@ fn renderTermioWindow(self: *Inspector) void { )) { 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(); { @@ -1137,6 +1140,20 @@ fn renderTermioWindow(self: *Inspector) void { } } // 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 })) { cimgui.c.igCloseCurrentPopup(); } diff --git a/src/inspector/termio.zig b/src/inspector/termio.zig index ac67123f4..9a2b0e43d 100644 --- a/src/inspector/termio.zig +++ b/src/inspector/termio.zig @@ -1,11 +1,12 @@ const std = @import("std"); const Allocator = std.mem.Allocator; +const cimgui = @import("cimgui"); const terminal = @import("../terminal/main.zig"); const CircBuf = @import("../circ_buf.zig").CircBuf; const Surface = @import("../Surface.zig"); /// The stream handler for our inspector. -pub const Stream = terminal.Stream(Handler); +pub const Stream = terminal.Stream(VTHandler); /// VT event circular buffer. pub const VTEventRing = CircBuf(VTEvent, undefined); @@ -49,21 +50,41 @@ pub const VTEvent = struct { pub fn deinit(self: *VTEvent, alloc: Allocator) void { 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. -const Handler = struct { +pub const VTHandler = struct { /// The surface that the inspector is attached to. We use this instead /// of the inspector because this is pointer-stable. surface: *Surface, /// Exclude certain actions by tag. filter_exclude: ActionTagSet = ActionTagSet.initMany(&.{.print}), + filter_text: *cimgui.c.ImGuiTextFilter, 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. - 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; // 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. if (self.filter_exclude.contains(std.meta.activeTag(action))) return true; + // Build our event 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; insp.vt_events.append(ev) catch |err| switch (err) {