summaryrefslogtreecommitdiff
path: root/test/mode.zig
blob: c7d7d5486437b0399af9f290f0e0d9c3b825da54 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
const std = @import("std");
const pardes = @import("pardes");
const panes = pardes.panes;
const Pardes = pardes.Pardes;

fn mode(p: *Pardes, id: usize, expected: panes.Text.Mode) !void {
    try std.testing.expect(p.executeBuiltinLine(id, "Mode"));
    try std.testing.expectEqual(expected, p.panes[id].?.body.mode);
    try std.testing.expect(p.panes[id].?.focus == .body);
}

fn clickModeTag(p: *Pardes) !void {
    const pane = p.panes[0].?;
    const text = try pardes.tagline.tagText(p, p.scratch.allocator(), pane);
    const col = std.mem.indexOf(u8, text, "Mode") orelse return error.MissingModeTag;
    const rect = p.rects[0];
    const row = if (p.settings.tag_bottom) rect.y + rect.h - pardes.BOX_H else rect.y;
    for ([_]pardes.Mouse.Kind{ .press, .release }) |kind|
        p.update(.{ .mouse = .{ .button = .left, .kind = kind, .col = rect.x + pardes.TAG_TEXT_INSET + @as(u16, @intCast(col)), .row = row } });
    try std.testing.expect(pane.focus == .tag);
}

fn customTag(pane: *pardes.Pane, text: []const u8) !void {
    if (pane.tag.own) |own| pane.gpa.free(own);
    pane.tag.own = try pane.gpa.dupe(u8, text);
}

test "Mode cycles terminal modes and keeps legacy toggle and custom tags" {
    if (comptime !panes.Terminal.enabled) return error.SkipZigTest;
    const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 100 });
    defer p.deinit();
    p.presentation.enabled = false;
    while (p.nextEffect()) |_| {}
    const pane = p.panes[0].?;
    try std.testing.expectEqual(panes.Text.Mode.tty, pane.body.mode);
    try std.testing.expect(std.mem.indexOf(u8, try pardes.tagline.tagText(p, p.scratch.allocator(), pane), " Mode") != null);
    try mode(p, 0, .normal);
    try mode(p, 0, .insert);
    // A clicked tag is typed into; its execute key is a normal-mode key, as
    // a body's is, and the body keeps its own mode meanwhile.
    try clickModeTag(p);
    try std.testing.expectEqual(panes.Text.Mode.insert, pane.tag.mode);
    try std.testing.expectEqual(panes.Text.Mode.insert, pane.body.mode);
    p.update(.{ .key = .{ .cp = pardes.Key.escape } });
    p.update(.{ .key = .{ .cp = pardes.Key.tab } });
    try std.testing.expectEqual(panes.Text.Mode.tty, pane.body.mode);
    try std.testing.expect(pane.focus == .body);
    while (p.nextEffect()) |effect| try std.testing.expect(effect != .write);

    try customTag(pane, " Togglettymode Keep");
    try mode(p, 0, .normal);
    try mode(p, 0, .insert);
    try std.testing.expect(p.executeBuiltinLine(0, "Togglettymode"));
    try std.testing.expectEqual(panes.Text.Mode.tty, pane.body.mode);
    p.update(.{ .key = .{ .cp = 'b', .ctrl = true } });
    try std.testing.expectEqual(panes.Text.Mode.normal, pane.body.mode);
    p.update(.{ .key = .{ .cp = 'b', .ctrl = true } });
    try std.testing.expectEqual(panes.Text.Mode.tty, pane.body.mode);
    try std.testing.expectEqualStrings(" Togglettymode Keep", pane.tag.own.?);
}

test "Mode from actual tag Exec preserves parked file and output insert transactions" {
    for ([_]bool{ false, true }) |output| {
        for ([_]bool{ false, true }) |normal_tag| {
            const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 100 });
            defer p.deinit();
            p.presentation.enabled = false;
            const pane = try p.setTestFile("ab\n");
            if (output) pane.file.?.output = .{ .from = .search };
            try std.testing.expect(std.mem.indexOf(u8, try pardes.tagline.tagText(p, p.scratch.allocator(), pane), " Mode") == null);
            try customTag(pane, " Mode");
            try mode(p, 0, .insert);
            p.update(.{ .key = .{ .cp = '界', .text = "界" } });
            p.update(.{ .key = .{ .cp = 'x', .text = "x" } });
            try std.testing.expectEqualStrings("界xab\n", pane.file.?.content);
            try clickModeTag(p);
            try std.testing.expectEqual(panes.Text.Mode.insert, pane.body.mode);
            if (normal_tag) pane.tag.mode = .normal else p.update(.{ .key = .{ .cp = pardes.Key.escape } });
            p.update(.{ .key = .{ .cp = pardes.Key.tab } });
            try std.testing.expectEqual(panes.Text.Mode.normal, pane.body.mode);
            try std.testing.expect(pane.focus == .body);
            try std.testing.expect(pane.body.append_at == null);
            p.update(.{ .key = .{ .cp = 'u' } });
            try std.testing.expectEqualStrings("ab\n", pane.file.?.content);
            p.update(.{ .key = .{ .cp = 'a' } });
            p.update(.{ .key = .{ .cp = 'z', .text = "z" } });
            try std.testing.expect(pane.body.append_at != null);
            try mode(p, 0, .normal);
            try std.testing.expect(pane.body.append_at == null);
            p.update(.{ .key = .{ .cp = 'u' } });
            try std.testing.expectEqualStrings("ab\n", pane.file.?.content);
        }
    }
}

test "Mode leaves image and PDF document modes unchanged" {
    const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true });
    defer p.deinit();
    const picture = try panes.Image.create(p, 1, "/mode-test.png", &.{});
    try mode(p, 1, .normal);
    try std.testing.expect(picture.image != null);
    if (comptime panes.Pdf.enabled) {
        var tmp = std.testing.tmpDir(.{});
        defer tmp.cleanup();
        const bytes = try panes.Pdf.pdf.makeLinksTestPdf(std.testing.allocator);
        defer std.testing.allocator.free(bytes);
        try tmp.dir.writeFile(std.testing.io, .{ .sub_path = "mode.pdf", .data = bytes });
        var buffer: [4096]u8 = undefined;
        const len = try tmp.dir.realPath(std.testing.io, &buffer);
        const path = try std.fmt.allocPrint(std.testing.allocator, "{s}/mode.pdf", .{buffer[0..len]});
        defer std.testing.allocator.free(path);
        const document = try panes.Pdf.openPane(p, 2, path, 1);
        const page = document.pdf.?.page;
        try mode(p, 2, .normal);
        try std.testing.expectEqual(page, document.pdf.?.page);
    }
}