summaryrefslogtreecommitdiff
path: root/src/tui_components.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/tui_components.zig')
-rw-r--r--src/tui_components.zig64
1 files changed, 36 insertions, 28 deletions
diff --git a/src/tui_components.zig b/src/tui_components.zig
index a9648ee..1ce5b56 100644
--- a/src/tui_components.zig
+++ b/src/tui_components.zig
@@ -1580,7 +1580,7 @@ pub const CompactionSummary = struct {
/// component holds no global state.
pub const ToolUse = struct {
/// Number of trailing output lines shown when collapsed.
- pub const collapsed_tail_lines: usize = 5;
+ pub const collapsed_tail_lines: usize = 8;
alloc: std.mem.Allocator,
cache: RenderCache,
@@ -1854,8 +1854,9 @@ test "AssistantText: renders wrapped text within width" {
// renderBlock adds 2 margin lines: 3 content + 2 = 5.
try testing.expectEqual(@as(usize, 5), lines.len);
for (lines) |l| try testing.expect(vw(l) <= 7);
- // First render after empty cache => changed from 0.
- try testing.expectEqual(@as(?usize, 0), at.comp().firstLineChanged());
+ // After a render the cache is clean, so the live signal is null. (The
+ // first-render diff index 0 is retained internally in changed_from.)
+ try testing.expectEqual(@as(?usize, null), at.comp().firstLineChanged());
}
test "AssistantText: streaming keeps firstLineChanged near the tail, not 0" {
@@ -2530,24 +2531,33 @@ test "ToolUse: stage 2 shows name + verbatim json + placeholder" {
for (lines) |l| try testing.expect(vw(l) <= 60);
}
-test "ToolUse: collapsed shows only the last 5 output lines (default)" {
+test "ToolUse: collapsed shows only the last collapsed_tail_lines output lines (default)" {
var t = ToolUse.init(testing.allocator);
defer t.deinit();
try t.setName("read");
try t.setInput("{}");
- // 8 short output lines -> collapsed shows the marker + last 5.
- try t.setOutput("l1\nl2\nl3\nl4\nl5\nl6\nl7\nl8");
+ // 12 short output lines -> collapsed shows the marker + the last
+ // collapsed_tail_lines (8) of them, eliding l1..l4.
+ try t.setOutput("l1\nl2\nl3\nl4\nl5\nl6\nl7\nl8\nl9\nl10\nl11\nl12");
const collapsed = try t.comp().render(40, testing.allocator);
- // margin+pad+header+sep+marker+l4..l8+pad+margin = 1+1+1+1+1+5+1+1 = 12
- // Last output line (l8) is at lines[len-3] (before bottom pad + margin).
- try testing.expect(std.mem.indexOf(u8, collapsed[collapsed.len - 3], "l8") != null);
- try testing.expect(std.mem.indexOf(u8, collapsed[collapsed.len - 7], "l4") != null);
- // The earliest output lines are elided when collapsed.
- var has_l1 = false;
+ // margin+pad+header+sep+marker+(tail lines)+pad+margin
+ // = 1+1+1+1+1+collapsed_tail_lines+1+1 = 7 + collapsed_tail_lines
+ try testing.expectEqual(@as(usize, 7 + ToolUse.collapsed_tail_lines), collapsed.len);
+ // Last output line (l12) is at lines[len-3] (before bottom pad + margin);
+ // the first SHOWN tail line is at lines[len-3-(tail-1)].
+ // Tokens are rendered as " l<n>" followed by right-padding, so match on a
+ // trailing space to avoid "l1" spuriously matching inside "l10".."l12".
+ try testing.expect(std.mem.indexOf(u8, collapsed[collapsed.len - 3], "l12 ") != null);
+ try testing.expect(std.mem.indexOf(u8, collapsed[collapsed.len - 3 - (ToolUse.collapsed_tail_lines - 1)], "l5 ") != null);
+ // The earliest output lines (l1..l4) are elided when collapsed.
+ var has_elided = false;
for (collapsed) |l| {
- if (std.mem.indexOf(u8, l, "l1") != null) has_l1 = true;
+ if (std.mem.indexOf(u8, l, "l1 ") != null or
+ std.mem.indexOf(u8, l, "l2 ") != null or
+ std.mem.indexOf(u8, l, "l3 ") != null or
+ std.mem.indexOf(u8, l, "l4 ") != null) has_elided = true;
}
- try testing.expect(!has_l1);
+ try testing.expect(!has_elided);
// Expanding shows everything.
t.setCollapsed(false);
@@ -2555,7 +2565,7 @@ test "ToolUse: collapsed shows only the last 5 output lines (default)" {
try testing.expect(expanded.len > collapsed.len);
var has_l1_exp = false;
for (expanded) |l| {
- if (std.mem.indexOf(u8, l, "l1") != null) has_l1_exp = true;
+ if (std.mem.indexOf(u8, l, "l1 ") != null) has_l1_exp = true;
}
try testing.expect(has_l1_exp);
}
@@ -2620,33 +2630,31 @@ test "ToolUse: collapse/expand is a length change with a cache-derived firstLine
defer t.deinit();
try t.setName("read");
try t.setInput("{}");
- try t.setOutput("l1\nl2\nl3\nl4\nl5\nl6\nl7\nl8");
+ // 12 output lines, so collapsing (tail = collapsed_tail_lines = 8) truncates.
+ try t.setOutput("l1\nl2\nl3\nl4\nl5\nl6\nl7\nl8\nl9\nl10\nl11\nl12");
// Default collapsed:
- // margin+pad+header+sep+truncmark+5lines+pad+margin = 1+1+1+1+1+5+1+1 = 12
+ // margin+pad+header+sep+truncmark+8lines+pad+margin = 1+1+1+1+1+8+1+1 = 15
const collapsed = try t.comp().render(40, testing.allocator);
- try testing.expectEqual(@as(usize, 12), collapsed.len);
- // A stable re-render is clean (cache-derived, no drift).
+ try testing.expectEqual(@as(usize, 15), collapsed.len);
+ // A stable re-render is clean: the live signal is null.
_ = try t.comp().render(40, testing.allocator);
try testing.expectEqual(@as(?usize, null), t.comp().firstLineChanged());
- // Expand: margin+pad+header+sep+8lines+pad+margin = 1+1+1+1+8+1+1 = 14
+ // Expand: margin+pad+header+sep+12lines+pad+margin = 1+1+1+1+12+1+1 = 18
t.setCollapsed(false);
// While dirty (full drop), the signal is the cache-derived 0.
try testing.expectEqual(@as(?usize, 0), t.comp().firstLineChanged());
const expanded = try t.comp().render(40, testing.allocator);
- try testing.expectEqual(@as(usize, 14), expanded.len);
- // After the render the baseline was dropped on the toggle, so the diff
- // reports from 0 — cache-derived, not a hand-managed value.
- try testing.expectEqual(@as(?usize, 0), t.comp().firstLineChanged());
- // Stable re-render is clean again.
- _ = try t.comp().render(40, testing.allocator);
+ try testing.expectEqual(@as(usize, 18), expanded.len);
+ // After the render the cache is clean, so the live signal is null again
+ // (the toggle's drop-from-0 diff is internal bookkeeping, not a live cut).
try testing.expectEqual(@as(?usize, null), t.comp().firstLineChanged());
- // Collapse again: shrink back to 12 rows.
+ // Collapse again: shrink back to 15 rows.
t.setCollapsed(true);
const recollapsed = try t.comp().render(40, testing.allocator);
- try testing.expectEqual(@as(usize, 12), recollapsed.len);
+ try testing.expectEqual(@as(usize, 15), recollapsed.len);
}
test "ToolUse: args are rendered VERBATIM (no pretty-print) and within width" {