feat(model): implement Elm architecture
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 1m2s

Now the `App` contains a state which is a user-defined `struct` which
is passed to the `handle` and `contents` callbacks for `Container`'s and
`Element`'s. Built-in `Element`'s shall not access the `App.Model` and
should therefore never cause any side-effects.

User-defined events shall be used to act as *messages* to cause
potential side-effects for the model. This is the reason why only
the `handle` callback has a non-const pointer to the `App.Model`. The
`contents` callback can only access the `App.Model` read-only to use for
generating the *view* (in context of the elm architecture).
This commit is contained in:
2025-10-26 15:58:07 +01:00
parent 8f90f57f44
commit feae9fa1a4
22 changed files with 396 additions and 319 deletions

View File

@@ -5,7 +5,7 @@ const QuitText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -41,7 +41,7 @@ const Spinner = struct {
};
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
const this: *@This() = @ptrCast(@alignCast(ctx));
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -83,7 +83,7 @@ const InputField = struct {
};
}
fn handle(ctx: *anyopaque, event: App.Event) !void {
fn handle(ctx: *anyopaque, _: *App.Model, event: App.Event) !void {
const this: *@This() = @ptrCast(@alignCast(ctx));
switch (event) {
.key => |key| {
@@ -102,7 +102,7 @@ const InputField = struct {
}
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
const this: *@This() = @ptrCast(@alignCast(ctx));
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -133,7 +133,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -214,7 +214,7 @@ pub fn main() !void {
else => {},
}
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -230,7 +230,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -242,6 +242,6 @@ const std = @import("std");
const time = std.time;
const assert = std.debug.assert;
const zterm = @import("zterm");
const App = zterm.App(union(enum) {
const App = zterm.App(struct {}, union(enum) {
accept: []u21,
});

View File

@@ -5,7 +5,7 @@ const QuitText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
pub fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
pub fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -33,7 +33,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -168,7 +168,7 @@ pub fn main() !void {
}
// NOTE returned errors should be propagated back to the application
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -183,7 +183,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -195,4 +195,4 @@ const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const input = zterm.input;
const App = zterm.App(union(enum) {});
const App = zterm.App(struct {}, union(enum) {});

View File

@@ -5,7 +5,7 @@ const QuitText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -32,7 +32,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -70,7 +70,7 @@ pub fn main() !void {
else => {},
}
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -85,7 +85,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -96,4 +96,4 @@ const log = std.log.scoped(.default);
const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const App = zterm.App(union(enum) {});
const App = zterm.App(struct {}, union(enum) {});

View File

@@ -5,7 +5,7 @@ const QuitText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -40,7 +40,7 @@ const Clickable = struct {
};
}
fn handle(ctx: *anyopaque, event: App.Event) !void {
fn handle(ctx: *anyopaque, _: *App.Model, event: App.Event) !void {
const this: *@This() = @ptrCast(@alignCast(ctx));
switch (event) {
.mouse => |mouse| if (mouse.button == .left and mouse.kind == .release) {
@@ -55,7 +55,7 @@ const Clickable = struct {
}
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
const this: *@This() = @ptrCast(@alignCast(ctx));
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -82,7 +82,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -119,7 +119,7 @@ pub fn main() !void {
else => {},
}
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -134,7 +134,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -145,7 +145,10 @@ const log = std.log.scoped(.default);
const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const App = zterm.App(union(enum) {
click: [:0]const u8,
accept,
});
const App = zterm.App(
struct {},
union(enum) {
click: [:0]const u8,
accept,
},
);

View File

@@ -5,7 +5,7 @@ const QuitText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -37,7 +37,7 @@ const MouseDraw = struct {
};
}
fn handle(ctx: *anyopaque, event: App.Event) !void {
fn handle(ctx: *anyopaque, _: *App.Model, event: App.Event) !void {
const this: *@This() = @ptrCast(@alignCast(ctx));
switch (event) {
.mouse => |mouse| this.position = .{ .x = mouse.x, .y = mouse.y },
@@ -45,7 +45,7 @@ const MouseDraw = struct {
}
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
const this: *@This() = @ptrCast(@alignCast(ctx));
@@ -65,7 +65,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -133,7 +133,7 @@ pub fn main() !void {
else => {},
}
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -148,7 +148,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -161,6 +161,9 @@ const assert = std.debug.assert;
const zterm = @import("zterm");
const Color = zterm.Color;
const App = zterm.App(union(enum) {
accept: []u8,
});
const App = zterm.App(
struct {},
union(enum) {
accept: []u8,
},
);

View File

@@ -5,7 +5,7 @@ const QuitText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -32,7 +32,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -138,7 +138,7 @@ pub fn main() !void {
else => {},
}
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -154,7 +154,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -166,6 +166,9 @@ const std = @import("std");
const time = std.time;
const assert = std.debug.assert;
const zterm = @import("zterm");
const App = zterm.App(union(enum) {
progress: u8,
});
const App = zterm.App(
struct {},
union(enum) {
progress: u8,
},
);

View File

@@ -5,7 +5,7 @@ const QuitText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -32,7 +32,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -67,7 +67,7 @@ pub fn main() !void {
else => {},
}
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -82,7 +82,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -93,6 +93,6 @@ const log = std.log.scoped(.default);
const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const App = zterm.App(union(enum) {
const App = zterm.App(struct {}, union(enum) {
accept,
});

View File

@@ -5,7 +5,7 @@ const QuitText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -34,7 +34,7 @@ const HelloWorldText = packed struct {
};
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -66,7 +66,7 @@ pub fn main() !void {
}
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -169,7 +169,7 @@ pub fn main() !void {
else => {},
}
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -184,7 +184,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -196,4 +196,4 @@ const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const input = zterm.input;
const App = zterm.App(union(enum) {});
const App = zterm.App(struct {}, union(enum) {});

View File

@@ -5,7 +5,7 @@ const QuitText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -32,7 +32,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -67,7 +67,7 @@ pub fn main() !void {
else => {},
}
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -82,7 +82,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -94,4 +94,4 @@ const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const Error = zterm.Error;
const App = zterm.App(union(enum) {});
const App = zterm.App(struct {}, union(enum) {});

View File

@@ -5,7 +5,7 @@ const QuitText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -31,7 +31,7 @@ const InfoText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -57,7 +57,7 @@ const ErrorNotification = struct {
return .{ .ptr = this, .vtable = &.{ .handle = handle, .content = content } };
}
fn handle(ctx: *anyopaque, event: App.Event) !void {
fn handle(ctx: *anyopaque, _: *App.Model, event: App.Event) !void {
const this: *@This() = @ptrCast(@alignCast(ctx));
switch (event) {
.key => |key| if (!key.isAscii()) return zterm.Error.TooSmall,
@@ -66,7 +66,7 @@ const ErrorNotification = struct {
}
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
const this: *@This() = @ptrCast(@alignCast(ctx));
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -97,7 +97,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -130,7 +130,7 @@ pub fn main() !void {
else => {},
}
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -145,7 +145,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -156,4 +156,4 @@ const log = std.log.scoped(.default);
const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const App = zterm.App(union(enum) {});
const App = zterm.App(struct {}, union(enum) {});

View File

@@ -8,7 +8,7 @@ const QuitText = struct {
};
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -35,7 +35,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -86,7 +86,7 @@ pub fn main() !void {
}
// NOTE returned errors should be propagated back to the application
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -101,7 +101,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -112,4 +112,4 @@ const log = std.log.scoped(.default);
const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const App = zterm.App(union(enum) {});
const App = zterm.App(struct {}, union(enum) {});

View File

@@ -8,7 +8,7 @@ const QuitText = struct {
};
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -35,7 +35,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -78,7 +78,7 @@ pub fn main() !void {
}
// NOTE returned errors should be propagated back to the application
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -93,7 +93,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -104,4 +104,4 @@ const log = std.log.scoped(.default);
const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const App = zterm.App(union(enum) {});
const App = zterm.App(struct {}, union(enum) {});

View File

@@ -8,7 +8,7 @@ const QuitText = struct {
};
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -35,7 +35,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -94,7 +94,7 @@ pub fn main() !void {
}
// NOTE returned errors should be propagated back to the application
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -109,7 +109,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -120,4 +120,4 @@ const log = std.log.scoped(.default);
const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const App = zterm.App(union(enum) {});
const App = zterm.App(struct {}, union(enum) {});

View File

@@ -8,7 +8,7 @@ const QuitText = struct {
};
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -35,7 +35,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -77,7 +77,7 @@ pub fn main() !void {
}
// NOTE returned errors should be propagated back to the application
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -92,7 +92,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -103,4 +103,4 @@ const log = std.log.scoped(.default);
const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const App = zterm.App(union(enum) {});
const App = zterm.App(struct {}, union(enum) {});

View File

@@ -5,7 +5,7 @@ const QuitText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -32,7 +32,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -73,7 +73,7 @@ pub fn main() !void {
else => {},
}
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -88,7 +88,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -99,4 +99,4 @@ const log = std.log.scoped(.default);
const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const App = zterm.App(union(enum) {});
const App = zterm.App(struct {}, union(enum) {});

View File

@@ -5,7 +5,7 @@ const QuitText = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -31,7 +31,7 @@ const TextStyles = struct {
return .{ .ptr = this, .vtable = &.{ .content = content } };
}
fn content(ctx: *anyopaque, cells: []zterm.Cell, size: zterm.Point) !void {
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
@setEvalBranchQuota(10000);
_ = ctx;
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
@@ -83,7 +83,7 @@ pub fn main() !void {
const allocator = gpa.allocator();
var app: App = .init;
var app: App = .init(.{});
var renderer = zterm.Renderer.Buffered.init(allocator);
defer renderer.deinit();
@@ -128,7 +128,7 @@ pub fn main() !void {
else => {},
}
container.handle(event) catch |err| app.postEvent(.{
container.handle(&app.model, event) catch |err| app.postEvent(.{
.err = .{
.err = err,
.msg = "Container Event handling failed",
@@ -143,7 +143,7 @@ pub fn main() !void {
container.resize(try renderer.resize());
container.reposition(.{});
try renderer.render(@TypeOf(container), &container);
try renderer.render(@TypeOf(container), &container, App.Model, &app.model);
try renderer.flush();
}
}
@@ -154,4 +154,5 @@ const log = std.log.scoped(.default);
const std = @import("std");
const assert = std.debug.assert;
const zterm = @import("zterm");
const App = zterm.App(union(enum) {});
const App = zterm.App(struct {}, union(enum) {});