Something went wrong. Try again.
A charm-like tui library
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394//! Mirrors bubbletea's `examples/progress-animated`: bumps progress by//! 25% every second; bar springs toward each new target.const std = @import("std");const matcha = @import("matcha");const blush = @import("blush");const leaves = @import("leaves");
const Writer = std.Io.Writer;
const padding: u16 = 2;const max_width: u16 = 80;
const Model = struct { model: matcha.Model = .{ .vtable = &.{ .init = init, .update = update, .view = view, } }, quitting: bool = false, // Default blueberry → neon pink blend matches bubbletea's // `WithDefaultBlend()`. progress: leaves.Progress = .{ .full_colors = &.{ .{ .rgb = .{ .r = 0x5A, .g = 0x56, .b = 0xE0 } }, .{ .rgb = .{ .r = 0xEE, .g = 0x6F, .b = 0xF8 } }, }, .scale_blend = false, },
fn init(m: *matcha.Model) ?matcha.Cmd { return matcha.Cmd.tick(m.gpa, std.time.ns_per_s, .tick) catch null; }
fn update(m: *matcha.Model, msg: matcha.Msg) ?matcha.Cmd { const self: *Model = @fieldParentPtr("model", m); switch (msg) { .key_press => return .quit, .window_size => |ws| { const desired: u16 = ws.width -| (padding * 2 + 4); self.progress.setWidth(@min(desired, max_width)); return null; }, .tick => { if (self.quitting) return .quit; if (self.progress.target_percent >= 1.0) { self.quitting = true; } if (self.quitting) { // At 100 % — just schedule the quit tick, don't bump further. return matcha.Cmd.tick(m.gpa, std.time.ns_per_s, .tick) catch null; } var cmds: [2]matcha.Cmd = undefined; var n: usize = 0; if (matcha.Cmd.tick(m.gpa, std.time.ns_per_s, .tick) catch null) |c| { cmds[n] = c; n += 1; } if (self.progress.incrPercent(m.gpa, 0.25)) |c| { cmds[n] = c; n += 1; } if (n == 0) return null; if (n == 1) return cmds[0]; return matcha.Cmd.batch(m.gpa, cmds[0..n]) catch cmds[0]; }, else => {}, } return self.progress.update(m.gpa, msg); }
fn view(m: *matcha.Model, w: *Writer) Writer.Error!matcha.View { const self: *Model = @fieldParentPtr("model", m); try w.writeByte('\n'); try writeSpaces(w, padding); try self.progress.view(w); try w.writeAll("\n\n"); try writeSpaces(w, padding); try w.writeAll("\x1b[38;5;243mPress any key to quit\x1b[0m\n"); return .{}; }};
fn writeSpaces(w: *Writer, n: u16) Writer.Error!void { var i: u16 = 0; while (i < n) : (i += 1) try w.writeByte(' ');}
pub fn animated(init: std.process.Init) !void { var m: Model = .{}; var program: matcha.Program = try .init(init, &m.model, .{}); defer program.deinit(); try program.run();}