diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-28 00:13:11 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:14 -0300 |
| commit | 42748f92b77367db415c8b4d0f2e537a9e1ddde7 (patch) | |
| tree | 3ff6606d33149581d5954dcc900eb6ab3e4f0f17 /test | |
| parent | 23f430573efe4f6ef55b0180aa0d742ff4eca1d9 (diff) | |
| download | pardes-42748f92b77367db415c8b4d0f2e537a9e1ddde7.tar.gz pardes-42748f92b77367db415c8b4d0f2e537a9e1ddde7.zip | |
Make the column and workspace tags Texts with the pane tag's keys
The headers had their own one-line editor with its own keys: Enter always
executed, h/l and J/K moved between headers and panes, Ctrl-c/x/v cut and
pasted, and TagLine refused a newline that 9P accepted. They are now Texts
like a pane's tag, with no prefix and a default until edited, so normal and
insert mode, undo and the look and execute keys are the body's. Moving
between them is the window keys' job: Up from a pane with nothing above it
reaches its column's tag and then the workspace's, Down comes back, and
Left and Right walk the column tags.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'test')
| -rw-r--r-- | test/column_drag.zig | 22 | ||||
| -rw-r--r-- | test/panes.zig | 12 | ||||
| -rw-r--r-- | test/snapshots/tagnav.golden | 24 | ||||
| -rw-r--r-- | test/snapshots/tagnav.snap | 43 |
4 files changed, 84 insertions, 17 deletions
diff --git a/test/column_drag.zig b/test/column_drag.zig index b2b8f35d..f128aa61 100644 --- a/test/column_drag.zig +++ b/test/column_drag.zig @@ -26,7 +26,7 @@ const Snapshot = struct { serial: u32, panes: [pardes.MAX_PANES]usize = undefined, count: usize, - tag: pardes.TagLine, + tag: []const u8, }; fn expectOrder(p: *Pardes, before: []const Snapshot, order: []const usize) !void { @@ -37,7 +37,7 @@ fn expectOrder(p: *Pardes, before: []const Snapshot, order: []const usize) !void try std.testing.expectEqual(saved.serial, p.col_serial[column]); try std.testing.expectEqual(saved.count, p.col_n[column]); try std.testing.expectEqualSlices(usize, saved.panes[0..saved.count], p.col_panes[column][0..p.col_n[column]]); - try std.testing.expectEqualStrings(saved.tag.slice(""), p.col_tags[column].slice("")); + try std.testing.expectEqualStrings(saved.tag, p.columnTag(column)); } } @@ -59,7 +59,7 @@ test "column grip drag moves only its interval and keeps tag caret with the colu try std.testing.expectEqual(@as(usize, 2), p.col_n[1]); for ([_]u64{ 2, 3, 5, 7 }, 0..) |weight, column| { p.col_weight[column] = weight; - try std.testing.expect(p.col_tags[column].set(([_][]const u8{ "zero column header", "one column header", "two column header", "three column header" })[column])); + p.col_tags[column].own = try p.gpa.dupe(u8, ([_][]const u8{ "zero column header", "one column header", "two column header", "three column header" })[column]); } p.update(.tick); var frame = std.heap.ArenaAllocator.init(p.gpa); @@ -67,7 +67,7 @@ test "column grip drag moves only its interval and keeps tag caret with the colu _ = try p.render(frame.allocator()); var before: [4]Snapshot = undefined; for (&before, 0..) |*saved, column| { - saved.* = .{ .weight = p.col_weight[column], .serial = p.col_serial[column], .count = p.col_n[column], .tag = p.col_tags[column] }; + saved.* = .{ .weight = p.col_weight[column], .serial = p.col_serial[column], .count = p.col_n[column], .tag = p.columnTag(column) }; @memcpy(saved.panes[0..saved.count], p.col_panes[column][0..saved.count]); } const layer = try tagLayer(p, 1); @@ -75,8 +75,8 @@ test "column grip drag moves only its interval and keeps tag caret with the colu p.update(.{ .mouse = headerMouse(layer, 10, .press) }); p.update(.{ .mouse = headerMouse(layer, 10, .release) }); try std.testing.expectEqual(@as(?usize, 1), p.header_column); - const caret = p.topbar_col; - const anchor = p.header_anchor; + const caret = p.focusedHeader().?.cur_col; + const anchor = p.focusedHeader().?.vsel; const scroll = p.header_scroll; const target = p.col_x[3] + p.col_w[3] - 2; const last_rect = p.rects[p.col_panes[3][0]]; @@ -93,14 +93,14 @@ test "column grip drag moves only its interval and keeps tag caret with the colu try expectOrder(p, &before, &.{ 0, 2, 3, 1 }); try std.testing.expectEqual(active, p.active); try std.testing.expectEqual(@as(?usize, 3), p.header_column); - try std.testing.expectEqual(caret, p.topbar_col); - try std.testing.expectEqual(anchor, p.header_anchor); + try std.testing.expectEqual(caret, p.focusedHeader().?.cur_col); + try std.testing.expectEqual(anchor, p.focusedHeader().?.vsel); try std.testing.expectEqual(scroll, p.header_scroll); // The old tag envelope must not edit the new occupant of its old index, // including the interval before hosts request another rendered frame. p.update(.{ .mouse = stale }); try std.testing.expectEqual(@as(?usize, 3), p.header_column); - try std.testing.expectEqual(caret, p.topbar_col); + try std.testing.expectEqual(caret, p.focusedHeader().?.cur_col); _ = try p.render(frame.allocator()); try std.testing.expectEqual(before[1].serial, (try tagLayer(p, 3)).serial); try std.testing.expectEqual(p.col_w[3] - pardes.TAG_TEXT_INSET, (try tagLayer(p, 3)).viewport.w); @@ -110,7 +110,7 @@ test "column grip drag moves only its interval and keeps tag caret with the colu mouse(p, .release, back); try expectOrder(p, &before, &.{ 0, 1, 2, 3 }); try std.testing.expectEqual(@as(?usize, 1), p.header_column); - try std.testing.expectEqual(caret, p.topbar_col); + try std.testing.expectEqual(caret, p.focusedHeader().?.cur_col); try std.testing.expectEqual(active, p.active); // A structural change between press and release must not retarget the // in-flight drag to whichever column now occupies the original index. @@ -165,7 +165,7 @@ test "column grip is separate from compact text and the resize seam" { try std.testing.expect(p.drag != .column_move); try std.testing.expect(p.header_drag); p.update(.{ .mouse = headerMouse(layer, 0, .release) }); - try std.testing.expectEqual(@as(?u16, 0), p.topbar_col); + try std.testing.expectEqual(@as(i32, 0), p.focusedHeader().?.cur_col); mouse(p, .press, p.col_x[1] + config.GUTTER - 1); try std.testing.expect(p.drag == .column_move); mouse(p, .release, p.col_x[1] + config.GUTTER - 1); diff --git a/test/panes.zig b/test/panes.zig index a391dba2..b9fa9a88 100644 --- a/test/panes.zig +++ b/test/panes.zig @@ -152,8 +152,8 @@ const TagLayerTests = struct { try std.testing.expect(left.sel[0].state == .done and left.sel[0].r0 == 0); p.update(.{ .key = .{ .cp = Key.escape } }); const long = "a" ** 60 ++ "界END"; - try std.testing.expect(p.global_tag.set(long)); - for (p.col_tags[0..p.ncol]) |*tag| try std.testing.expect(tag.set(long)); + p.global_tag.own = try p.gpa.dupe(u8, long); + for (p.col_tags[0..p.ncol]) |*tag| tag.own = try p.gpa.dupe(u8, long); _ = try p.render(frame.allocator()); for ([_]Kind{ .workspace, .column }) |kind| { const id: usize = if (kind == .column) 1 else 0; @@ -161,7 +161,7 @@ const TagLayerTests = struct { const x = @as(f32, @floatFromInt(header.viewport.x)) * 10 + 62.5 * 5; p.update(.{ .mouse = mouse(header, x, .press) }); p.update(.{ .mouse = mouse(header, x, .release) }); - try std.testing.expectEqual(@as(?u16, 63), p.topbar_col); + try std.testing.expectEqual(@as(i32, 63), p.focusedHeader().?.cur_col); if (kind == .column) try std.testing.expectEqual(@as(?usize, 1), p.header_column) else try std.testing.expect(p.header_column == null); p.update(.{ .key = .{ .cp = Key.escape } }); } @@ -334,7 +334,7 @@ const TagNavigationTests = struct { key(p, 'j'); try std.testing.expectEqual(@as(i32, 0), pane.tag.cur_col); try std.testing.expectEqual(@as(usize, 0), p.active); - try std.testing.expect(pane.focus == .tag and p.topbar_col == null); + try std.testing.expect(pane.focus == .tag and !p.header_focus); window(p, 'l'); try std.testing.expectEqual(right, p.active); try std.testing.expect(pane.focus == .body and p.panes[right].?.focus == .body); @@ -1291,13 +1291,13 @@ test "leaving a pane or entering a header cancels an uncommitted filename" { const pane = try p.setTestFile("untouched\n"); for ([_]bool{ false, true }) |header| { p.active = 0; - p.topbar_col = null; + p.exitHeader(); p.update(.tick); clickPathEnd(p, pane); p.update(.{ .paste = "/draft" }); try std.testing.expect(pane.prompt == .name); if (header) { - p.topbar_col = 0; + p.enterHeader(null); p.update(.tick); } else { try std.testing.expect(p.executeBuiltinLine(0, "New")); diff --git a/test/snapshots/tagnav.golden b/test/snapshots/tagnav.golden index 3fdba9f2..45d64b42 100644 --- a/test/snapshots/tagnav.golden +++ b/test/snapshots/tagnav.golden @@ -39,3 +39,27 @@ |5: 3 gamma $ == snap tty-tag grid=100x31 cursor=90,2 == snap tty-restored grid=100x31 cursor=54,5 +== snap column-tag grid=100x31 cursor=3,1 +|2: /tmp/pardes-snap/tagnav/cwd/w.txt Save Tty Coll /tmp/pardes-snap/tagnav/cwd Tty Save Mode Filte +|3: 1 alpha Up ls +|5: 3 gamma +== snap column-word grid=100x31 cursor=6,1 +|3: 1 alpha ls +== snap workspace-tag grid=100x31 cursor=0,0 +|3: 1 alpha Up ls +== snap topbar-dollar grid=100x31 cursor=70,0 +|3: 1 alpha ls +== snap topbar-dump-word grid=100x31 cursor=46,0 +== snap topbar-exec grid=100x31 cursor=7,3 +|0: Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill Restore /tmp/pardes-snap/tag +|3: 1 alpha Dump ls +== snap topbar-restore-word grid=100x31 cursor=72,0 +|3: 1 alpha ls +== snap topbar-restored grid=100x31 cursor=7,3 +|0: Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor Debug Kill +|3: 1 alpha $ ls +|5: 3 gamma $ +|6: ── restored history ── +|18: $ ls +|20: $ +|21: ── restored history ── diff --git a/test/snapshots/tagnav.snap b/test/snapshots/tagnav.snap index eed808de..c9ac9605 100644 --- a/test/snapshots/tagnav.snap +++ b/test/snapshots/tagnav.snap @@ -77,3 +77,46 @@ settle 100 key : stable 400 5000 snap tty-restored +# The column and workspace tags are Texts in the same layout, with the same +# keys: Up from a pane with nothing above it reaches its column's tag, in +# normal mode, then the workspace's; Down comes back the same way. +key c-b +stable 700 15000 +key c-w h +stable 400 5000 +key c-w k +stable 400 5000 +snap column-tag +key w +stable 400 5000 +snap column-word +key c-w k +stable 400 5000 +snap workspace-tag +# `$` is the last cell; four long-word steps back land on `Dump`, and the +# execute key runs it and gives the keyboard back to the body FIRST -- `Kill` +# lives up here too, so a builtin that frees the session must never return +# into a focused header. Dump grows a `Restore <path>` word, which is also the +# case where the line gets longer than the column you were parked on. +key $ +stable 400 5000 +snap topbar-dollar +key B B B B +stable 400 5000 +snap topbar-dump-word +key tab +stable 700 15000 +snap topbar-exec +# THE DELETION HAZARD, from the bar itself: `Restore` frees every pane and +# swaps the core out from under the caller. Walk back up onto the word the +# Dump just grew -- B twice off the tail, because the LONG word motions are the +# ones that step over a path in one go -- and run it. +key c-w k +key c-w k +stable 400 5000 +key $ B B +stable 400 5000 +snap topbar-restore-word +key tab +stable 900 15000 +snap topbar-restored |
