feat: change event system
this fixes a common use-after-free footgun and removes the need for a global allocator
This commit is contained in:
parent
97be1d863a
commit
a62e77483b
|
@ -22,7 +22,9 @@ pub fn init() void {
|
|||
// do initialization stuff
|
||||
}
|
||||
|
||||
pub fn update(ev: zz.Event) void {
|
||||
pub fn update() void {
|
||||
var event = zz.getEvent(my_allocator) catch return;
|
||||
defer event.deinit();
|
||||
// handle events
|
||||
}
|
||||
|
||||
|
|
|
@ -16,10 +16,6 @@ var mode: ?zz.types.InputMode = null;
|
|||
|
||||
// called on startup
|
||||
pub fn init() void {
|
||||
// set zellzig's allocator
|
||||
// This is required to receive events.
|
||||
zz.allocator = gpa.allocator();
|
||||
|
||||
// This is required to make zellij close once everything but our plugin is gone.
|
||||
zz.api.setSelectable(false);
|
||||
|
||||
|
@ -28,8 +24,11 @@ pub fn init() void {
|
|||
}
|
||||
|
||||
// called on every event
|
||||
pub fn update(ev: zz.Event) void {
|
||||
switch (ev) {
|
||||
pub fn update() void {
|
||||
var ev = zz.getEvent(gpa.allocator()) catch return;
|
||||
defer ev.deinit();
|
||||
|
||||
switch (ev.data) {
|
||||
.ModeUpdate => |mode_info| mode = mode_info.mode,
|
||||
else => {},
|
||||
}
|
||||
|
|
16
src/api.zig
16
src/api.zig
|
@ -15,17 +15,17 @@ pub fn sendObj(data: anytype) !void {
|
|||
}
|
||||
|
||||
/// Receives a JSON object from zellij
|
||||
pub fn recvObj(comptime T: type) !zz.OwnedDeserData(T) {
|
||||
pub fn recvObj(comptime T: type, alloc: std.mem.Allocator) !zz.OwnedDeserData(T) {
|
||||
var stdin = std.io.getStdIn();
|
||||
|
||||
const data = (try stdin.reader().readUntilDelimiterOrEofAlloc(
|
||||
zz.allocator.?,
|
||||
alloc,
|
||||
'\n',
|
||||
std.math.maxInt(usize),
|
||||
)) orelse unreachable;
|
||||
defer zz.allocator.?.free(data);
|
||||
defer alloc.free(data);
|
||||
|
||||
return zz.OwnedDeserData(T).deserialize(zz.allocator.?, data);
|
||||
return zz.OwnedDeserData(T).deserialize(alloc, data);
|
||||
}
|
||||
|
||||
/// Subscribes to the given events.
|
||||
|
@ -49,15 +49,15 @@ pub fn setSelectable(selectable: bool) void {
|
|||
}
|
||||
|
||||
/// Returns the ID of this plugin, and zellij's PID.
|
||||
pub fn getPluginIds() !zz.OwnedDeserData(types.PluginIds) {
|
||||
pub fn getPluginIds(alloc: std.mem.Allocator) !zz.OwnedDeserData(types.PluginIds) {
|
||||
zapi.host_get_plugin_ids();
|
||||
return try recvObj(types.PluginIds);
|
||||
return try recvObj(types.PluginIds, alloc);
|
||||
}
|
||||
|
||||
/// Returns zellij's version string.
|
||||
pub fn getZellijVersion() !zz.OwnedDeserData([]const u8) {
|
||||
pub fn getZellijVersion(alloc: std.mem.Allocator) !zz.OwnedDeserData([]const u8) {
|
||||
zapi.host_get_zellij_version();
|
||||
return try recvObj([]const u8);
|
||||
return try recvObj([]const u8, alloc);
|
||||
}
|
||||
|
||||
pub fn openFile(path: []const u8) !void {
|
||||
|
|
30
src/main.zig
30
src/main.zig
|
@ -19,22 +19,26 @@ test {
|
|||
/// ```zig
|
||||
/// // main.zig
|
||||
/// const zz = @import("zellzig");
|
||||
///
|
||||
/// const gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
///
|
||||
/// comptime {
|
||||
/// zz.createPlugin(@This());
|
||||
/// }
|
||||
///
|
||||
/// pub fn init() void {
|
||||
/// const alloc = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
/// zz.allocator = alloc.allocator();
|
||||
/// pub fn init() void {}
|
||||
/// pub fn update(event: zz.Event) void {
|
||||
/// var event = zz.getEvent(gpa.allocator()) catch return;
|
||||
/// defer event.deinit();
|
||||
/// // use event
|
||||
/// }
|
||||
/// pub fn update(event: zz.Event) void {}
|
||||
/// pub fn render(rows: i32, cols: i32) void {}
|
||||
/// ```
|
||||
pub fn createPlugin(comptime Plugin: type) void {
|
||||
if (@TypeOf(Plugin.init) != fn () void)
|
||||
@compileError("Function 'init' has invalid signature!");
|
||||
|
||||
if (@TypeOf(Plugin.update) != fn (Event) void)
|
||||
if (@TypeOf(Plugin.update) != fn () void)
|
||||
@compileError("Function 'update' has invalid signature!");
|
||||
|
||||
if (@TypeOf(Plugin.render) != fn (i32, i32) void)
|
||||
|
@ -50,17 +54,11 @@ pub fn createPlugin(comptime Plugin: type) void {
|
|||
}
|
||||
|
||||
export fn update() void {
|
||||
if (allocator == null) {
|
||||
@panic("Got event while allocator is null! Did you forget to set it?");
|
||||
}
|
||||
|
||||
var ev = api.recvObj(types.Event) catch |err| {
|
||||
std.log.err("Deserialize error: {}", .{err});
|
||||
return;
|
||||
};
|
||||
defer ev.deinit();
|
||||
|
||||
Plugin.update(ev.data);
|
||||
Plugin.update();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getEvent(alloc: std.mem.Allocator) !OwnedDeserData(types.Event) {
|
||||
return try api.recvObj(types.Event, alloc);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue