aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/frontend/io_interface.zig50
-rw-r--r--src/frontend/ncurses.zig26
-rw-r--r--src/main.zig45
3 files changed, 80 insertions, 41 deletions
diff --git a/src/frontend/io_interface.zig b/src/frontend/io_interface.zig
new file mode 100644
index 0000000..a2aa0ca
--- /dev/null
+++ b/src/frontend/io_interface.zig
@@ -0,0 +1,50 @@
+const std = @import("std");
+const Action = @import("../actions.zig").Action;
+
+pub const IOInterface = struct {
+ ptr: *anyopaque,
+ displayMessageFn: *const fn (ptr: *anyopaque, str: []const u8) anyerror!void,
+ waitForTickFn: *const fn (ptr: *anyopaque) anyerror!Action,
+ deinitFn: *const fn (ptr: *anyopaque) void,
+
+ pub fn init(ptr: anytype) !IOInterface {
+ const T = @TypeOf(ptr);
+ const ptr_info = @typeInfo(T);
+
+ const gen = struct {
+ pub fn displayMessage(pointer: *anyopaque, str: []const u8) anyerror!void {
+ const self: T = @ptrCast(@alignCast(pointer));
+ return ptr_info.Pointer.child.displayMessage(self, str);
+ }
+
+ pub fn waitForTick(pointer: *anyopaque) anyerror!Action {
+ const self: T = @ptrCast(@alignCast(pointer));
+ return ptr_info.Pointer.child.waitForTick(self);
+ }
+
+ pub fn deinit(pointer: *anyopaque) void {
+ const self: T = @ptrCast(@alignCast(pointer));
+ return ptr_info.Pointer.child.deinit(self);
+ }
+ };
+
+ return .{
+ .ptr = ptr,
+ .displayMessageFn = gen.displayMessage,
+ .waitForTickFn = gen.waitForTick,
+ .deinitFn = gen.deinit,
+ };
+ }
+
+ pub fn displayMessage(self: IOInterface, str: []const u8) anyerror!void {
+ return self.displayMessageFn(self.ptr, str);
+ }
+
+ pub fn waitForTick(self: IOInterface) anyerror!Action {
+ return self.waitForTickFn(self.ptr);
+ }
+
+ pub fn deinit(self: IOInterface) void {
+ return self.deinitFn(self.ptr);
+ }
+};
diff --git a/src/frontend/ncurses.zig b/src/frontend/ncurses.zig
index dfbf276..fd58cf1 100644
--- a/src/frontend/ncurses.zig
+++ b/src/frontend/ncurses.zig
@@ -1,5 +1,5 @@
//! This module provides an implementation of IO using the ncurses library.
-const io_interface = @import("io_interface.zig");
+const IOInterface = @import("io_interface.zig").IOInterface;
const std = @import("std");
const Action = @import("../actions.zig").Action;
const ncurses = @cImport({
@@ -120,7 +120,7 @@ pub const IO = struct {
/// Display a message in the message box.
/// Takes a pre-formatted null-terminated string
/// If the message is too wide for the box, display "Message too long" instead.
- pub fn displayMessage(self: *IO, str: []const u8) error{OutOfMemory}!void {
+ pub fn displayMessage(self: *IO, str: []const u8) anyerror!void {
if (self.msgs == null) return;
for (1..MESSAGE_PANEL_WIDTH - 1) |i| {
@@ -161,7 +161,7 @@ pub const IO = struct {
/// An interface for user input and time processing.
/// Waits for the end of a tick and returns a tick action.
/// If input is given before the end of the tick, return that instead.
- pub fn waitForTick(self: *IO) !Action {
+ pub fn waitForTick(self: *IO) anyerror!Action {
var new = std.time.milliTimestamp();
while (new - self.prev_tick_time <= TICK_MS) {
@@ -236,17 +236,17 @@ pub const IO = struct {
);
}
- pub fn init(allocator: std.mem.Allocator) !IO {
+ pub fn init(allocator: std.mem.Allocator) !IOInterface {
_ = locale.setlocale(locale.LC_ALL, "");
- var io = IO{
- .allocator = allocator,
- .inst = null,
- .msgs = null,
- .stat = null,
- .main = null,
- .prev_tick_time = std.time.milliTimestamp(),
- };
+ const io_ptr = try allocator.alloc(IO, 1);
+ var io = &io_ptr[0];
+ io.allocator = allocator;
+ io.inst = null;
+ io.msgs = null;
+ io.stat = null;
+ io.main = null;
+ io.prev_tick_time = std.time.milliTimestamp();
if (ncurses.initscr() == null) {
return error.CursesInitFail;
@@ -275,7 +275,7 @@ pub const IO = struct {
try io.createPanels();
}
- return io;
+ return IOInterface.init(io);
}
fn deleteWindows(self: *IO) void {
diff --git a/src/main.zig b/src/main.zig
index 5fe26db..f55935d 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -2,48 +2,37 @@ const std = @import("std");
const IO = @import("frontend/ncurses.zig").IO;
const Action = @import("actions.zig").Action;
-pub fn main() u8 {
- var gpa = std.heap.GeneralPurposeAllocator(.{}){};
- const allocator = gpa.allocator();
- var io = IO.init(allocator) catch |err| {
- std.log.err("{}", .{err});
- return 1;
- };
- defer io.deinit();
+fn run(allocator: std.mem.Allocator) !void {
+ var io = try IO.init(allocator);
+ defer {
+ io.deinit();
+ }
- io.displayMessage("Initialized") catch {
- return 1;
- };
+ try io.displayMessage("Initialized");
var action = Action.illegal;
var tick_count: usize = 0;
while (action != Action.exit) {
- const str = std.fmt.allocPrint(allocator, "{}", .{tick_count}) catch {
- return 1;
- };
+ const str = try std.fmt.allocPrint(allocator, "{}", .{tick_count});
defer allocator.free(str);
- io.displayMessage(str) catch {
- return 1;
- };
+ try io.displayMessage(str);
- action = io.waitForTick() catch {
- return 1;
- };
+ action = try io.waitForTick();
switch (action) {
Action.tick => {
- const str2 = std.fmt.allocPrint(allocator, "{}", .{tick_count}) catch {
- return 1;
- };
- defer allocator.free(str2);
- io.displayMessage(str2) catch {
- return 1;
- };
-
tick_count += 1;
},
else => {},
}
}
+}
+
+pub fn main() u8 {
+ var gpa = std.heap.GeneralPurposeAllocator(.{}){};
+ const allocator = gpa.allocator();
+ run(allocator) catch {
+ return 1;
+ };
return 0;
}