Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 39s
This also contains some minor refactoring to improve the readability and understandability of the library (i.e. renaming of Style.Attributes to Style.Emphasis).
97 lines
3.2 KiB
Zig
97 lines
3.2 KiB
Zig
const std = @import("std");
|
|
const zterm = @import("zterm");
|
|
|
|
const App = zterm.App(union(enum) {});
|
|
|
|
const log = std.log.scoped(.default);
|
|
|
|
const QuitText = struct {
|
|
const text = "Press ctrl+c to quit.";
|
|
|
|
pub fn element(this: *@This()) App.Element {
|
|
return .{ .ptr = this, .vtable = &.{ .content = content } };
|
|
}
|
|
|
|
pub fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Size) !void {
|
|
_ = ctx;
|
|
std.debug.assert(cells.len == @as(usize, size.cols) * @as(usize, size.rows));
|
|
|
|
const row = 2;
|
|
const col = size.cols / 2 -| (text.len / 2);
|
|
const anchor = (row * size.cols) + col;
|
|
|
|
for (text, 0..) |cp, idx| {
|
|
cells[anchor + idx].style.fg = .white;
|
|
cells[anchor + idx].style.bg = .black;
|
|
cells[anchor + idx].cp = cp;
|
|
|
|
// NOTE: do not write over the contents of this `Container`'s `Size`
|
|
if (anchor + idx == cells.len - 1) break;
|
|
}
|
|
}
|
|
};
|
|
|
|
pub fn main() !void {
|
|
errdefer |err| log.err("Application Error: {any}", .{err});
|
|
|
|
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
|
|
defer if (gpa.deinit() == .leak) {
|
|
log.err("memory leak", .{});
|
|
};
|
|
const allocator = gpa.allocator();
|
|
|
|
var app: App = .init;
|
|
var renderer = zterm.Renderer.Buffered.init(allocator);
|
|
defer renderer.deinit();
|
|
|
|
var quit_text: QuitText = .{};
|
|
const element = quit_text.element();
|
|
|
|
var container = try App.Container.init(allocator, .{
|
|
.layout = .{
|
|
.gap = 2,
|
|
.padding = .{ .top = 5, .bottom = 3, .left = 3, .right = 3 },
|
|
},
|
|
}, element);
|
|
defer container.deinit();
|
|
|
|
var box = try App.Container.init(allocator, .{
|
|
.layout = .{ .direction = .horizontal },
|
|
.min_size = .{ .cols = 3 * std.meta.fields(zterm.Color).len }, // ensure enough columns to render all colors -> scrollable otherwise
|
|
}, .{});
|
|
defer box.deinit();
|
|
|
|
inline for (std.meta.fields(zterm.Color)) |field| {
|
|
if (comptime field.value == 0) continue; // zterm.Color.default == 0 -> skip
|
|
try box.append(try App.Container.init(allocator, .{ .rectangle = .{ .fill = @enumFromInt(field.value) } }, .{}));
|
|
}
|
|
var scrollable: App.Scrollable = .init(box);
|
|
try container.append(try App.Container.init(allocator, .{}, scrollable.element()));
|
|
|
|
try app.start();
|
|
defer app.stop() catch |err| log.err("Failed to stop application: {any}", .{err});
|
|
|
|
while (true) {
|
|
const event = app.nextEvent();
|
|
log.debug("received event: {s}", .{@tagName(event)});
|
|
|
|
switch (event) {
|
|
.init => continue,
|
|
.quit => break,
|
|
.resize => |size| try renderer.resize(size),
|
|
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
|
|
.err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }),
|
|
else => {},
|
|
}
|
|
|
|
container.handle(event) catch |err| app.postEvent(.{
|
|
.err = .{
|
|
.err = err,
|
|
.msg = "Container Event handling failed",
|
|
},
|
|
});
|
|
try renderer.render(@TypeOf(container), &container);
|
|
try renderer.flush();
|
|
}
|
|
}
|