rename project libvaxis

This is so similar to my vaxis project for go that we'll retain the name
here as well. The two can keep similar APIs and feature sets, but are
used in different languages. Maybe someday libvaxis will export a C api
for even broader use

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
This commit is contained in:
Tim Culverhouse 2024-01-19 10:13:32 -06:00
parent e1c042d5ae
commit c3964fec43
6 changed files with 58 additions and 45 deletions

View file

@ -4,21 +4,21 @@ pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{}); const optimize = b.standardOptimizeOption(.{});
const odditui = b.addModule("odditui", .{ .root_source_file = .{ .path = "src/main.zig" } }); const vaxis = b.addModule("vaxis", .{ .root_source_file = .{ .path = "src/main.zig" } });
const ziglyph = b.dependency("ziglyph", .{ const ziglyph = b.dependency("ziglyph", .{
.optimize = optimize, .optimize = optimize,
.target = target, .target = target,
}); });
odditui.addImport("ziglyph", ziglyph.module("ziglyph")); vaxis.addImport("ziglyph", ziglyph.module("ziglyph"));
const exe = b.addExecutable(.{ const exe = b.addExecutable(.{
.name = "odditui", .name = "vaxis",
.root_source_file = .{ .path = "examples/main.zig" }, .root_source_file = .{ .path = "examples/main.zig" },
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
}); });
exe.root_module.addImport("odditui", odditui); exe.root_module.addImport("vaxis", vaxis);
const run_cmd = b.addRunArtifact(exe); const run_cmd = b.addRunArtifact(exe);

View file

@ -1,5 +1,5 @@
const std = @import("std"); const std = @import("std");
const odditui = @import("odditui"); const vaxis = @import("vaxis");
const log = std.log.scoped(.main); const log = std.log.scoped(.main);
pub fn main() !void { pub fn main() !void {
@ -13,14 +13,14 @@ pub fn main() !void {
} }
const alloc = gpa.allocator(); const alloc = gpa.allocator();
var app: odditui.App(Event) = try odditui.App(Event).init(.{}); var vx = try vaxis.init(Event, .{});
defer app.deinit(alloc); defer vx.deinit(alloc);
try app.start(); try vx.start();
defer app.stop(); defer vx.stop();
outer: while (true) { outer: while (true) {
const event = app.nextEvent(); const event = vx.nextEvent();
log.debug("event: {}\r\n", .{event}); log.debug("event: {}\r\n", .{event});
switch (event) { switch (event) {
.key_press => |key| { .key_press => |key| {
@ -29,7 +29,7 @@ pub fn main() !void {
} }
}, },
.winsize => |ws| { .winsize => |ws| {
try app.resize(alloc, ws.rows, ws.cols); try vx.resize(alloc, ws.rows, ws.cols);
}, },
else => {}, else => {},
} }
@ -37,7 +37,7 @@ pub fn main() !void {
} }
const Event = union(enum) { const Event = union(enum) {
key_press: odditui.Key, key_press: vaxis.Key,
winsize: odditui.Winsize, winsize: vaxis.Winsize,
mouse: u8, mouse: u8,
}; };

2
src/Options.zig Normal file
View file

@ -0,0 +1,2 @@
/// Runtime options
const Options = @This();

View file

@ -1,9 +1,9 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const os = std.os; const os = std.os;
const odditui = @import("main.zig"); const vaxis = @import("main.zig");
const App = odditui.App; const Vaxis = vaxis.Vaxis;
const Key = odditui.Key; const Key = vaxis.Key;
const log = std.log.scoped(.tty); const log = std.log.scoped(.tty);
@ -51,7 +51,7 @@ pub fn stop(self: *Tty) void {
pub fn run( pub fn run(
self: *Tty, self: *Tty,
comptime EventType: type, comptime EventType: type,
app: *App(EventType), vx: *Vaxis(EventType),
) !void { ) !void {
// create a pipe so we can signal to exit the run loop // create a pipe so we can signal to exit the run loop
const pipe = try os.pipe(); const pipe = try os.pipe();
@ -71,11 +71,11 @@ pub fn run(
const WinchHandler = struct { const WinchHandler = struct {
const Self = @This(); const Self = @This();
var winchApp: *App(EventType) = undefined; var vx_winch: *Vaxis(EventType) = undefined;
var fd: os.fd_t = undefined; var fd: os.fd_t = undefined;
fn init(app_arg: *App(EventType), fd_arg: os.fd_t) !void { fn init(vx_arg: *Vaxis(EventType), fd_arg: os.fd_t) !void {
winchApp = app_arg; vx_winch = vx_arg;
fd = fd_arg; fd = fd_arg;
var act = os.Sigaction{ var act = os.Sigaction{
.handler = .{ .handler = Self.handleWinch }, .handler = .{ .handler = Self.handleWinch },
@ -94,10 +94,10 @@ pub fn run(
const ws = getWinsize(fd) catch { const ws = getWinsize(fd) catch {
return; return;
}; };
winchApp.postEvent(.{ .winsize = ws }); vx_winch.postEvent(.{ .winsize = ws });
} }
}; };
try WinchHandler.init(app, self.fd); try WinchHandler.init(vx, self.fd);
// the state of the parser // the state of the parser
const State = enum { const State = enum {
@ -157,7 +157,7 @@ pub fn run(
else => Key{ .codepoint = b }, else => Key{ .codepoint = b },
}; };
if (key) |k| { if (key) |k| {
app.postEvent(.{ .key_press = k }); vx.postEvent(.{ .key_press = k });
} }
}, },
.escape => state = .ground, .escape => state = .ground,

View file

@ -1,13 +1,21 @@
pub const App = @import("app.zig").App; pub const Vaxis = @import("vaxis.zig").Vaxis;
pub const Options = @import("Options.zig");
pub const Key = @import("Key.zig"); pub const Key = @import("Key.zig");
pub const Winsize = @import("Tty.zig").Winsize; pub const Winsize = @import("Tty.zig").Winsize;
/// Initialize a Vaxis application.
pub fn init(comptime EventType: type, opts: Options) !Vaxis(EventType) {
return Vaxis(EventType).init(opts);
}
test { test {
_ = @import("Key.zig"); _ = @import("Key.zig");
_ = @import("Options.zig");
_ = @import("Screen.zig"); _ = @import("Screen.zig");
_ = @import("Tty.zig"); _ = @import("Tty.zig");
_ = @import("Window.zig"); _ = @import("Window.zig");
_ = @import("app.zig");
_ = @import("cell.zig"); _ = @import("cell.zig");
_ = @import("queue.zig"); _ = @import("queue.zig");
_ = @import("vaxis.zig");
} }

View file

@ -5,25 +5,26 @@ const Tty = @import("Tty.zig");
const Key = @import("Key.zig"); const Key = @import("Key.zig");
const Screen = @import("Screen.zig"); const Screen = @import("Screen.zig");
const Window = @import("Window.zig"); const Window = @import("Window.zig");
const Options = @import("Options.zig");
/// App is the entrypoint for an odditui application. The provided type T should /// Vaxis is the entrypoint for a Vaxis application. The provided type T should
/// be a tagged union which contains all of the events the application will /// be a tagged union which contains all of the events the application will
/// handle. Odditui will look for the following fields on the union and, if /// handle. Vaxis will look for the following fields on the union and, if
/// found, emit them via the "nextEvent" method /// found, emit them via the "nextEvent" method
/// ///
/// The following events *must* be in your enum /// The following events are available:
/// - `key_press: Key`, for key press events /// - `key_press: Key`, for key press events
/// - `winsize: std.os.system.winsize`, for resize events. Must call app.resize /// - `winsize: Winsize`, for resize events. Must call app.resize when receiving
/// when receiving this event /// this event
pub fn App(comptime T: type) type { pub fn Vaxis(comptime T: type) type {
return struct { return struct {
const Self = @This(); const Self = @This();
const log = std.log.scoped(.app); const log = std.log.scoped(.vaxis);
pub const EventType = T; pub const EventType = T;
/// the event queue for this App /// the event queue for Vaxis
// //
// TODO: is 512 ok? // TODO: is 512 ok?
queue: queue.Queue(T, 512), queue: queue.Queue(T, 512),
@ -32,10 +33,7 @@ pub fn App(comptime T: type) type {
screen: Screen, screen: Screen,
/// Runtime options /// Initialize Vaxis with runtime options
const Options = struct {};
/// Initialize an App with runtime options
pub fn init(_: Options) !Self { pub fn init(_: Options) !Self {
return Self{ return Self{
.queue = .{}, .queue = .{},
@ -44,12 +42,16 @@ pub fn App(comptime T: type) type {
}; };
} }
pub fn deinit(self: *Self, alloc: std.mem.Allocator) void { /// Resets the terminal to it's original state. If an allocator is
/// passed, this will free resources associated with Vaxis. This is left as an
/// optional so applications can choose to not free resources when the
/// application will be exiting anyways
pub fn deinit(self: *Self, alloc: ?std.mem.Allocator) void {
if (self.tty) |_| { if (self.tty) |_| {
var tty = &self.tty.?; var tty = &self.tty.?;
tty.deinit(); tty.deinit();
} }
self.screen.deinit(alloc); if (alloc) |a| self.screen.deinit(a);
} }
/// spawns the input thread to start listening to the tty for input /// spawns the input thread to start listening to the tty for input
@ -60,6 +62,7 @@ pub fn App(comptime T: type) type {
try read_thread.setName("tty"); try read_thread.setName("tty");
} }
/// stops reading from the tty
pub fn stop(self: *Self) void { pub fn stop(self: *Self) void {
if (self.tty) |_| { if (self.tty) |_| {
var tty = &self.tty.?; var tty = &self.tty.?;
@ -85,6 +88,7 @@ pub fn App(comptime T: type) type {
try self.screen.resize(alloc, w, h); try self.screen.resize(alloc, w, h);
} }
/// returns a Window comprising of the entire terminal screen
pub fn window(self: *Self) Window { pub fn window(self: *Self) Window {
return Window{ return Window{
.x_off = 0, .x_off = 0,
@ -98,14 +102,13 @@ pub fn App(comptime T: type) type {
}; };
} }
test "App: event queueing" { test "Vaxis: event queueing" {
const Event = union(enum) { const Event = union(enum) {
key, key,
}; };
const alloc = std.testing.allocator; var vx: Vaxis(Event) = try Vaxis(Event).init(.{});
var app: App(Event) = try App(Event).init(.{}); defer vx.deinit(null);
defer app.deinit(alloc); vx.postEvent(.key);
app.postEvent(.key); const event = vx.nextEvent();
const event = app.nextEvent();
try std.testing.expect(event == .key); try std.testing.expect(event == .key);
} }