a modern tui library written in zig
at v0.3.0 117 lines 3.5 kB view raw
1const std = @import("std"); 2const vaxis = @import("vaxis"); 3const Cell = vaxis.Cell; 4 5const Event = union(enum) { 6 key_press: vaxis.Key, 7 winsize: vaxis.Winsize, 8}; 9 10pub const panic = vaxis.panic_handler; 11 12pub fn main() !void { 13 var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 14 defer { 15 const deinit_status = gpa.deinit(); 16 //fail test; can't try in defer as defer is executed after we return 17 if (deinit_status == .leak) { 18 std.log.err("memory leak", .{}); 19 } 20 } 21 const alloc = gpa.allocator(); 22 23 var tty = try vaxis.Tty.init(); 24 var vx = try vaxis.init(alloc, .{}); 25 defer vx.deinit(alloc, tty.anyWriter()); 26 27 var loop: vaxis.Loop(Event) = .{ .tty = &tty, .vaxis = &vx }; 28 try loop.init(); 29 30 try loop.start(); 31 defer loop.stop(); 32 33 try vx.enterAltScreen(tty.anyWriter()); 34 try vx.queryTerminal(tty.anyWriter(), 1 * std.time.ns_per_s); 35 36 try vx.queryColor(tty.anyWriter(), .fg); 37 try vx.queryColor(tty.anyWriter(), .bg); 38 var pct: u8 = 0; 39 var dir: enum { 40 up, 41 down, 42 } = .up; 43 44 const fg = [_]u8{ 192, 202, 245 }; 45 const bg = [_]u8{ 26, 27, 38 }; 46 47 // block until we get a resize 48 while (true) { 49 const event = loop.nextEvent(); 50 switch (event) { 51 .key_press => |key| if (key.matches('c', .{ .ctrl = true })) return, 52 .winsize => |ws| { 53 try vx.resize(alloc, tty.anyWriter(), ws); 54 break; 55 }, 56 } 57 } 58 59 while (true) { 60 while (loop.tryEvent()) |event| { 61 switch (event) { 62 .key_press => |key| if (key.matches('c', .{ .ctrl = true })) return, 63 .winsize => |ws| try vx.resize(alloc, tty.anyWriter(), ws), 64 } 65 } 66 67 const win = vx.window(); 68 win.clear(); 69 70 const color = try blendColors(bg, fg, pct); 71 72 const style: vaxis.Style = .{ .fg = color }; 73 74 const segment: vaxis.Segment = .{ 75 .text = vaxis.logo, 76 .style = style, 77 }; 78 const center = vaxis.widgets.alignment.center(win, 28, 4); 79 _ = try center.printSegment(segment, .{ .wrap = .grapheme }); 80 try vx.render(tty.anyWriter()); 81 std.time.sleep(16 * std.time.ns_per_ms); 82 switch (dir) { 83 .up => { 84 pct += 1; 85 if (pct == 100) dir = .down; 86 }, 87 .down => { 88 pct -= 1; 89 if (pct == 0) dir = .up; 90 }, 91 } 92 } 93} 94 95/// blend two rgb colors. pct is an integer percentage for te portion of 'b' in 96/// 'a' 97fn blendColors(a: [3]u8, b: [3]u8, pct: u8) !vaxis.Color { 98 // const r_a = (a[0] * (100 -| pct)) / 100; 99 100 const r_a = (@as(u16, a[0]) * @as(u16, (100 -| pct))) / 100; 101 const r_b = (@as(u16, b[0]) * @as(u16, pct)) / 100; 102 103 const g_a = (@as(u16, a[1]) * @as(u16, (100 -| pct))) / 100; 104 const g_b = (@as(u16, b[1]) * @as(u16, pct)) / 100; 105 // const g_a = try std.math.mul(u8, a[1], (100 -| pct) / 100); 106 // const g_b = (b[1] * pct) / 100; 107 108 const b_a = (@as(u16, a[2]) * @as(u16, (100 -| pct))) / 100; 109 const b_b = (@as(u16, b[2]) * @as(u16, pct)) / 100; 110 // const b_a = try std.math.mul(u8, a[2], (100 -| pct) / 100); 111 // const b_b = (b[2] * pct) / 100; 112 return .{ .rgb = [_]u8{ 113 @min(r_a + r_b, 255), 114 @min(g_a + g_b, 255), 115 @min(b_a + b_b, 255), 116 } }; 117}