this repo has no description
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 3fde9f2ff7f8ea58b4b5c4a90256b34a5b5ea6be 133 lines 3.9 kB view raw
1const std = @import("std"); 2const assert = std.debug.assert; 3const Style = @import("Cell.zig").Style; 4const Cell = @import("Cell.zig"); 5const MouseShape = @import("Mouse.zig").Shape; 6const CursorShape = Cell.CursorShape; 7 8const log = std.log.scoped(.vaxis); 9 10const InternalScreen = @This(); 11 12pub const InternalCell = struct { 13 char: std.ArrayListUnmanaged(u8) = .empty, 14 style: Style = .{}, 15 uri: std.ArrayListUnmanaged(u8) = .empty, 16 uri_id: std.ArrayListUnmanaged(u8) = .empty, 17 // if we got skipped because of a wide character 18 skipped: bool = false, 19 default: bool = true, 20 21 // If we should skip rendering *this* round due to being printed over previously (from a scaled 22 // cell, for example) 23 skip: bool = false, 24 25 scale: Cell.Scale = .{}, 26 27 pub fn eql(self: InternalCell, cell: Cell) bool { 28 29 // fastpath when both cells are default 30 if (self.default and cell.default) return true; 31 32 return std.mem.eql(u8, self.char.items, cell.char.grapheme) and 33 Style.eql(self.style, cell.style) and 34 std.mem.eql(u8, self.uri.items, cell.link.uri) and 35 std.mem.eql(u8, self.uri_id.items, cell.link.params); 36 } 37}; 38 39arena: *std.heap.ArenaAllocator, 40width: u16 = 0, 41height: u16 = 0, 42 43buf: []InternalCell, 44 45cursor_row: u16 = 0, 46cursor_col: u16 = 0, 47cursor_vis: bool = false, 48cursor_shape: CursorShape = .default, 49 50mouse_shape: MouseShape = .default, 51 52/// sets each cell to the default cell 53pub fn init(alloc: std.mem.Allocator, w: u16, h: u16) !InternalScreen { 54 const arena = try alloc.create(std.heap.ArenaAllocator); 55 arena.* = .init(alloc); 56 var screen = InternalScreen{ 57 .arena = arena, 58 .buf = try arena.allocator().alloc(InternalCell, @as(usize, @intCast(w)) * h), 59 }; 60 for (screen.buf, 0..) |_, i| { 61 screen.buf[i] = .{ 62 .char = try std.ArrayListUnmanaged(u8).initCapacity(arena.allocator(), 1), 63 .uri = .empty, 64 .uri_id = .empty, 65 }; 66 screen.buf[i].char.appendAssumeCapacity(' '); 67 } 68 screen.width = w; 69 screen.height = h; 70 return screen; 71} 72 73pub fn deinit(self: *InternalScreen, alloc: std.mem.Allocator) void { 74 self.arena.deinit(); 75 alloc.destroy(self.arena); 76 self.* = undefined; 77} 78 79/// writes a cell to a location. 0 indexed 80pub fn writeCell( 81 self: *InternalScreen, 82 col: u16, 83 row: u16, 84 cell: Cell, 85) void { 86 if (self.width < col) { 87 // column out of bounds 88 return; 89 } 90 if (self.height < row) { 91 // height out of bounds 92 return; 93 } 94 const i = (@as(usize, @intCast(row)) * self.width) + col; 95 assert(i < self.buf.len); 96 self.buf[i].char.clearRetainingCapacity(); 97 self.buf[i].char.appendSlice(self.arena.allocator(), cell.char.grapheme) catch { 98 log.warn("couldn't write grapheme", .{}); 99 }; 100 self.buf[i].uri.clearRetainingCapacity(); 101 self.buf[i].uri.appendSlice(self.arena.allocator(), cell.link.uri) catch { 102 log.warn("couldn't write uri", .{}); 103 }; 104 self.buf[i].uri_id.clearRetainingCapacity(); 105 self.buf[i].uri_id.appendSlice(self.arena.allocator(), cell.link.params) catch { 106 log.warn("couldn't write uri_id", .{}); 107 }; 108 self.buf[i].style = cell.style; 109 self.buf[i].default = cell.default; 110} 111 112pub fn readCell(self: *InternalScreen, col: u16, row: u16) ?Cell { 113 if (self.width < col) { 114 // column out of bounds 115 return null; 116 } 117 if (self.height < row) { 118 // height out of bounds 119 return null; 120 } 121 const i = (row * self.width) + col; 122 assert(i < self.buf.len); 123 const cell = self.buf[i]; 124 return .{ 125 .char = .{ .grapheme = cell.char.items }, 126 .style = cell.style, 127 .link = .{ 128 .uri = cell.uri.items, 129 .params = cell.uri_id.items, 130 }, 131 .default = cell.default, 132 }; 133}