add(zig-interface): dependency to check interface contracts at comptime
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 53s

The described interfaces for `Widget` and `Layout` are now defined and
correspondingly checked at comptime.
This commit is contained in:
2024-11-12 23:13:35 +01:00
parent 07e4819ecd
commit 28817d468a
8 changed files with 80 additions and 46 deletions

View File

@@ -12,14 +12,13 @@ const Style = terminal.Cell.Style;
const log = std.log.scoped(.layout_framing);
pub fn Layout(comptime Event: type, comptime Renderer: type) type {
pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: type) type {
if (!isTaggedUnion(Event)) {
@compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`.");
@compileError("Provided user event `Event` for `Layout(comptime Event: type, comptime Element: type, comptime Renderer: type)` is not of type `union(enum)`.");
}
if (!isTaggedUnion(Element)) {
@compileError("Provided type `Element` for `Layout(comptime Event: type, comptime Element: type, comptime Renderer: type)` is not of type `union(enum)`.");
}
const Element = union(enum) {
layout: @import("../layout.zig").Layout(Event, Renderer),
widget: @import("../widget.zig").Widget(Event, Renderer),
};
const Events = std.ArrayList(Event);
return struct {
size: terminal.Size = undefined,

View File

@@ -11,17 +11,17 @@ const Key = terminal.Key;
const log = std.log.scoped(.layout_hstack);
pub fn Layout(comptime Event: type, comptime Renderer: type) type {
pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: type) type {
if (!isTaggedUnion(Event)) {
@compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`.");
@compileError("Provided user event `Event` for `Layout(comptime Event: type, comptime Element: type, comptime Renderer: type)` is not of type `union(enum)`.");
}
if (!isTaggedUnion(Element)) {
@compileError("Provided type `Element` for `Layout(comptime Event: type, comptime Element: type, comptime Renderer: type)` is not of type `union(enum)`.");
}
const Widget = @import("../widget.zig").Widget(Event, Renderer);
const Lay = @import("../layout.zig").Layout(Event, Renderer);
const Element = union(enum) {
layout: Lay,
widget: Widget,
};
const Elements = std.ArrayList(Element);
// TODO: expect name of field to be corresponding to the type
const LayoutType = @typeInfo(Element).Union.fields[0].type;
const WidgetType = @typeInfo(Element).Union.fields[1].type;
const Events = std.ArrayList(Event);
return struct {
// TODO: current focused `Element`?
@@ -40,15 +40,15 @@ pub fn Layout(comptime Event: type, comptime Renderer: type) type {
inline for (comptime fields_info) |field| {
const child = @field(children, field.name);
const ChildType = @TypeOf(child);
if (ChildType == Widget) {
if (ChildType == WidgetType) {
elements.append(.{ .widget = child }) catch {};
continue;
}
if (ChildType == Lay) {
if (ChildType == LayoutType) {
elements.append(.{ .layout = child }) catch {};
continue;
}
@compileError("child: " ++ field.name ++ " is not of type " ++ @typeName(Lay) ++ " or " ++ @typeName(Widget) ++ " but " ++ @typeName(ChildType));
@compileError("child: " ++ field.name ++ " is not of type " ++ @typeName(WidgetType) ++ " or " ++ @typeName(LayoutType) ++ " but " ++ @typeName(ChildType));
}
return .{
.elements = elements,

View File

@@ -11,14 +11,13 @@ const Key = terminal.Key;
const log = std.log.scoped(.layout_padding);
pub fn Layout(comptime Event: type, comptime Renderer: type) type {
pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: type) type {
if (!isTaggedUnion(Event)) {
@compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`.");
@compileError("Provided user event `Event` for `Layout(comptime Event: type, comptime Element: type, comptime Renderer: type)` is not of type `union(enum)`.");
}
if (!isTaggedUnion(Element)) {
@compileError("Provided type `Element` for `Layout(comptime Event: type, comptime Element: type, comptime Renderer: type)` is not of type `union(enum)`.");
}
const Element = union(enum) {
layout: @import("../layout.zig").Layout(Event, Renderer),
widget: @import("../widget.zig").Widget(Event, Renderer),
};
const Events = std.ArrayList(Event);
return struct {
size: terminal.Size = undefined,

View File

@@ -11,17 +11,17 @@ const Key = terminal.Key;
const log = std.log.scoped(.layout_vstack);
pub fn Layout(comptime Event: type, comptime Renderer: type) type {
pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: type) type {
if (!isTaggedUnion(Event)) {
@compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`.");
@compileError("Provided user event `Event` for `Layout(comptime Event: type, comptime Element: type, comptime Renderer: type)` is not of type `union(enum)`.");
}
if (!isTaggedUnion(Element)) {
@compileError("Provided type `Element` for `Layout(comptime Event: type, comptime Element: type, comptime Renderer: type)` is not of type `union(enum)`.");
}
const Widget = @import("../widget.zig").Widget(Event, Renderer);
const Lay = @import("../layout.zig").Layout(Event, Renderer);
const Element = union(enum) {
layout: Lay,
widget: Widget,
};
const Elements = std.ArrayList(Element);
// TODO: expect name of field to be corresponding to the type
const LayoutType = @typeInfo(Element).Union.fields[0].type;
const WidgetType = @typeInfo(Element).Union.fields[1].type;
const Events = std.ArrayList(Event);
return struct {
// TODO: current focused `Element`?
@@ -40,15 +40,15 @@ pub fn Layout(comptime Event: type, comptime Renderer: type) type {
inline for (comptime fields_info) |field| {
const child = @field(children, field.name);
const ChildType = @TypeOf(child);
if (ChildType == Widget) {
if (ChildType == WidgetType) {
elements.append(.{ .widget = child }) catch {};
continue;
}
if (ChildType == Lay) {
if (ChildType == LayoutType) {
elements.append(.{ .layout = child }) catch {};
continue;
}
@compileError("child: " ++ field.name ++ " is not of type " ++ @typeName(Lay) ++ " or " ++ @typeName(Widget) ++ " but " ++ @typeName(ChildType));
@compileError("child: " ++ field.name ++ " is not of type " ++ @typeName(WidgetType) ++ " or " ++ @typeName(LayoutType) ++ " but " ++ @typeName(ChildType));
}
return .{
.elements = elements,