diff --git a/README.md b/README.md index 8509ac2..26c4acf 100644 --- a/README.md +++ b/README.md @@ -35,3 +35,5 @@ pub fn render(rows: i32, cols: i32) void { PRs are always welcome if you feel that something needs improvement/fixing! Make sure to follow [Conventional Commits](https://www.conventionalcommits.org/) and to run tests first, though. Run tests using `gyro build test`. Note that tests are run on the native target, not WASM. + +Documentation may be generated by running `gyro build -Ddocs`. diff --git a/build.zig b/build.zig index aae6aa2..8e82e7a 100644 --- a/build.zig +++ b/build.zig @@ -1,7 +1,7 @@ const std = @import("std"); const pkgs = @import("deps.zig").pkgs; -pub fn build(b: *std.build.Builder) void { +pub fn build(b: *std.build.Builder) !void { const docs = b.option(bool, "docs", "emit docs") orelse false; // Standard release options allow the person running `zig build` to select // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. @@ -16,6 +16,9 @@ pub fn build(b: *std.build.Builder) void { if (docs) { lib.emit_docs = .{ .emit_to = "zig-out/docs" }; + const create_out_step = try b.allocator.create(std.build.Step); + create_out_step.* = CreateZigOutStep.step(b.allocator); + lib.step.dependOn(create_out_step); } lib.install(); @@ -27,3 +30,23 @@ pub fn build(b: *std.build.Builder) void { const test_step = b.step("test", "Run library tests"); test_step.dependOn(&main_tests.step); } + +/// A step to create the zig-out directory for documentation. +const CreateZigOutStep = struct { + pub fn step(ally: std.mem.Allocator) std.build.Step { + return std.build.Step.init( + .custom, + "Create zig-out", + ally, + &make, + ); + } + + fn make(_: *std.build.Step) anyerror!void { + // TODO: don't hardcode zig-out + std.fs.cwd().makeDir("zig-out") catch |e| { + if (e != error.PathAlreadyExists) + return e; + }; + } +}; diff --git a/src/api.zig b/src/api.zig index 9e64abe..5c80cf1 100644 --- a/src/api.zig +++ b/src/api.zig @@ -1,16 +1,21 @@ +//! This module contains Zellij's API. +//! Every function in this module is used to communicate with zellij. + const std = @import("std"); const zz = @import("main.zig"); const json = @import("json"); const zapi = @import("zellij_api.zig"); const types = @import("types.zig"); +/// Sends an object as JSON to zellij pub fn sendObj(data: anytype) !void { var stdout = std.io.getStdOut(); try json.toWriter(data, stdout.writer()); try stdout.writeAll("\n"); } -pub fn recvObj(comptime T: type) !types.OwnedDeserData(T) { +/// Receives a JSON object from zellij +pub fn recvObj(comptime T: type) !zz.OwnedDeserData(T) { var stdin = std.io.getStdIn(); const data = (try stdin.reader().readUntilDelimiterOrEofAlloc( @@ -20,32 +25,37 @@ pub fn recvObj(comptime T: type) !types.OwnedDeserData(T) { )) orelse unreachable; defer zz.allocator.?.free(data); - return types.OwnedDeserData(T).deserialize(zz.allocator.?, data); + return zz.OwnedDeserData(T).deserialize(zz.allocator.?, data); } -// Subscription Handling +/// Subscribes to the given events. +/// `Plugin.update` will be called on the subscribed avents. pub fn subscribe(event_types: []const types.EventType) !void { try sendObj(event_types); zapi.host_subscribe(); } +/// Unsubscribe from the given events. +/// `Plugin.update` will no longer be called upon receiving the given events. pub fn unsubscribe(event_types: []const types.EventType) !void { try sendObj(event_types); zapi.host_unsubscribe(); } -// Plugin Settings +/// If the plugin is set to be selectable, it will allow the user to tab into it, +/// and it will keep zellij alive if the other panes are closed. pub fn setSelectable(selectable: bool) void { zapi.host_set_selectable(@boolToInt(selectable)); } -// Query Functions -pub fn getPluginIds() !types.OwnedDeserData(types.PluginIds) { +/// Returns the ID of this plugin, and zellij's PID. +pub fn getPluginIds() !zz.OwnedDeserData(types.PluginIds) { zapi.host_get_plugin_ids(); return try recvObj(types.PluginIds); } -pub fn getZellijVersion() !types.OwnedDeserData([]const u8) { +/// Returns zellij's version string. +pub fn getZellijVersion() !zz.OwnedDeserData([]const u8) { zapi.host_get_zellij_version(); return try recvObj([]const u8); } @@ -55,14 +65,17 @@ pub fn openFile(path: []const u8) !void { zapi.host_open_file(); } +/// Switches the currently selected zellij tab to the given index. pub fn switchTabTo(tab_idx: u32) void { zapi.host_switch_tab_to(tab_idx); } +/// Triggers the `.Timer` event in the given amount of seconds. pub fn setTimeout(secs: f64) void { zapi.host_set_timeout(secs); } +/// Executes a system command. This must be enabled in the plugin's configuration. pub fn execCmd(cmd: []const []const u8) !void { try sendObj(cmd); zapi.host_exec_cmd(); diff --git a/src/main.zig b/src/main.zig index c5a7d80..6031457 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,20 +1,21 @@ const std = @import("std"); pub const types = @import("types.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. +/// This is the allocator that will be used by zellzig for communication. +/// This must be set before events can be received. pub var allocator: ?std.mem.Allocator = null; -comptime { - if (@import("builtin").is_test) - std.testing.refAllDecls(@This()); +test { + std.testing.refAllDecls(@This()); } /// Creates a plugin that can be called into by zellij. This function should take a /// struct type with the functions of your plugin. Usage of this function should /// look like this: +/// /// ```zig /// // main.zig /// const zz = @import("zellzig"); @@ -26,7 +27,7 @@ comptime { /// const alloc = std.heap.GeneralPurposeAllocator(.{}){}; /// zz.allocator = alloc.allocator(); /// } -/// pub fn update() void {} +/// pub fn update(event: zz.Event) void {} /// pub fn render(rows: i32, cols: i32) void {} /// ``` pub fn createPlugin(comptime Plugin: type) void { diff --git a/src/types.zig b/src/types.zig index 37e0d5e..480e9b8 100644 --- a/src/types.zig +++ b/src/types.zig @@ -10,8 +10,12 @@ pub const dbs = .{ @import("deserialization_blocks/line_and_column.zig"), }; -// required because the only way to properly free deserilized -// json is using an arena alloc. +/// This is a wrapper object around some data deserialized from JSON. +/// Its purpose is to manage the allocation of the data, as the data +/// created by the JSON deserializer needs to be managed using an arena allocator. +/// +/// This object must be freed by calling `deinit`. +/// The data can be accessed using the `data` field. pub fn OwnedDeserData(comptime T: type) type { return struct { data: T, diff --git a/src/zellij_api.zig b/src/zellij_api.zig index 041814f..61dfc36 100644 --- a/src/zellij_api.zig +++ b/src/zellij_api.zig @@ -1,3 +1,5 @@ +//! Raw Zellij API externs. + pub extern "zellij" fn host_subscribe() void; pub extern "zellij" fn host_unsubscribe() void; pub extern "zellij" fn host_set_selectable(selectable: i32) void;