diff options
Diffstat (limited to 'src/draw.zig')
| -rw-r--r-- | src/draw.zig | 62 |
1 files changed, 58 insertions, 4 deletions
diff --git a/src/draw.zig b/src/draw.zig index 9c9e11dd..ad24153f 100644 --- a/src/draw.zig +++ b/src/draw.zig @@ -63,7 +63,7 @@ pub fn place(p: *Pardes, s: *Surface) void { // A folded pane is its tag rows and nothing else. if (pane.collapsed) continue; const body_h = r.h -| pane.tag_rows; - const line: i32 = if (pane.file) |f| @intCast(@min(f.scroll, std.math.maxInt(i32))) else if (pane.isTerminal()) panes.Terminal.gridOffset(pane) else 0; + const line: i32 = if (pane.file) |f| @intCast(@min(f.scroll, std.math.maxInt(i32))) else if (pane.isTerminal()) panes.terminal.gridOffset(pane) else 0; s.addRegion(.{ .kind = .body, .owner = owner, .serial = pane.serial, .active = active, .line = line, .rect = .{ .x = r.x + config.GUTTER, .y = body_y, .w = r.w - config.GUTTER, .h = body_h } }); var rail: Region = .{ .kind = .rail, .owner = owner, .serial = pane.serial, .active = active, .rect = .{ .x = r.x, .y = body_y, .w = config.GUTTER, .h = body_h } }; // An image's rail has no thumb; a native PDF's is measured as its @@ -78,7 +78,7 @@ pub fn place(p: *Pardes, s: *Surface) void { .offset = page, .len = 1, } else blk: { - const gsb = panes.Terminal.scrollbar(pane); + const gsb = panes.terminal.scrollbar(pane); break :blk .{ .total = gsb.total, .offset = gsb.offset, .len = gsb.len }; }; const track_h: usize = body_h; @@ -241,7 +241,7 @@ fn glideCursor(p: *Pardes, s: *Surface) void { if (inside) frame = paneFrame(s, pane.serial, rect); const origin: [2]f32 = .{ @floatFromInt(rect.x), @floatFromInt(rect.y) }; const view = p.cursor_view; - const line: i64 = if (pane.file) |f| @intCast(f.scroll) else if (pane.isTerminal()) panes.Terminal.gridOffset(pane) else 0; + const line: i64 = if (pane.file) |f| @intCast(f.scroll) else if (pane.isTerminal()) panes.terminal.gridOffset(pane) else 0; if (view.serial == pane.serial and view.inside == inside) { // The pane moved in the layout: the springs move with it (its // own cursor's; one in a column's tag stays). @@ -719,7 +719,7 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface { sb_off = page; sb_total = if (comptime pdf_enabled) at.pdf.?.page_count else 0; } else { - const sb = panes.Terminal.scrollbar(at); + const sb = panes.terminal.scrollbar(at); sb_off = sb.offset; sb_total = sb.total; } @@ -1477,6 +1477,60 @@ test "a grip's four states, focused or not and clean or dirty, are each its own pane.file.?.revision = pane.file.?.saved_revision; } +test "every theme draws a file's name, a +Errors and a Tty word in a tint, never the tag's plain ink" { + const gpa = std.testing.allocator; + const p = try Pardes.init(gpa, .{ .cols = 120, .rows = 40, .tty_only = true }); + defer p.deinit(); + _ = try p.setTestFile("text\n"); + try std.testing.expect(p.executeBuiltinLine(0, "Tty+sh")); + const terminal = p.active; + p.acknowledgeShell(terminal, "/bin/sh", false); + try @import("Output.zig").openErrors(p, 0, try gpa.dupe(u8, "oops\n")); + while (p.nextEffect()) |_| {} + p.animate_theme_changes = false; + const errors = for (p.panes, 0..) |slot, id| { + const pane = slot orelse continue; + if (pane.file) |f| if (std.mem.endsWith(u8, f.path, "+Errors")) break id; + } else return error.NoErrorsPane; + const Probe = struct { id: usize, word: []const u8 }; + const probes = [_]Probe{ .{ .id = 0, .word = "test.txt" }, .{ .id = terminal, .word = "Tty+sh" }, .{ .id = errors, .word = "+Errors" } }; + var arena: std.heap.ArenaAllocator = .init(gpa); + defer arena.deinit(); + for (pardes.themes, 0..) |theme, index| { + colors.setThemeIndex(p, index); + // Each pane focused in turn: every word on both grounds. + for (probes) |focused| { + p.active = focused.id; + _ = arena.reset(.retain_capacity); + const s = try p.render(arena.allocator()); + for (probes) |probe| { + const r = p.rects[probe.id]; + const y = p.tagTop(p.panes[probe.id].?, r); + // The row's text, and the column each byte of it is drawn at. + var row: [512]u8 = undefined; + var cols: [512]u16 = undefined; + var len: usize = 0; + for (r.x..r.x + r.w) |x| { + const g = s.at(@intCast(x), y).grapheme(); + for (if (g.len == 0) " " else g) |byte| if (len < row.len) { + row[len] = byte; + cols[len] = @intCast(x); + len += 1; + }; + } + const name = std.mem.indexOf(u8, row[0..len], probe.word) orelse return error.WordNotDrawn; + const plain = std.mem.indexOf(u8, row[0..len], " Del") orelse return error.WordNotDrawn; + const tint = s.at(cols[name], y).style.fg; + const ink = s.at(cols[plain + 1], y).style.fg; + if (std.meta.eql(tint, ink)) std.debug.print("{s}: {s} drawn in the tag's ink\n", .{ theme.name, probe.word }); + try std.testing.expect(!std.meta.eql(tint, ink)); + // The whole word, in the one tint. + try std.testing.expect(std.meta.eql(s.at(cols[name + probe.word.len - 1], y).style.fg, tint)); + } + } + } +} + test "a tag of three rows has its grip on the first, and band under it that still grabs the pane" { const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 100, .rows = 30 }); defer p.deinit(); |
