diff --git a/examples/continuous.zig b/examples/continuous.zig index b08cc7d..2b73b46 100644 --- a/examples/continuous.zig +++ b/examples/continuous.zig @@ -133,7 +133,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/demo.zig b/examples/demo.zig index 74c57d2..a75c044 100644 --- a/examples/demo.zig +++ b/examples/demo.zig @@ -31,7 +31,7 @@ pub fn main() !void { defer if (gpa.deinit() == .leak) log.err("memory leak", .{}); const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); @@ -153,7 +153,7 @@ pub fn main() !void { renderer.size = .{}; // reset size, such that next resize will cause a full re-draw! defer app.start() catch @panic("could not start app event loop"); var child = std.process.Child.init(&.{"hx"}, allocator); - _ = child.spawnAndWait() catch |err| app.postEvent(.{ + _ = child.spawnAndWait(threaded_io.io()) catch |err| app.postEvent(.{ .err = .{ .err = err, .msg = "Spawning $EDITOR failed", diff --git a/examples/elements/alignment.zig b/examples/elements/alignment.zig index 9238cfe..5952c58 100644 --- a/examples/elements/alignment.zig +++ b/examples/elements/alignment.zig @@ -32,7 +32,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/elements/button.zig b/examples/elements/button.zig index 31ad4b4..0952362 100644 --- a/examples/elements/button.zig +++ b/examples/elements/button.zig @@ -82,7 +82,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/elements/input.zig b/examples/elements/input.zig index b03e70d..4455267 100644 --- a/examples/elements/input.zig +++ b/examples/elements/input.zig @@ -65,7 +65,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/elements/progress.zig b/examples/elements/progress.zig index 4b63a7f..62f2f00 100644 --- a/examples/elements/progress.zig +++ b/examples/elements/progress.zig @@ -32,7 +32,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/elements/radio-button.zig b/examples/elements/radio-button.zig index c4264c6..ff6e0c4 100644 --- a/examples/elements/radio-button.zig +++ b/examples/elements/radio-button.zig @@ -32,7 +32,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/elements/scrollable.zig b/examples/elements/scrollable.zig index 8821c84..017e4ae 100644 --- a/examples/elements/scrollable.zig +++ b/examples/elements/scrollable.zig @@ -65,7 +65,7 @@ pub fn main() !void { } const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/elements/selection.zig b/examples/elements/selection.zig index 8d68e2f..2f8ec04 100644 --- a/examples/elements/selection.zig +++ b/examples/elements/selection.zig @@ -32,7 +32,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/errors.zig b/examples/errors.zig index e557d5c..5bbba88 100644 --- a/examples/errors.zig +++ b/examples/errors.zig @@ -97,7 +97,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/layouts/grid.zig b/examples/layouts/grid.zig index c85383f..9998b2b 100644 --- a/examples/layouts/grid.zig +++ b/examples/layouts/grid.zig @@ -35,7 +35,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/layouts/horizontal.zig b/examples/layouts/horizontal.zig index 70db90c..e9f7d3e 100644 --- a/examples/layouts/horizontal.zig +++ b/examples/layouts/horizontal.zig @@ -35,7 +35,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/layouts/mixed.zig b/examples/layouts/mixed.zig index a29da15..957f1db 100644 --- a/examples/layouts/mixed.zig +++ b/examples/layouts/mixed.zig @@ -35,7 +35,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/layouts/vertical.zig b/examples/layouts/vertical.zig index dddc618..928a3f9 100644 --- a/examples/layouts/vertical.zig +++ b/examples/layouts/vertical.zig @@ -35,7 +35,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/styles/palette.zig b/examples/styles/palette.zig index 35178e2..38d4a47 100644 --- a/examples/styles/palette.zig +++ b/examples/styles/palette.zig @@ -32,7 +32,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/examples/styles/text.zig b/examples/styles/text.zig index 135d6e1..06cbb50 100644 --- a/examples/styles/text.zig +++ b/examples/styles/text.zig @@ -178,7 +178,7 @@ pub fn main() !void { const allocator = gpa.allocator(); - var threaded_io: std.Io.Threaded = .init(allocator); + var threaded_io: std.Io.Threaded = .init(allocator, .{}); defer threaded_io.deinit(); var app: App = .init(threaded_io.ioBasic(), .{}); diff --git a/src/app.zig b/src/app.zig index eede524..733c371 100644 --- a/src/app.zig +++ b/src/app.zig @@ -146,7 +146,7 @@ pub fn App(comptime M: type, comptime E: type) type { }; } while (true) { - if (this.io.cancelRequested()) break; + this.io.checkCancel() catch break; // non-blocking read const read_bytes = terminal.read(&buf) catch |err| switch (err) { diff --git a/src/element.zig b/src/element.zig index e02ddee..932e822 100644 --- a/src/element.zig +++ b/src/element.zig @@ -5,6 +5,7 @@ // -> currently you need to swap out the entire `Container` accordingly before rendering // -> this might be necessary for size depending layout options, etc. // -> maybe this can be implemented / supported similarly as to how the scrollable `Element`'s are implemented +// - `Form` using a struct that contains the fields that shall be generated for the user to submit (similar to `Input` it shall be build on-top of smaller pieces that are designed to be used in `Element` implementations) // FIX known issues: // - hold fewer instances of the `Allocator` diff --git a/src/event.zig b/src/event.zig index 8410398..8991f9f 100644 --- a/src/event.zig +++ b/src/event.zig @@ -46,21 +46,44 @@ pub fn mergeTaggedUnions(comptime A: type, comptime B: type) type { const b_fields = @typeInfo(B).@"union".fields; const b_fields_tag = @typeInfo(B).@"union".tag_type.?; const b_enum_fields = @typeInfo(b_fields_tag).@"enum".fields; - var fields: [a_fields.len + b_fields.len]std.builtin.Type.UnionField = undefined; - var enum_fields: [a_fields.len + b_fields.len]std.builtin.Type.EnumField = undefined; + var field_names: [a_fields.len + b_fields.len][:0]const u8 = undefined; + var field_types: [a_fields.len + b_fields.len]type = undefined; + var field_attributes: [a_fields.len + b_fields.len]std.builtin.Type.UnionField.Attributes = undefined; + var enum_names: [a_fields.len + b_fields.len][:0]const u8 = undefined; + const UEnumSize = blk: { + const total_size = a_fields.len + b_fields.len; + break :blk switch (total_size) { + 1...2 => u1, + 3...4 => u2, + 5...8 => u4, + 9...16 => u4, + 17...32 => u5, + 33...64 => u6, + 65...128 => u7, + 129...256 => u8, + else => u16, // should suffice + }; + }; + var enum_values: [a_fields.len + b_fields.len]UEnumSize = undefined; var i: usize = 0; for (a_fields, a_enum_fields) |field, enum_field| { - fields[i] = field; + field_names[i] = field.name; + field_types[i] = field.type; + field_attributes[i] = .{ .@"align" = field.alignment }; var enum_f = enum_field; enum_f.value = i; - enum_fields[i] = enum_f; + enum_names[i] = enum_f.name; + enum_values[i] = enum_f.value; i += 1; } for (b_fields, b_enum_fields) |field, enum_field| { - fields[i] = field; + field_names[i] = field.name; + field_types[i] = field.type; + field_attributes[i] = .{ .@"align" = field.alignment }; var enum_f = enum_field; enum_f.value = i; - enum_fields[i] = enum_f; + enum_names[i] = enum_f.name; + enum_values[i] = enum_f.value; i += 1; } @@ -71,35 +94,22 @@ pub fn mergeTaggedUnions(comptime A: type, comptime B: type) type { // user provided one) const a_enum_decls = @typeInfo(A).@"union".decls; const b_enum_decls = @typeInfo(B).@"union".decls; - var decls: [a_enum_decls.len + b_enum_decls.len]std.builtin.Type.Declaration = undefined; + var decl_names: [a_enum_decls.len + b_enum_decls.len]std.builtin.Type.Declaration = undefined; var j: usize = 0; for (a_enum_decls) |decl| { - decls[j] = decl; + decl_names[j] = decl.name; j += 1; } for (b_enum_decls) |decl| { - decls[j] = decl; + decl_names[j] = decl.name; j += 1; } - const EventType = @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = @bitSizeOf(@TypeOf(i)) - @clz(i), - } }); + const EventType = @Int(.unsigned, @bitSizeOf(@TypeOf(i)) - @clz(i)); - const Event = @Type(.{ .@"enum" = .{ - .tag_type = EventType, - .fields = enum_fields[0..], - .decls = &.{}, - .is_exhaustive = true, - } }); + const Event = @Enum(EventType, .exhaustive, enum_names[0..], enum_values[0..]); - return @Type(.{ .@"union" = .{ - .layout = .auto, - .tag_type = Event, - .fields = fields[0..], - .decls = &.{}, - } }); + return @Union(.auto, Event, field_names[0..], field_types[0..], field_attributes[0..]); } /// Determine whether the provided type `T` is a tagged union: `union(enum)`. diff --git a/src/testing.zig b/src/testing.zig index df656eb..1fd96b8 100644 --- a/src/testing.zig +++ b/src/testing.zig @@ -211,14 +211,13 @@ pub fn expectEqualCells(origin: Point, size: Point, expected: []const Cell, actu if (!differ) return; // test failed - debug.lockStdErr(); - defer debug.unlockStdErr(); - var stdout_buffer: [1024]u8 = undefined; - var stdout = std.fs.File.stdout().writer(&stdout_buffer); - const stdout_writer = &stdout.interface; - try stdout_writer.writeAll(writer.buffer[0..writer.end]); - try stdout_writer.flush(); + const io = debug.lockStderr(&stdout_buffer); + defer debug.unlockStderr(); + + const error_writer = &io.file_writer.interface; + try error_writer.writeAll(writer.buffer[0..writer.end]); + try error_writer.flush(); return error.TestExpectEqualCells; }