this repo has no description
13
fork

Configure Feed

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

at b58ae3a2fa16b3b7f11d2a7297c73a1e839d035b 136 lines 3.7 kB view raw
1const std = @import("std"); 2 3/// Control bytes. See man 7 ascii 4pub const C0 = enum(u8) { 5 NUL = 0x00, 6 SOH = 0x01, 7 STX = 0x02, 8 ETX = 0x03, 9 EOT = 0x04, 10 ENQ = 0x05, 11 ACK = 0x06, 12 BEL = 0x07, 13 BS = 0x08, 14 HT = 0x09, 15 LF = 0x0a, 16 VT = 0x0b, 17 FF = 0x0c, 18 CR = 0x0d, 19 SO = 0x0e, 20 SI = 0x0f, 21 DLE = 0x10, 22 DC1 = 0x11, 23 DC2 = 0x12, 24 DC3 = 0x13, 25 DC4 = 0x14, 26 NAK = 0x15, 27 SYN = 0x16, 28 ETB = 0x17, 29 CAN = 0x18, 30 EM = 0x19, 31 SUB = 0x1a, 32 ESC = 0x1b, 33 FS = 0x1c, 34 GS = 0x1d, 35 RS = 0x1e, 36 US = 0x1f, 37}; 38 39pub const CSI = struct { 40 intermediate: ?u8 = null, 41 private_marker: ?u8 = null, 42 43 final: u8, 44 params: []const u8, 45 46 pub fn hasIntermediate(self: CSI, b: u8) bool { 47 return b == self.intermediate orelse return false; 48 } 49 50 pub fn hasPrivateMarker(self: CSI, b: u8) bool { 51 return b == self.private_marker orelse return false; 52 } 53 54 pub fn iterator(self: CSI, comptime T: type) ParamIterator(T) { 55 return .{ .bytes = self.params }; 56 } 57 58 pub fn format(self: CSI, writer: anytype) !void { 59 if (self.private_marker == null and self.intermediate == null) 60 try writer.print("CSI {s} {c}", .{ 61 self.params, 62 self.final, 63 }) 64 else if (self.private_marker != null and self.intermediate == null) 65 try writer.print("CSI {c} {s} {c}", .{ 66 self.private_marker.?, 67 self.params, 68 self.final, 69 }) 70 else if (self.private_marker == null and self.intermediate != null) 71 try writer.print("CSI {s} {c} {c}", .{ 72 self.params, 73 self.intermediate.?, 74 self.final, 75 }) 76 else 77 try writer.print("CSI {c} {s} {c} {c}", .{ 78 self.private_marker.?, 79 self.params, 80 self.intermediate.?, 81 self.final, 82 }); 83 } 84}; 85 86pub fn ParamIterator(T: type) type { 87 return struct { 88 const Self = @This(); 89 90 bytes: []const u8, 91 idx: usize = 0, 92 /// indicates the next parameter will be a sub parameter of the current 93 next_is_sub: bool = false, 94 /// indicates the current parameter was an empty string 95 is_empty: bool = false, 96 97 pub fn next(self: *Self) ?T { 98 // reset state 99 self.next_is_sub = false; 100 self.is_empty = false; 101 102 const start = self.idx; 103 var val: T = 0; 104 while (self.idx < self.bytes.len) { 105 defer self.idx += 1; // defer so we trigger on return as well 106 const b = self.bytes[self.idx]; 107 switch (b) { 108 0x30...0x39 => { 109 val = (val * 10) + (b - 0x30); 110 if (self.idx == self.bytes.len - 1) return val; 111 }, 112 ':', ';' => { 113 self.next_is_sub = b == ':'; 114 self.is_empty = self.idx == start; 115 return val; 116 }, 117 else => return null, 118 } 119 } 120 return null; 121 } 122 123 /// verifies there are at least n more parameters 124 pub fn hasAtLeast(self: *Self, n: usize) bool { 125 const start = self.idx; 126 defer self.idx = start; 127 128 var i: usize = 0; 129 while (self.next()) |_| { 130 i += 1; 131 if (i >= n) return true; 132 } 133 return i >= n; 134 } 135 }; 136}