this repo has no description
13
fork

Configure Feed

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

at 01605eebf65be21caa85ee9d840047f864553308 129 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.ArrayList(u8) = undefined, 14 style: Style = .{}, 15 uri: std.ArrayList(u8) = undefined, 16 uri_id: std.ArrayList(u8) = undefined, 17 // if we got skipped because of a wide character 18 skipped: bool = false, 19 default: bool = true, 20 21 pub fn eql(self: InternalCell, cell: Cell) bool { 22 // fastpath when both cells are default 23 if (self.default and cell.default) return true; 24 // this is actually faster than std.meta.eql on the individual items. 25 // Our strings are always small, usually less than 4 bytes so the simd 26 // usage in std.mem.eql has too much overhead vs looping the bytes 27 if (!std.mem.eql(u8, self.char.items, cell.char.grapheme)) return false; 28 if (!Style.eql(self.style, cell.style)) return false; 29 if (!std.mem.eql(u8, self.uri.items, cell.link.uri)) return false; 30 if (!std.mem.eql(u8, self.uri_id.items, cell.link.params)) return false; 31 return true; 32 } 33}; 34 35width: u16 = 0, 36height: u16 = 0, 37 38buf: []InternalCell = undefined, 39 40cursor_row: u16 = 0, 41cursor_col: u16 = 0, 42cursor_vis: bool = false, 43cursor_shape: CursorShape = .default, 44 45mouse_shape: MouseShape = .default, 46 47/// sets each cell to the default cell 48pub fn init(alloc: std.mem.Allocator, w: u16, h: u16) !InternalScreen { 49 var screen = InternalScreen{ 50 .buf = try alloc.alloc(InternalCell, @as(usize, @intCast(w)) * h), 51 }; 52 for (screen.buf, 0..) |_, i| { 53 screen.buf[i] = .{ 54 .char = try std.ArrayList(u8).initCapacity(alloc, 1), 55 .uri = std.ArrayList(u8).init(alloc), 56 .uri_id = std.ArrayList(u8).init(alloc), 57 }; 58 try screen.buf[i].char.append(' '); 59 } 60 screen.width = w; 61 screen.height = h; 62 return screen; 63} 64 65pub fn deinit(self: *InternalScreen, alloc: std.mem.Allocator) void { 66 for (self.buf, 0..) |_, i| { 67 self.buf[i].char.deinit(); 68 self.buf[i].uri.deinit(); 69 self.buf[i].uri_id.deinit(); 70 } 71 72 alloc.free(self.buf); 73} 74 75/// writes a cell to a location. 0 indexed 76pub fn writeCell( 77 self: *InternalScreen, 78 col: u16, 79 row: u16, 80 cell: Cell, 81) void { 82 if (self.width < col) { 83 // column out of bounds 84 return; 85 } 86 if (self.height < row) { 87 // height out of bounds 88 return; 89 } 90 const i = (@as(usize, @intCast(row)) * self.width) + col; 91 assert(i < self.buf.len); 92 self.buf[i].char.clearRetainingCapacity(); 93 self.buf[i].char.appendSlice(cell.char.grapheme) catch { 94 log.warn("couldn't write grapheme", .{}); 95 }; 96 self.buf[i].uri.clearRetainingCapacity(); 97 self.buf[i].uri.appendSlice(cell.link.uri) catch { 98 log.warn("couldn't write uri", .{}); 99 }; 100 self.buf[i].uri_id.clearRetainingCapacity(); 101 self.buf[i].uri_id.appendSlice(cell.link.params) catch { 102 log.warn("couldn't write uri_id", .{}); 103 }; 104 self.buf[i].style = cell.style; 105 self.buf[i].default = cell.default; 106} 107 108pub fn readCell(self: *InternalScreen, col: u16, row: u16) ?Cell { 109 if (self.width < col) { 110 // column out of bounds 111 return null; 112 } 113 if (self.height < row) { 114 // height out of bounds 115 return null; 116 } 117 const i = (row * self.width) + col; 118 assert(i < self.buf.len); 119 const cell = self.buf[i]; 120 return .{ 121 .char = .{ .grapheme = cell.char.items }, 122 .style = cell.style, 123 .link = .{ 124 .uri = cell.uri.items, 125 .params = cell.uri_id.items, 126 }, 127 .default = cell.default, 128 }; 129}