a modern tui library written in zig
at main 2.8 kB view raw
1const std = @import("std"); 2const vaxis = @import("vaxis"); 3const vxfw = vaxis.vxfw; 4 5const Text = vxfw.Text; 6const ListView = vxfw.ListView; 7const Widget = vxfw.Widget; 8 9const Model = struct { 10 list_view: ListView, 11 12 pub fn widget(self: *Model) Widget { 13 return .{ 14 .userdata = self, 15 .eventHandler = Model.typeErasedEventHandler, 16 .drawFn = Model.typeErasedDrawFn, 17 }; 18 } 19 20 pub fn typeErasedEventHandler(ptr: *anyopaque, ctx: *vxfw.EventContext, event: vxfw.Event) anyerror!void { 21 const self: *Model = @ptrCast(@alignCast(ptr)); 22 try ctx.requestFocus(self.list_view.widget()); 23 switch (event) { 24 .key_press => |key| { 25 if (key.matches('q', .{}) or key.matchExact('c', .{ .ctrl = true })) { 26 ctx.quit = true; 27 return; 28 } 29 }, 30 else => {}, 31 } 32 } 33 34 fn typeErasedDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) std.mem.Allocator.Error!vxfw.Surface { 35 const self: *Model = @ptrCast(@alignCast(ptr)); 36 const max = ctx.max.size(); 37 38 const list_view: vxfw.SubSurface = .{ 39 .origin = .{ .row = 1, .col = 1 }, 40 .surface = try self.list_view.draw(ctx), 41 }; 42 43 const children = try ctx.arena.alloc(vxfw.SubSurface, 1); 44 children[0] = list_view; 45 46 return .{ 47 .size = max, 48 .widget = self.widget(), 49 .buffer = &.{}, 50 .children = children, 51 }; 52 } 53}; 54 55pub fn main() !void { 56 var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 57 defer _ = gpa.deinit(); 58 59 const allocator = gpa.allocator(); 60 61 var app = try vxfw.App.init(allocator); 62 defer app.deinit(); 63 64 const model = try allocator.create(Model); 65 defer allocator.destroy(model); 66 67 const n = 80; 68 var texts = try std.ArrayList(Widget).initCapacity(allocator, n); 69 70 var allocs = try std.ArrayList(*Text).initCapacity(allocator, n); 71 defer { 72 for (allocs.items) |tw| { 73 allocator.free(tw.text); 74 allocator.destroy(tw); 75 } 76 allocs.deinit(allocator); 77 texts.deinit(allocator); 78 } 79 80 for (0..n) |i| { 81 const t = std.fmt.allocPrint(allocator, "List Item {d}", .{i}) catch "placeholder"; 82 const tw = try allocator.create(Text); 83 tw.* = .{ .text = t }; 84 _ = try allocs.append(allocator, tw); 85 _ = try texts.append(allocator, tw.widget()); 86 } 87 88 model.* = .{ 89 .list_view = .{ 90 .wheel_scroll = 3, 91 .scroll = .{ 92 .wants_cursor = true, 93 }, 94 .children = .{ .slice = texts.items }, 95 }, 96 }; 97 98 try app.run(model.widget(), .{}); 99}