summaryrefslogtreecommitdiff
path: root/test/panes.zig
diff options
context:
space:
mode:
Diffstat (limited to 'test/panes.zig')
-rw-r--r--test/panes.zig87
1 files changed, 54 insertions, 33 deletions
diff --git a/test/panes.zig b/test/panes.zig
index 662ea3a5..40b4b6ba 100644
--- a/test/panes.zig
+++ b/test/panes.zig
@@ -2,6 +2,7 @@ const std = @import("std");
const pardes = @import("pardes");
const panes = pardes.panes;
const layout = pardes.layout;
+const animation = pardes.animation;
const Pardes = pardes.Pardes;
const Pane = pardes.Pane;
const Key = pardes.Key;
@@ -18,17 +19,17 @@ fn setTag(pane: *Pane, text: []const u8) !void {
}
const TagLayerTests = struct {
- const Kind = @FieldType(pardes.TagLayer, "kind");
- fn findLayer(p: *Pardes, kind: Kind, id: usize) !*pardes.TagLayer {
+ const Kind = @FieldType(pardes.Layer, "kind");
+ fn findLayer(p: *Pardes, kind: Kind, id: usize) !*pardes.Layer {
for (&p.surface.tag_layers) |*layer| {
- if (layer.cols > 0 and layer.kind == kind and layer.id == id) return layer;
+ if (layer.rows > 0 and layer.kind == kind and layer.id == id) return layer;
}
return error.MissingTagLayer;
}
- fn mouse(layer: *const pardes.TagLayer, x: f32, kind: pardes.Mouse.Kind) pardes.Mouse {
+ fn mouse(layer: *const pardes.Layer, x: f32, kind: pardes.Mouse.Kind) pardes.Mouse {
const y = (@as(f32, @floatFromInt(layer.viewport.y)) + 0.5) * 20;
- return .{ .button = .left, .kind = kind, .col = @intFromFloat(x / 10), .row = @intFromFloat(y / 20), .tag_hit = layer.hitAt(x, y, 10, 20, 5, 10) };
+ return .{ .button = .left, .kind = kind, .col = @intFromFloat(x / 10), .row = @intFromFloat(y / 20), .tag_hit = layer.tagHit(x, y, 10, 20, 5, 10) };
}
test "compact tag layers render and edit Unicode text beyond body column capacity" {
@@ -70,7 +71,7 @@ const TagLayerTests = struct {
try std.testing.expectEqualStrings("body\n", pane.file.?.content);
p.update(.{ .key = .{ .cp = Key.escape } });
const rect = p.rects[0];
- const track: layout.Track = .{
+ const track: animation.Track = .{
.serial = pane.serial,
.pane = 0,
.effect = .zoom,
@@ -199,14 +200,16 @@ test "a tag with a newline in it is as tall as its lines, and each line is typed
const body_y = p.bodyTop(pane, r);
try std.testing.expectEqual(if (bottom) r.y else r.y + 2, body_y);
try std.testing.expectEqualStrings("b", surface.at(r.x + config.GUTTER + panes.File.gutterWidth(pane), body_y).grapheme());
- // a layer to a line, for a pixel shell
- var lines: usize = 0;
+ // one layer, a row to each line, for a pixel shell
+ var layers: usize = 0;
for (p.surface.tagLayers()) |*layer| {
- if (layer.cols == 0 or layer.kind != .pane or layer.id != 0) continue;
- try std.testing.expectEqual(tag_y + layer.line, layer.viewport.y);
- lines += 1;
+ if (layer.rows == 0 or layer.kind != .pane or layer.id != 0) continue;
+ try std.testing.expectEqual(tag_y, layer.viewport.y);
+ try std.testing.expectEqual(@as(u16, 2), layer.rows);
+ try std.testing.expectEqual(@as(u16, 2), layer.viewport.h);
+ layers += 1;
}
- try std.testing.expectEqual(@as(usize, 2), lines);
+ try std.testing.expectEqual(@as(usize, 1), layers);
// a click on the second line puts the tag's cursor on it
p.update(.{ .key = .{ .cp = Key.escape } });
p.update(.{ .key = .{ .cp = ':' } });
@@ -305,7 +308,7 @@ const TagNavigationTests = struct {
try std.testing.expectEqual(@as(usize, 2), got.n);
for (ranges[0..got.n]) |range| try std.testing.expectEqualStrings("S", text[@min(range.anchor, range.head)..@max(range.anchor, range.head)]);
// the body's selection is its own
- try std.testing.expectEqual(@as(u8, 0), pane.body.nsel);
+ try std.testing.expectEqual(@as(u16, 0), pane.body.nsel);
// `/` from the tag is the body's search, as acme's Look from a tag is
key(p, ',');
key(p, '/');
@@ -314,6 +317,19 @@ const TagNavigationTests = struct {
try std.testing.expect(pane.prompt == .none and pane.focus == .body);
}
+ test "ms and md edit a tag's own text, and the text the edit made is read back whole" {
+ const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 100, .rows = 20 });
+ defer p.deinit();
+ const pane = try p.setTestFile("body\n");
+ p.update(.tick);
+ key(p, ':'); // the tag, on `Save` the first time
+ for ("miwms(") |cp| key(p, cp);
+ try std.testing.expect(std.mem.indexOf(u8, pardes.tagline.curTail(pane), "(Save)") != null);
+ for ("md(") |cp| key(p, cp);
+ try std.testing.expect(std.mem.indexOf(u8, pardes.tagline.curTail(pane), " Save ") != null);
+ try std.testing.expect(std.mem.indexOf(u8, pardes.tagline.curTail(pane), "(") == null);
+ }
+
test "the keyboard reaches a tag's path, which it can select and yank but not edit" {
const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 100, .rows = 20 });
defer p.deinit();
@@ -325,7 +341,7 @@ const TagNavigationTests = struct {
try std.testing.expectEqual(@as(i32, 0), pane.tag.cur_col);
key(p, 'E');
key(p, 'y');
- try std.testing.expectEqualStrings("/test.txt", p.yank.?);
+ try std.testing.expectEqualStrings("/test.txt", p.registers.text(p.gpa, '"').?);
// an edit that reaches into it is refused, the cursor with it
const before = try std.testing.allocator.dupe(u8, try pardes.edit.flatSurface(p, &pane.tag));
defer std.testing.allocator.free(before);
@@ -540,11 +556,11 @@ const TagNavigationTests = struct {
};
const BodyHitTests = struct {
- fn mouse(layer: *const pardes.BodyLayer, row: u16, col: u16, kind: pardes.Mouse.Kind) pardes.Mouse {
+ fn mouse(layer: *const pardes.Layer, row: u16, col: u16, kind: pardes.Mouse.Kind) pardes.Mouse {
const width: f32 = if (row < layer.context_rows) 8 else 10;
const x = @as(f32, @floatFromInt(layer.viewport.x)) * 10 + (@as(f32, @floatFromInt(col)) + 0.5) * width;
const y = layer.rowTop(row, 20, 10) + layer.rowHeight(row, 20, 10) / 2;
- return .{ .button = .left, .kind = kind, .col = @intFromFloat(x / 10), .row = @intFromFloat(y / 20), .body_hit = layer.hitAt(x, y, 10, 20, 8, 10).? };
+ return .{ .button = .left, .kind = kind, .col = @intFromFloat(x / 10), .row = @intFromFloat(y / 20), .body_hit = layer.bodyHit(x, y, 10, 20, 8, 10).? };
}
test "compact TreeContext mouse follows source rows in reclaimed space" {
@@ -672,7 +688,7 @@ const TreeContextTests = struct {
const y = layer.rowTop(row, 20, 10) + 9.5;
const x = @as(f32, @floatFromInt(layer.viewport.x)) * 10 + 5;
// A one-pixel separator remains inside its existing header row.
- try std.testing.expectEqual(row, layer.hitAt(x, y, 10, 20, 8, 10).?.row);
+ try std.testing.expectEqual(row, layer.bodyHit(x, y, 10, 20, 8, 10).?.row);
}
pane.scrollBy(-5);
_ = try p.render(frame.allocator());
@@ -848,12 +864,12 @@ const TtySelectionTests = struct {
const x = rect.x + config.GUTTER;
const y = p.bodyTop(pane, rect);
JumpSelectionTests.drag(p, x + 1, y, x + 3, y);
- try std.testing.expectEqualStrings("lph", p.yank orelse return error.MissingAutomaticTtyYank);
+ try std.testing.expectEqualStrings("lph", p.registers.text(p.gpa, '"') orelse return error.MissingAutomaticTtyYank);
p.update(.{ .key = .{ .cp = p.opts.tty_toggle, .ctrl = true } });
p.update(.{ .key = .{ .cp = 'l' } });
try std.testing.expectEqual(@as(i32, 4), pane.body.cur_col);
p.update(.{ .key = .{ .cp = 'y' } });
- try std.testing.expectEqualStrings("a", p.yank.?);
+ try std.testing.expectEqualStrings("a", p.registers.text(p.gpa, '"').?);
try noChildInput(p);
}
@@ -881,7 +897,7 @@ const TtySelectionTests = struct {
const expected = if (prompt) "$ ab" else "lph\nrav";
try std.testing.expectEqual(panes.Text.Mode.tty, pane.body.mode);
try std.testing.expectEqualStrings(expected, pardes.test_api.heldSelection(p, 0).?);
- try std.testing.expectEqualStrings(expected, p.yank orelse return error.MissingAutomaticTtyYank);
+ try std.testing.expectEqualStrings(expected, p.registers.text(p.gpa, '"') orelse return error.MissingAutomaticTtyYank);
try noChildInput(p);
try std.testing.expect(p.executeBuiltinLine(0, "ClipYank"));
@@ -897,7 +913,7 @@ const TtySelectionTests = struct {
}
try std.testing.expectEqualStrings(expected, pardes.test_api.heldSelection(p, 0).?);
p.update(.{ .key = .{ .cp = 'y' } });
- try std.testing.expectEqualStrings(expected, p.yank.?);
+ try std.testing.expectEqualStrings(expected, p.registers.text(p.gpa, '"').?);
try noChildInput(p);
p.update(.{ .key = .{ .cp = p.opts.tty_toggle, .ctrl = true } });
try std.testing.expectEqual(panes.Text.Mode.tty, pane.body.mode);
@@ -908,7 +924,7 @@ const TtySelectionTests = struct {
_ = try p.render(frame.allocator());
try std.testing.expectEqual(panes.Text.Mode.tty, pane.body.mode);
try std.testing.expectEqualStrings(expected, pardes.test_api.heldSelection(p, 0).?);
- try std.testing.expectEqualStrings(expected, p.yank.?);
+ try std.testing.expectEqualStrings(expected, p.registers.text(p.gpa, '"').?);
try noChildInput(p);
}
}
@@ -940,7 +956,7 @@ const TtySelectionTests = struct {
const sx = source.x + config.GUTTER;
const sy = if (p.settings.tag_bottom) source.y else source.y + pardes.BOX_H;
JumpSelectionTests.drag(p, sx + 1, sy, sx + 3, sy + 1);
- try std.testing.expectEqualStrings("lph\nrav", p.yank orelse return error.MissingAutomaticTtyYank);
+ try std.testing.expectEqualStrings("lph\nrav", p.registers.text(p.gpa, '"') orelse return error.MissingAutomaticTtyYank);
try noChildInput(p);
const target = p.rects[1];
@@ -1001,7 +1017,7 @@ const TtySelectionTests = struct {
try std.testing.expectEqual(panes.Text.Mode.tty, pane.body.mode);
if (bracketed) p.update(.{ .output = .{ .pane = 0, .bytes = "\x1b[?2004h" } });
try std.testing.expectEqual(bracketed, panes.Terminal.bracketedPaste(pane));
- p.yank = try p.gpa.dupe(u8, "one\ntwo"); // what a `y` anywhere left behind
+ p.registers.put(p.gpa, '"', "one\ntwo", 0, 1, true); // what a `y` anywhere left behind
var buf: [256]u8 = undefined;
_ = childInput(p, &buf);
@@ -1033,7 +1049,7 @@ const TtySelectionTests = struct {
);
}
// ...and neither chord put the clipboard in the register on its way.
- try std.testing.expectEqualStrings("one\ntwo", p.yank orelse "");
+ try std.testing.expectEqualStrings("one\ntwo", p.registers.text(p.gpa, '"') orelse "");
}
}
};
@@ -1941,7 +1957,11 @@ test "a prompt owns the pipe behavior through cancellation and submission" {
p.update(.{ .key = .{ .cp = Key.enter } });
const pending = p.pipe.wait orelse return error.MissingPipe;
try std.testing.expectEqual(how, pending.how);
- try std.testing.expectEqualStrings("cat", pending.command);
+ // `$` runs the command in a subshell that reports its status
+ if (how == .keep)
+ try std.testing.expect(std.mem.indexOf(u8, pending.command, "\ncat\n") != null)
+ else
+ try std.testing.expectEqualStrings("cat", pending.command);
try std.testing.expectEqual(@as(usize, 1), pending.inputs.len);
try std.testing.expectEqualStrings(if (how.pipes()) "one" else "", pending.inputs[0].bytes);
try std.testing.expect(pane.prompt == .none);
@@ -1967,8 +1987,8 @@ test "prompt cancellation restores the selection before regex previews" {
p.update(.{ .key = .{ .cp = case.pattern[0], .text = case.pattern } });
try std.testing.expectEqual(case.secondary, pane.body.nsel);
p.update(.{ .key = .{ .cp = Key.escape } });
- try std.testing.expectEqual(@as(u8, 0), pane.body.nsel);
- try std.testing.expectEqual(@as(u8, 0), pane.nsel_snap);
+ try std.testing.expectEqual(@as(u16, 0), pane.body.nsel);
+ try std.testing.expectEqual(@as(u16, 0), pane.nsel_snap);
try std.testing.expectEqual(@as(i32, 10), pane.body.cur_col);
try std.testing.expectEqual(@as(i32, 0), pane.body.vsel.col);
try std.testing.expect(pane.body.vsel.active and pane.body.vsel.explicit);
@@ -2744,7 +2764,7 @@ const OutputTests = struct {
try fillResults(p, 0, "/", .{ .query = .hover }, "", try p.gpa.dupe(u8, "short\n"), null);
try std.testing.expectEqualStrings("short\n", result.file.?.content);
try std.testing.expect(!result.body.vsel.active and !result.body.msel.active and !result.body.select);
- try std.testing.expectEqual(@as(u8, 0), result.body.nsel);
+ try std.testing.expectEqual(@as(u16, 0), result.body.nsel);
try std.testing.expectEqual(@as(i32, 0), result.body.cur_row);
try std.testing.expectEqual(@as(i32, 0), result.body.cur_col);
try std.testing.expectEqual(@as(usize, 0), result.file.?.scroll);
@@ -4242,7 +4262,7 @@ test "an empty counted paste leaves no count for the next motion" {
const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 60, .rows = 12 });
defer p.deinit();
const pane = try p.setTestFile("abcdefgh\n");
- if (empty_register) p.yank = try p.gpa.dupe(u8, "");
+ if (empty_register) p.registers.put(p.gpa, '"', "", 0, 1, true);
for ("3p") |cp| p.update(.{ .key = .{ .cp = cp } });
try std.testing.expectEqual(modal.Normal.State{}, pane.body.normal);
p.update(.{ .key = .{ .cp = 'l' } });
@@ -4543,11 +4563,12 @@ const LookResetTests = struct {
pane.body.cur_col = 3;
pane.body.vsel = .{ .active = true, .explicit = true, .row = 0, .col = 0 };
pane.body.msel = .{ .active = true, .r0 = 0, .r1 = 1 };
+ _ = pane.body.reserveSels();
pane.body.sels[0] = .{ .row = 1, .col = 2, .arow = 0, .acol = 1 };
pane.body.nsel = 1;
pane.body.select = true;
pane.body.normal.count = 5;
- pane.body.append_at = .{ .row = 0, .col = 3 };
+ pane.body.restore_cursor = true;
pane.body.sticky_col = 7;
for (0..pane.sel.len) |slot| {
pane.clearPointerSelection(slot);
@@ -4564,10 +4585,10 @@ const LookResetTests = struct {
fn cleared(pane: *const Pane) !void {
try std.testing.expect(!pane.body.msel.active);
- try std.testing.expectEqual(@as(u8, 0), pane.body.nsel);
+ try std.testing.expectEqual(@as(u16, 0), pane.body.nsel);
try std.testing.expect(!pane.body.select);
try std.testing.expectEqual(modal.Normal.State{}, pane.body.normal);
- try std.testing.expect(pane.body.append_at == null);
+ try std.testing.expect(!pane.body.restore_cursor);
try std.testing.expectEqual(@as(i32, -1), pane.body.sticky_col);
for (pane.sel) |selection| try std.testing.expectEqual(.none, selection.state);
for (pane.pointer_selections) |selection| try std.testing.expect(selection == null);