feat: added error context and upgraded zellij API

This commit is contained in:
LordMZTE 2022-12-26 21:25:40 +01:00
parent 6c3fcb8594
commit 6d05abc4d4
Signed by: LordMZTE
GPG key ID: B64802DC33A64FF6
5 changed files with 77 additions and 16 deletions

25
src/DeserErrorCtx.zig Normal file
View file

@ -0,0 +1,25 @@
//! A type containing some information about an error that occured
//! while deserializing a message from Zelilj.
const std = @import("std");
pos: usize,
/// A string of the json source starting at pos - 16 and ending at pos + 16
sample: []const u8,
/// The allocator that was used to create this object.
alloc: std.mem.Allocator,
const Self = @This();
pub fn init(alloc: std.mem.Allocator, pos: usize, data: []const u8) !Self {
return .{
.pos = pos,
.sample = try alloc.dupe(u8, data[pos -| 16..pos + 16]),
.alloc = alloc,
};
}
pub fn deinit(self: Self) void {
self.alloc.free(self.sample);
}

View file

@ -7,6 +7,8 @@ const json = @import("json");
const zapi = @import("zellij_api.zig");
const types = @import("types.zig");
const DeserErrorCtx = @import("DeserErrorCtx.zig");
/// Sends an object as JSON to zellij
pub fn sendObj(data: anytype) !void {
var stdout = std.io.getStdOut();
@ -15,7 +17,7 @@ pub fn sendObj(data: anytype) !void {
}
/// Receives a JSON object from zellij
pub fn recvObj(comptime T: type, alloc: std.mem.Allocator) !zz.OwnedDeserData(T) {
pub fn recvObj(comptime T: type, alloc: std.mem.Allocator, err_ctx: ?*?DeserErrorCtx) !zz.OwnedDeserData(T) {
var stdin = std.io.getStdIn();
const data = (try stdin.reader().readUntilDelimiterOrEofAlloc(
@ -25,7 +27,7 @@ pub fn recvObj(comptime T: type, alloc: std.mem.Allocator) !zz.OwnedDeserData(T)
)) orelse unreachable;
defer alloc.free(data);
return zz.OwnedDeserData(T).deserialize(alloc, data);
return zz.OwnedDeserData(T).deserialize(alloc, err_ctx, data);
}
/// Subscribes to the given events.

View file

@ -20,6 +20,11 @@ const Vis = struct {
const column = (try input.nextElement(alloc, usize)) orelse
return error.InvalidLength;
// Getty needs a final nextElement call
if (try input.nextElement(alloc, getty.de.Ignored)) |_| {
return error.InvalidLength;
}
return types.LineAndColumn{
.line = line,
.column = column,

View file

@ -1,8 +1,10 @@
const std = @import("std");
pub const api = @import("api.zig");
pub const types = @import("types.zig");
pub const DeserErrorCtx = @import("DeserErrorCtx.zig");
pub const Event = types.Event;
pub const OwnedDeserData = types.OwnedDeserData;
pub const api = @import("api.zig");
/// This is the allocator that will be used by zellzig for communication.
/// This must be set before events can be received.
@ -69,6 +71,6 @@ pub fn createPlugin(comptime Plugin: type) void {
};
}
pub fn getEvent(alloc: std.mem.Allocator) !OwnedDeserData(types.Event) {
return try api.recvObj(types.Event, alloc);
pub fn getEvent(alloc: std.mem.Allocator, err_ctx: ?*?DeserErrorCtx) !OwnedDeserData(types.Event) {
return try api.recvObj(types.Event, alloc, err_ctx);
}

View file

@ -2,6 +2,8 @@ const std = @import("std");
const getty = @import("getty");
const json = @import("json");
const DeserErrorCtx = @import("DeserErrorCtx.zig");
/// getty deserialization blocks required to properly deserialize messages
pub const dbs = .{
@import("deserialization_blocks/bytearray.zig"),
@ -23,14 +25,19 @@ pub fn OwnedDeserData(comptime T: type) type {
const Self = @This();
pub fn deserialize(alloc: std.mem.Allocator, data: []const u8) !Self {
pub fn deserialize(alloc: std.mem.Allocator, err_ctx: ?*?DeserErrorCtx, data: []const u8) !Self {
@setEvalBranchQuota(10000);
var arena = std.heap.ArenaAllocator.init(alloc);
errdefer arena.deinit();
const arena_alloc = arena.allocator();
var deser = json.Deserializer(dbs).withAllocator(arena_alloc, data);
const deser_data = try getty.deserialize(arena_alloc, T, deser.deserializer());
const deser_data = getty.deserialize(arena_alloc, T, deser.deserializer()) catch |e| {
if (err_ctx) |ctx| {
ctx.* = try DeserErrorCtx.init(alloc, deser.tokens.i, data);
}
return e;
};
return Self{
.data = deser_data,
@ -55,7 +62,7 @@ test "deserialize Char" {
\\"x"
;
var deser = try OwnedDeserData(Char).deserialize(std.testing.allocator, json_src);
var deser = try OwnedDeserData(Char).deserialize(std.testing.allocator, null, json_src);
defer deser.deinit();
}
@ -77,7 +84,7 @@ test "deserialize Bytearray" {
;
var valid_deser = try OwnedDeserData(Bytearray)
.deserialize(std.testing.allocator, valid_json_src);
.deserialize(std.testing.allocator, null, valid_json_src);
defer valid_deser.deinit();
const invalid_json_src =
@ -86,7 +93,7 @@ test "deserialize Bytearray" {
try std.testing.expectError(
error.InvalidType,
OwnedDeserData(Bytearray).deserialize(std.testing.allocator, invalid_json_src),
OwnedDeserData(Bytearray).deserialize(std.testing.allocator, null, invalid_json_src),
);
}
@ -190,7 +197,7 @@ test "deserialize Event" {
\\}
;
var deser = try OwnedDeserData(Event).deserialize(std.testing.allocator, json_src);
var deser = try OwnedDeserData(Event).deserialize(std.testing.allocator, null, json_src);
defer deser.deinit();
}
@ -208,7 +215,10 @@ test "deserialize KeybindSet" {
\\ },
\\ [
\\ {
\\ "Resize": "Increase"
\\ "Resize": [
\\ "Increase",
\\ null
\\ ]
\\ }
\\ ]
\\ ]
@ -216,7 +226,7 @@ test "deserialize KeybindSet" {
\\]
;
var deser = try OwnedDeserData(KeybindSet).deserialize(std.testing.allocator, json_src);
var deser = try OwnedDeserData(KeybindSet).deserialize(std.testing.allocator, null, json_src);
defer deser.deinit();
}
@ -335,7 +345,7 @@ test "deserialize Palette" {
\\ }
;
var deser = try OwnedDeserData(Palette).deserialize(std.testing.allocator, json_src);
var deser = try OwnedDeserData(Palette).deserialize(std.testing.allocator, null, json_src);
defer deser.deinit();
}
@ -403,7 +413,7 @@ test "deserialize Key" {
\\]
;
var deser = try OwnedDeserData([]Key).deserialize(std.testing.allocator, json_src);
var deser = try OwnedDeserData([]Key).deserialize(std.testing.allocator, null, json_src);
defer deser.deinit();
}
@ -415,12 +425,14 @@ pub const CharOrArrow = union(enum) {
test "deserialize CharOrArrow" {
var data_1 = try OwnedDeserData(CharOrArrow).deserialize(
std.testing.allocator,
null,
"\"A\"",
);
defer data_1.deinit();
var data_2 = try OwnedDeserData(CharOrArrow).deserialize(
std.testing.allocator,
null,
"\"Left\"",
);
defer data_2.deinit();
@ -553,9 +565,24 @@ pub const Resize = enum {
Decrease,
};
pub const PercentOrFixed = union(enum) {
Percent: usize,
Fixed: usize,
};
pub const FloatingPanesLayout = struct {
name: ?[]u8,
height: ?PercentOrFixed,
width: ?PercentOrFixed,
x: ?PercentOrFixed,
y: ?PercentOrFixed,
run: ?Run,
focus: ?bool,
};
pub const EditFileInfo = std.meta.Tuple(&.{ []u8, ?usize, ?Direction, bool });
pub const NewTiledPaneInfo = std.meta.Tuple(&.{ ?Direction, ?RunCommandAction, ?[]u8 });
pub const NewTabInfo = std.meta.Tuple(&.{ ?PaneLayout, ?[]u8 });
pub const NewTabInfo = std.meta.Tuple(&.{ ?PaneLayout, []FloatingPanesLayout, ?[]u8 });
pub const NewPaneInfo = std.meta.Tuple(&.{ ?Direction, ?[]u8 });
pub const NewFloatingPaneInfo = std.meta.Tuple(&.{ ?RunCommandAction, ?[]u8 });
pub const ResizeInfo = std.meta.Tuple(&.{ Resize, ?Direction });