Something went wrong. Try again.
A charm-like tui library
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112//! Mirrors bubbletea's `examples/list-default`: paginated list of "fave//! things" with title + description per item, DefaultDelegate styling,//! substring filter via `/`.const std = @import("std");const matcha = @import("matcha");const leaves = @import("leaves");
const Writer = std.Io.Writer;
const Entry = struct { title_text: []const u8, desc_text: []const u8,
var vt: leaves.List.Item.VTable = .{ .filter_value = filterValueFn, .title = titleFn, .description = descFn, };
fn filterValueFn(ctx: *anyopaque) []const u8 { const self: *const Entry = @ptrCast(@alignCast(ctx)); return self.title_text; } fn titleFn(ctx: *anyopaque) []const u8 { const self: *const Entry = @ptrCast(@alignCast(ctx)); return self.title_text; } fn descFn(ctx: *anyopaque) []const u8 { const self: *const Entry = @ptrCast(@alignCast(ctx)); return self.desc_text; }
fn item(self: *Entry) leaves.List.Item { return .{ .ctx = self, .vtable = &vt }; }};
var entries = [_]Entry{ .{ .title_text = "Raspberry Pi's", .desc_text = "I have 'em all over my house" }, .{ .title_text = "Nutella", .desc_text = "It's good on toast" }, .{ .title_text = "Bitter melon", .desc_text = "It cools you down" }, .{ .title_text = "Nice socks", .desc_text = "And by that I mean socks without holes" }, .{ .title_text = "Eight hours of sleep", .desc_text = "I had this once" }, .{ .title_text = "Cats", .desc_text = "Usually" }, .{ .title_text = "Plantasia, the album", .desc_text = "My plants love it too" }, .{ .title_text = "Pour over coffee", .desc_text = "It takes forever to make though" }, .{ .title_text = "VR", .desc_text = "Virtual reality...what is there to say?" }, .{ .title_text = "Noguchi Lamps", .desc_text = "Such pleasing organic forms" }, .{ .title_text = "Linux", .desc_text = "Pretty much the best OS" }, .{ .title_text = "Business school", .desc_text = "Just kidding" }, .{ .title_text = "Pottery", .desc_text = "Wet clay is a great feeling" }, .{ .title_text = "Shampoo", .desc_text = "Nothing like clean hair" }, .{ .title_text = "Table tennis", .desc_text = "It's surprisingly exhausting" }, .{ .title_text = "Milk crates", .desc_text = "Great for packing in your extra stuff" }, .{ .title_text = "Afternoon tea", .desc_text = "Especially the tea sandwich part" }, .{ .title_text = "Stickers", .desc_text = "The thicker the vinyl the better" }, .{ .title_text = "20° Weather", .desc_text = "Celsius, not Fahrenheit" }, .{ .title_text = "Warm light", .desc_text = "Like around 2700 Kelvin" }, .{ .title_text = "The vernal equinox", .desc_text = "The autumnal equinox is pretty good too" }, .{ .title_text = "Gaffer's tape", .desc_text = "Basically sticky fabric" }, .{ .title_text = "Terrycloth", .desc_text = "In other words, towel fabric" },};
const Model = struct { model: matcha.Model = .{ .vtable = &.{ .init = init, .update = update, .view = view, } }, list: leaves.List = .{ .title_text = "My Fave Things" }, delegate: leaves.List.DefaultDelegate = .{}, item_slots: [entries.len]leaves.List.Item = undefined,
fn init(m: *matcha.Model) ?matcha.Cmd { const self: *Model = @fieldParentPtr("model", m); for (&entries, 0..) |*e, i| self.item_slots[i] = e.item(); self.list.setItems(&self.item_slots); self.list.setDelegate(self.delegate.delegate()); return null; }
fn update(m: *matcha.Model, msg: matcha.Msg) ?matcha.Cmd { const self: *Model = @fieldParentPtr("model", m); switch (msg) { .key_press => |k| if (k.kind == .rune and k.rune == 'c' and k.mods.ctrl) return .quit, .interrupt => return .quit, .window_size => |ws| { self.list.setSize(ws.width -| 4, ws.height -| 2); return null; }, else => {}, } return self.list.update(m.gpa, msg); }
fn view(m: *matcha.Model, w: *Writer) Writer.Error!matcha.View { const self: *Model = @fieldParentPtr("model", m); try w.writeAll("\n "); try self.list.view(w); return .{ .alt_screen = true }; }};
pub fn list(init: std.process.Init) !void { var m: Model = .{}; defer m.list.deinit(init.gpa);
var program: matcha.Program = try .init(init, &m.model, .{}); defer program.deinit(); try program.run();}