diff options
| author | t <t@tjp.lol> | 2026-07-01 13:08:42 -0600 |
|---|---|---|
| committer | t <t@tjp.lol> | 2026-07-01 13:10:30 -0600 |
| commit | f8c67fe9f10e734dce91241bb5f19323ac6708d8 (patch) | |
| tree | 2e557626c085d0605b74783127c5307cec1cb0b0 /src | |
| parent | 5e76e4aa90e70245404c10085e809880635572a0 (diff) | |
Refine TUI status and tool block styling
Diffstat (limited to 'src')
| -rw-r--r-- | src/tui_components.zig | 69 | ||||
| -rw-r--r-- | src/tui_theme.zig | 20 |
2 files changed, 63 insertions, 26 deletions
diff --git a/src/tui_components.zig b/src/tui_components.zig index 837db0d..b00098a 100644 --- a/src/tui_components.zig +++ b/src/tui_components.zig @@ -2198,10 +2198,24 @@ pub const Thinking = struct { fn renderImpl(ptr: *anyopaque, width: usize, alloc: std.mem.Allocator) anyerror![]const []const u8 { _ = alloc; const self: *Thinking = @ptrCast(@alignCast(ptr)); - // Thinking blocks: dimmed text, no bg, with margin/indent spacing. - const dim = theme.default.fg(.dim); const plain = theme.default.fg(.assistant); - return renderBlockCached(&self.cache, self.buffer.items, plain, dim, width, 1, 0, self.alloc); + const header = theme.default.fg(.thinking_header); + const body = theme.default.fg(.thinking); + + var out: std.ArrayList([]const u8) = .empty; + defer { + for (out.items) |l| self.alloc.free(l); + out.deinit(self.alloc); + } + + const styled_header = try std.fmt.allocPrint(self.alloc, "{s}thinking{s}", .{ header.open(), theme.reset }); + defer self.alloc.free(styled_header); + try renderBlock(&out, styled_header, plain, plain, width, 1, 0, self.alloc); + if (self.buffer.items.len != 0) { + try renderBlock(&out, self.buffer.items, plain, body, width, 1, 0, self.alloc); + } + try self.cache.store(out.items); + return cacheLines(&self.cache); } fn firstLineChangedImpl(ptr: *anyopaque) ?usize { @@ -2258,25 +2272,21 @@ pub const CompactionSummary = struct { _ = alloc; const self: *CompactionSummary = @ptrCast(@alignCast(ptr)); const a = self.alloc; - const dim = theme.default.fg(.dim); - const plain_bg = theme.default.fg(.assistant); // no-op bg - - // Build body: header + wrapped summary text. - var body: std.ArrayList(u8) = .empty; - defer body.deinit(a); - try body.appendSlice(a, "[context compacted]"); - if (self.buffer.items.len != 0) { - try body.append(a, '\n'); - try body.appendSlice(a, self.buffer.items); - } + const header = theme.default.fg(.compaction_header); + const dim = theme.default.fg(.compaction); - // Render as a dim block with margin/indent spacing. var out: std.ArrayList([]const u8) = .empty; defer { for (out.items) |l| a.free(l); out.deinit(a); } - try renderBlock(&out, body.items, plain_bg, dim, width, 1, 0, a); + + const styled_header = try std.fmt.allocPrint(a, "{s}[context compacted]{s}", .{ header.open(), theme.reset }); + defer a.free(styled_header); + try renderBlock(&out, styled_header, theme.default.fg(.assistant), theme.default.fg(.assistant), width, 1, 0, a); + if (self.buffer.items.len != 0) { + try renderBlock(&out, self.buffer.items, theme.default.fg(.assistant), dim, width, 1, 0, a); + } try self.cache.store(out.items); return cacheLines(&self.cache); } @@ -2470,10 +2480,14 @@ pub const ToolUse = struct { // null -> pending (dark blue-gray) // true -> success (dark green) // false -> error (dark red) - const bg = theme.default.fg(.tool_pending_bg); + const bg = if (self.result_ok) |ok| switch (ok) { + true => theme.default.fg(.tool_success_bg), + false => theme.default.fg(.tool_error_bg), + } else theme.default.fg(.tool_pending_bg); const header_fg = theme.default.fg(.tool_header); - const dim_fg = theme.default.fg(.dim); - const plain_fg = theme.default.fg(.assistant); + const pending_fg = theme.default.fg(.tool_pending); + const success_fg = theme.default.fg(.tool_success); + const error_fg = theme.default.fg(.tool_error); // Padding within the block (1 col each side matches pi). const pad: usize = 1; @@ -2513,8 +2527,8 @@ pub const ToolUse = struct { // -- Stage 1: name not yet known ----------------------------------- if (self.name == null) { try lines.append(a, try ctx.blank()); - const vis = truncateToCols("tool (?)\xe2\x80\xa6", inner_w); - try lines.append(a, try ctx.line(header_fg, vis)); + const vis = truncateToCols("tool (?)…", inner_w); + try lines.append(a, try ctx.line(pending_fg, vis)); try lines.append(a, try ctx.blank()); try lines.append(a, try a.dupe(u8, "")); try self.cache.store(lines.items); @@ -2541,10 +2555,15 @@ pub const ToolUse = struct { // Separator blank row inside the block. try lines.append(a, try ctx.blank()); + const result_fg = if (self.result_ok) |ok| switch (ok) { + true => success_fg, + false => error_fg, + } else pending_fg; + // -- Result region: `(…)` placeholder or output text. if (self.output == null) { - const vis = truncateToCols("(\xe2\x80\xa6)", inner_w); - try lines.append(a, try ctx.line(dim_fg, vis)); + const vis = truncateToCols("(…)", inner_w); + try lines.append(a, try ctx.line(result_fg, vis)); } else { var out_lines: std.ArrayList([]const u8) = .empty; defer out_lines.deinit(a); @@ -2558,11 +2577,11 @@ pub const ToolUse = struct { } if (truncated) { const vis = truncateToCols("\xe2\x80\xa6", inner_w); - try lines.append(a, try ctx.line(dim_fg, vis)); + try lines.append(a, try ctx.line(result_fg, vis)); } for (out_lines.items[start..]) |oline| { const vis = truncateStyledToCols(oline, inner_w); - try lines.append(a, try ctx.line(plain_fg, vis)); + try lines.append(a, try ctx.line(result_fg, vis)); } } diff --git a/src/tui_theme.zig b/src/tui_theme.zig index 038deb5..db0ee25 100644 --- a/src/tui_theme.zig +++ b/src/tui_theme.zig @@ -37,6 +37,18 @@ pub const StyleName = enum { tool, /// Footer / chrome line. footer, + /// Neutral tool-body text shown inside tool blocks. + tool_text, + /// Pending tool placeholder / secondary chrome. + tool_pending, + /// Success accent for tool status / glyphs. + tool_success, + /// Error accent for tool status / glyphs. + tool_error, + /// Compaction-summary accent/header. + compaction_header, + /// Thinking-block accent/header. + thinking_header, /// The virtual cursor: reverse video block. cursor, /// Error / retry text. @@ -127,7 +139,13 @@ fn styleFor(name: StyleName) Style { .assistant => .{ .open_seq = "", .is_plain = true }, .user => .{ .open_seq = "\x1b[39m" }, .tool => .{ .open_seq = "\x1b[36m" }, - .footer => .{ .open_seq = "\x1b[2m" }, + .footer => .{ .open_seq = "\x1b[2m\x1b[38;2;120;130;150m" }, + .tool_text => .{ .open_seq = "\x1b[38;2;210;214;220m" }, + .tool_pending => .{ .open_seq = "\x1b[38;2;150;160;185m" }, + .tool_success => .{ .open_seq = "\x1b[38;2;110;215;140m" }, + .tool_error => .{ .open_seq = "\x1b[38;2;255;140;140m" }, + .compaction_header => .{ .open_seq = "\x1b[38;2;255;210;120m" }, + .thinking_header => .{ .open_seq = "\x1b[38;2;180;150;255m" }, // Reverse video — the virtual cursor block. .cursor => .{ .open_seq = "\x1b[7m" }, .err => .{ .open_seq = "\x1b[31m" }, |
