refactor: make code more idiomatic
- Added standard .gitattributes file for Zig projects. - Reworked build.zig a little, hopefully it's a bit clearer. Also, now zig build will run all steps. - outer: while in examples was redundant since there's only one loop to break from. switch expressions don't allow breaking from them, so breaking is only for loops, i.e. while and for. - When returning a struct instance from a function, the compiler infers the return type from function signature, so instead of return MyType{...}; , it's more idiomatic to write return .{...};. - Logging adds a new line by default, so you don't usually need to write \n like here: log.debug("event: {}\r\n", .{event});.
This commit is contained in:
parent
a733860a21
commit
4a463cfa3a
20 changed files with 115 additions and 160 deletions
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*.zig text eol=lf
|
||||||
|
*.zon text eol=lf
|
12
README.md
12
README.md
|
@ -53,7 +53,7 @@ const border = vaxis.widgets.border;
|
||||||
|
|
||||||
const log = std.log.scoped(.main);
|
const log = std.log.scoped(.main);
|
||||||
|
|
||||||
// Our EventType. This can contain internal events as well as Vaxis events.
|
// This can contain internal events as well as Vaxis events.
|
||||||
// Internal events can be posted into the same queue as vaxis events to allow
|
// Internal events can be posted into the same queue as vaxis events to allow
|
||||||
// for a single event loop with exhaustive switching. Booya
|
// for a single event loop with exhaustive switching. Booya
|
||||||
const Event = union(enum) {
|
const Event = union(enum) {
|
||||||
|
@ -102,12 +102,12 @@ pub fn main() !void {
|
||||||
|
|
||||||
// The main event loop. Vaxis provides a thread safe, blocking, buffered
|
// The main event loop. Vaxis provides a thread safe, blocking, buffered
|
||||||
// queue which can serve as the primary event queue for an application
|
// queue which can serve as the primary event queue for an application
|
||||||
outer: while (true) {
|
while (true) {
|
||||||
// nextEvent blocks until an event is in the queue
|
// nextEvent blocks until an event is in the queue
|
||||||
const event = vx.nextEvent();
|
const event = vx.nextEvent();
|
||||||
log.debug("event: {}\r\n", .{event});
|
log.debug("event: {}", .{event});
|
||||||
// exhaustive switching ftw. Vaxis will send events if your EventType
|
// exhaustive switching ftw. Vaxis will send events if your Event enum
|
||||||
// enum has the fields for those events (ie "key_press", "winsize")
|
// has the fields for those events (ie "key_press", "winsize")
|
||||||
switch (event) {
|
switch (event) {
|
||||||
.key_press => |key| {
|
.key_press => |key| {
|
||||||
color_idx = switch (color_idx) {
|
color_idx = switch (color_idx) {
|
||||||
|
@ -115,7 +115,7 @@ pub fn main() !void {
|
||||||
else => color_idx + 1,
|
else => color_idx + 1,
|
||||||
};
|
};
|
||||||
if (key.matches('c', .{ .ctrl = true })) {
|
if (key.matches('c', .{ .ctrl = true })) {
|
||||||
break :outer;
|
break;
|
||||||
} else if (key.matches('l', .{ .ctrl = true })) {
|
} else if (key.matches('l', .{ .ctrl = true })) {
|
||||||
vx.queueRefresh();
|
vx.queueRefresh();
|
||||||
} else {
|
} else {
|
||||||
|
|
67
build.zig
67
build.zig
|
@ -3,52 +3,61 @@ const std = @import("std");
|
||||||
pub fn build(b: *std.Build) void {
|
pub fn build(b: *std.Build) void {
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
const root_source_file = std.Build.LazyPath.relative("src/main.zig");
|
||||||
|
|
||||||
const vaxis = b.addModule("vaxis", .{ .root_source_file = .{ .path = "src/main.zig" } });
|
// Dependencies
|
||||||
|
const ziglyph_dep = b.dependency("ziglyph", .{
|
||||||
const ziglyph = b.dependency("ziglyph", .{
|
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.target = target,
|
.target = target,
|
||||||
});
|
});
|
||||||
vaxis.addImport("ziglyph", ziglyph.module("ziglyph"));
|
const zigimg_dep = b.dependency("zigimg", .{
|
||||||
|
|
||||||
const zigimg = b.dependency("zigimg", .{
|
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.target = target,
|
.target = target,
|
||||||
});
|
});
|
||||||
vaxis.addImport("zigimg", zigimg.module("zigimg"));
|
|
||||||
|
|
||||||
const exe = b.addExecutable(.{
|
// Module
|
||||||
.name = "vaxis",
|
const vaxis_mod = b.addModule("vaxis", .{ .root_source_file = root_source_file });
|
||||||
.root_source_file = .{ .path = "examples/pathological.zig" },
|
vaxis_mod.addImport("ziglyph", ziglyph_dep.module("ziglyph"));
|
||||||
|
vaxis_mod.addImport("zigimg", zigimg_dep.module("zigimg"));
|
||||||
|
|
||||||
|
// Examples
|
||||||
|
const example_step = b.step("example", "Run examples");
|
||||||
|
|
||||||
|
const example = b.addExecutable(.{
|
||||||
|
.name = "vaxis_pathological_example",
|
||||||
|
.root_source_file = std.Build.LazyPath.relative("examples/pathological.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
exe.root_module.addImport("vaxis", vaxis);
|
example.root_module.addImport("vaxis", vaxis_mod);
|
||||||
|
|
||||||
const run_cmd = b.addRunArtifact(exe);
|
const example_run = b.addRunArtifact(example);
|
||||||
|
example_step.dependOn(&example_run.step);
|
||||||
|
b.default_step.dependOn(example_step);
|
||||||
|
|
||||||
run_cmd.step.dependOn(b.getInstallStep());
|
// Tests
|
||||||
|
const tests_step = b.step("test", "Run tests");
|
||||||
|
|
||||||
if (b.args) |args| {
|
const tests = b.addTest(.{
|
||||||
run_cmd.addArgs(args);
|
.root_source_file = root_source_file,
|
||||||
}
|
|
||||||
|
|
||||||
const run_step = b.step("run", "Run the app");
|
|
||||||
run_step.dependOn(&run_cmd.step);
|
|
||||||
|
|
||||||
// Creates a step for unit testing. This only builds the test executable
|
|
||||||
// but does not run it.
|
|
||||||
const lib_unit_tests = b.addTest(.{
|
|
||||||
.root_source_file = .{ .path = "src/main.zig" },
|
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
lib_unit_tests.root_module.addImport("ziglyph", ziglyph.module("ziglyph"));
|
tests.root_module.addImport("ziglyph", ziglyph_dep.module("ziglyph"));
|
||||||
lib_unit_tests.root_module.addImport("zigimg", zigimg.module("zigimg"));
|
tests.root_module.addImport("zigimg", zigimg_dep.module("zigimg"));
|
||||||
|
|
||||||
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
|
const tests_run = b.addRunArtifact(tests);
|
||||||
|
tests_step.dependOn(&tests_run.step);
|
||||||
|
b.default_step.dependOn(tests_step);
|
||||||
|
|
||||||
const test_step = b.step("test", "Run unit tests");
|
// Lints
|
||||||
test_step.dependOn(&run_lib_unit_tests.step);
|
const lints_step = b.step("lint", "Run lints");
|
||||||
|
|
||||||
|
const lints = b.addFmt(.{
|
||||||
|
.paths = &.{ "src", "build.zig" },
|
||||||
|
.check = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
lints_step.dependOn(&lints.step);
|
||||||
|
b.default_step.dependOn(lints_step);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +1,15 @@
|
||||||
.{
|
.{
|
||||||
.name = "vaxis",
|
.name = "vaxis",
|
||||||
// This is a [Semantic Version](https://semver.org/).
|
|
||||||
// In a future version of Zig it will be used for package deduplication.
|
|
||||||
.version = "0.1.0",
|
.version = "0.1.0",
|
||||||
|
.paths = .{""},
|
||||||
// This field is optional.
|
|
||||||
// This is currently advisory only; Zig does not yet do anything
|
|
||||||
// with this value.
|
|
||||||
//.minimum_zig_version = "0.11.0",
|
|
||||||
|
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.ziglyph = .{
|
.ziglyph = .{
|
||||||
.url = "https://codeberg.org/dude_the_builder/ziglyph/archive/ac50ab06c91d2dd632ff4573c035dafe3b374aba.tar.gz",
|
.url = "https://codeberg.org/dude_the_builder/ziglyph/archive/ac50ab06c9.tar.gz",
|
||||||
.hash = "1220e097fbfb3a15a6f3484cf507f1f10ab571d1bcf519c3b5447ca727782b7a5264",
|
.hash = "1220e097fbfb3a15a6f3484cf507f1f10ab571d1bcf519c3b5447ca727782b7a5264",
|
||||||
},
|
},
|
||||||
.zigimg = .{
|
.zigimg = .{
|
||||||
.url = "https://github.com/zigimg/zigimg/archive/f6998808f283f8d3c2ef34e8b4af423bc1786f32.tar.gz",
|
.url = "https://github.com/zigimg/zigimg/archive/2224f91.tar.gz",
|
||||||
.hash = "12202ee5d22ade0c300e9e7eae4c1951bda3d5f236fe1a139eb3613b43e2f12a88db",
|
.hash = "12207067e4892c48369415268648380859baa89c324748ae5bfda414a12868c9fc8b",
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
.paths = .{
|
|
||||||
// This makes *all* files, recursively, included in this package. It is generally
|
|
||||||
// better to explicitly list the files and directories instead, to insure that
|
|
||||||
// fetching from tarballs, file system paths, and version control all result
|
|
||||||
// in the same contents hash.
|
|
||||||
"",
|
|
||||||
// For example...
|
|
||||||
//"build.zig",
|
|
||||||
//"build.zig.zon",
|
|
||||||
//"src",
|
|
||||||
//"LICENSE",
|
|
||||||
//"README.md",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ pub fn main() !void {
|
||||||
|
|
||||||
const img = imgs[n];
|
const img = imgs[n];
|
||||||
const dims = try img.cellSize(win);
|
const dims = try img.cellSize(win);
|
||||||
const center = vaxis.alignment.center(win, dims.cols, dims.rows);
|
const center = vaxis.widgets.alignment.center(win, dims.cols, dims.rows);
|
||||||
const scale = false;
|
const scale = false;
|
||||||
const z_index = 0;
|
const z_index = 0;
|
||||||
img.draw(center, scale, z_index);
|
img.draw(center, scale, z_index);
|
||||||
|
|
|
@ -32,11 +32,11 @@ pub fn main() !void {
|
||||||
|
|
||||||
// The main event loop. Vaxis provides a thread safe, blocking, buffered
|
// The main event loop. Vaxis provides a thread safe, blocking, buffered
|
||||||
// queue which can serve as the primary event queue for an application
|
// queue which can serve as the primary event queue for an application
|
||||||
outer: while (true) {
|
while (true) {
|
||||||
// nextEvent blocks until an event is in the queue
|
// nextEvent blocks until an event is in the queue
|
||||||
const event = vx.nextEvent();
|
const event = vx.nextEvent();
|
||||||
log.debug("event: {}\r\n", .{event});
|
log.debug("event: {}", .{event});
|
||||||
// exhaustive switching ftw. Vaxis will send events if your EventType
|
// exhaustive switching ftw. Vaxis will send events if your Event
|
||||||
// enum has the fields for those events (ie "key_press", "winsize")
|
// enum has the fields for those events (ie "key_press", "winsize")
|
||||||
switch (event) {
|
switch (event) {
|
||||||
.key_press => |key| {
|
.key_press => |key| {
|
||||||
|
@ -45,7 +45,7 @@ pub fn main() !void {
|
||||||
else => color_idx + 1,
|
else => color_idx + 1,
|
||||||
};
|
};
|
||||||
if (key.codepoint == 'c' and key.mods.ctrl) {
|
if (key.codepoint == 'c' and key.mods.ctrl) {
|
||||||
break :outer;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.winsize => |ws| {
|
.winsize => |ws| {
|
||||||
|
@ -87,7 +87,7 @@ pub fn main() !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Our EventType. This can contain internal events as well as Vaxis events.
|
// Our Event. This can contain internal events as well as Vaxis events.
|
||||||
// Internal events can be posted into the same queue as vaxis events to allow
|
// Internal events can be posted into the same queue as vaxis events to allow
|
||||||
// for a single event loop with exhaustive switching. Booya
|
// for a single event loop with exhaustive switching. Booya
|
||||||
const Event = union(enum) {
|
const Event = union(enum) {
|
||||||
|
|
|
@ -19,12 +19,12 @@ pub fn main() !void {
|
||||||
try vx.enterAltScreen();
|
try vx.enterAltScreen();
|
||||||
try vx.queryTerminal();
|
try vx.queryTerminal();
|
||||||
|
|
||||||
outer: while (true) {
|
while (true) {
|
||||||
const event = vx.nextEvent();
|
const event = vx.nextEvent();
|
||||||
switch (event) {
|
switch (event) {
|
||||||
.winsize => |ws| {
|
.winsize => |ws| {
|
||||||
try vx.resize(alloc, ws);
|
try vx.resize(alloc, ws);
|
||||||
break :outer;
|
break;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ const border = vaxis.widgets.border;
|
||||||
|
|
||||||
const log = std.log.scoped(.main);
|
const log = std.log.scoped(.main);
|
||||||
|
|
||||||
// Our EventType. This can contain internal events as well as Vaxis events.
|
// Our Event. This can contain internal events as well as Vaxis events.
|
||||||
// Internal events can be posted into the same queue as vaxis events to allow
|
// Internal events can be posted into the same queue as vaxis events to allow
|
||||||
// for a single event loop with exhaustive switching. Booya
|
// for a single event loop with exhaustive switching. Booya
|
||||||
const Event = union(enum) {
|
const Event = union(enum) {
|
||||||
|
@ -59,11 +59,11 @@ pub fn main() !void {
|
||||||
|
|
||||||
// The main event loop. Vaxis provides a thread safe, blocking, buffered
|
// The main event loop. Vaxis provides a thread safe, blocking, buffered
|
||||||
// queue which can serve as the primary event queue for an application
|
// queue which can serve as the primary event queue for an application
|
||||||
outer: while (true) {
|
while (true) {
|
||||||
// nextEvent blocks until an event is in the queue
|
// nextEvent blocks until an event is in the queue
|
||||||
const event = vx.nextEvent();
|
const event = vx.nextEvent();
|
||||||
log.debug("event: {}\r\n", .{event});
|
log.debug("event: {}", .{event});
|
||||||
// exhaustive switching ftw. Vaxis will send events if your EventType
|
// exhaustive switching ftw. Vaxis will send events if your Event
|
||||||
// enum has the fields for those events (ie "key_press", "winsize")
|
// enum has the fields for those events (ie "key_press", "winsize")
|
||||||
switch (event) {
|
switch (event) {
|
||||||
.key_press => |key| {
|
.key_press => |key| {
|
||||||
|
@ -72,7 +72,7 @@ pub fn main() !void {
|
||||||
else => color_idx + 1,
|
else => color_idx + 1,
|
||||||
};
|
};
|
||||||
if (key.matches('c', .{ .ctrl = true })) {
|
if (key.matches('c', .{ .ctrl = true })) {
|
||||||
break :outer;
|
break;
|
||||||
} else if (key.matches('l', .{ .ctrl = true })) {
|
} else if (key.matches('l', .{ .ctrl = true })) {
|
||||||
vx.queueRefresh();
|
vx.queueRefresh();
|
||||||
} else if (key.matches('n', .{ .ctrl = true })) {
|
} else if (key.matches('n', .{ .ctrl = true })) {
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
const Image = @import("Image.zig");
|
const Image = @import("Image.zig");
|
||||||
|
|
||||||
pub const Cell = struct {
|
char: Character = .{},
|
||||||
char: Character = .{},
|
style: Style = .{},
|
||||||
style: Style = .{},
|
link: Hyperlink = .{},
|
||||||
link: Hyperlink = .{},
|
image: ?Image.Placement = null,
|
||||||
image: ?Image.Placement = null,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Segment is a contiguous run of text that has a constant style
|
/// Segment is a contiguous run of text that has a constant style
|
||||||
pub const Segment = struct {
|
pub const Segment = struct {
|
||||||
|
@ -17,7 +15,7 @@ pub const Segment = struct {
|
||||||
pub const Character = struct {
|
pub const Character = struct {
|
||||||
grapheme: []const u8 = " ",
|
grapheme: []const u8 = " ",
|
||||||
/// width should only be provided when the application is sure the terminal
|
/// width should only be provided when the application is sure the terminal
|
||||||
/// will meeasure the same width. This can be ensure by using the gwidth method
|
/// will measure the same width. This can be ensure by using the gwidth method
|
||||||
/// included in libvaxis. If width is 0, libvaxis will measure the glyph at
|
/// included in libvaxis. If width is 0, libvaxis will measure the glyph at
|
||||||
/// render time
|
/// render time
|
||||||
width: usize = 1,
|
width: usize = 1,
|
|
@ -1,7 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const Style = @import("cell.zig").Style;
|
const Style = @import("Cell.zig").Style;
|
||||||
const Cell = @import("cell.zig").Cell;
|
const Cell = @import("Cell.zig");
|
||||||
const Shape = @import("Mouse.zig").Shape;
|
const Shape = @import("Mouse.zig").Shape;
|
||||||
|
|
||||||
const log = std.log.scoped(.internal_screen);
|
const log = std.log.scoped(.internal_screen);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
const Cell = @import("cell.zig").Cell;
|
const Cell = @import("Cell.zig");
|
||||||
const Shape = @import("Mouse.zig").Shape;
|
const Shape = @import("Mouse.zig").Shape;
|
||||||
const Image = @import("Image.zig");
|
const Image = @import("Image.zig");
|
||||||
const Winsize = @import("Tty.zig").Winsize;
|
const Winsize = @import("Tty.zig").Winsize;
|
||||||
|
|
29
src/Tty.zig
29
src/Tty.zig
|
@ -1,11 +1,8 @@
|
||||||
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 vaxis = @import("main.zig");
|
const Vaxis = @import("vaxis.zig").Vaxis;
|
||||||
const Vaxis = vaxis.Vaxis;
|
|
||||||
const Event = @import("event.zig").Event;
|
|
||||||
const Parser = @import("Parser.zig");
|
const Parser = @import("Parser.zig");
|
||||||
const Key = vaxis.Key;
|
|
||||||
const GraphemeCache = @import("GraphemeCache.zig");
|
const GraphemeCache = @import("GraphemeCache.zig");
|
||||||
|
|
||||||
const log = std.log.scoped(.tty);
|
const log = std.log.scoped(.tty);
|
||||||
|
@ -68,8 +65,8 @@ pub fn stop(self: *Tty) void {
|
||||||
/// read input from the tty
|
/// read input from the tty
|
||||||
pub fn run(
|
pub fn run(
|
||||||
self: *Tty,
|
self: *Tty,
|
||||||
comptime EventType: type,
|
comptime Event: type,
|
||||||
vx: *Vaxis(EventType),
|
vx: *Vaxis(Event),
|
||||||
) !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();
|
||||||
|
@ -78,7 +75,7 @@ pub fn run(
|
||||||
|
|
||||||
// get our initial winsize
|
// get our initial winsize
|
||||||
const winsize = try getWinsize(self.fd);
|
const winsize = try getWinsize(self.fd);
|
||||||
if (@hasField(EventType, "winsize")) {
|
if (@hasField(Event, "winsize")) {
|
||||||
vx.postEvent(.{ .winsize = winsize });
|
vx.postEvent(.{ .winsize = winsize });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,10 +88,10 @@ pub fn run(
|
||||||
const WinchHandler = struct {
|
const WinchHandler = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
var vx_winch: *Vaxis(EventType) = undefined;
|
var vx_winch: *Vaxis(Event) = undefined;
|
||||||
var fd: os.fd_t = undefined;
|
var fd: os.fd_t = undefined;
|
||||||
|
|
||||||
fn init(vx_arg: *Vaxis(EventType), fd_arg: os.fd_t) !void {
|
fn init(vx_arg: *Vaxis(Event), fd_arg: os.fd_t) !void {
|
||||||
vx_winch = vx_arg;
|
vx_winch = vx_arg;
|
||||||
fd = fd_arg;
|
fd = fd_arg;
|
||||||
var act = os.Sigaction{
|
var act = os.Sigaction{
|
||||||
|
@ -114,7 +111,7 @@ pub fn run(
|
||||||
const ws = getWinsize(fd) catch {
|
const ws = getWinsize(fd) catch {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if (@hasField(EventType, "winsize")) {
|
if (@hasField(Event, "winsize")) {
|
||||||
vx_winch.postEvent(.{ .winsize = ws });
|
vx_winch.postEvent(.{ .winsize = ws });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +153,7 @@ pub fn run(
|
||||||
const event = result.event orelse continue;
|
const event = result.event orelse continue;
|
||||||
switch (event) {
|
switch (event) {
|
||||||
.key_press => |key| {
|
.key_press => |key| {
|
||||||
if (@hasField(EventType, "key_press")) {
|
if (@hasField(Event, "key_press")) {
|
||||||
// HACK: yuck. there has to be a better way
|
// HACK: yuck. there has to be a better way
|
||||||
var mut_key = key;
|
var mut_key = key;
|
||||||
if (key.text) |text| {
|
if (key.text) |text| {
|
||||||
|
@ -166,27 +163,27 @@ pub fn run(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.mouse => |mouse| {
|
.mouse => |mouse| {
|
||||||
if (@hasField(EventType, "mouse")) {
|
if (@hasField(Event, "mouse")) {
|
||||||
vx.postEvent(.{ .mouse = mouse });
|
vx.postEvent(.{ .mouse = mouse });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.focus_in => {
|
.focus_in => {
|
||||||
if (@hasField(EventType, "focus_in")) {
|
if (@hasField(Event, "focus_in")) {
|
||||||
vx.postEvent(.focus_in);
|
vx.postEvent(.focus_in);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.focus_out => {
|
.focus_out => {
|
||||||
if (@hasField(EventType, "focus_out")) {
|
if (@hasField(Event, "focus_out")) {
|
||||||
vx.postEvent(.focus_out);
|
vx.postEvent(.focus_out);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.paste_start => {
|
.paste_start => {
|
||||||
if (@hasField(EventType, "paste_start")) {
|
if (@hasField(Event, "paste_start")) {
|
||||||
vx.postEvent(.paste_start);
|
vx.postEvent(.paste_start);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.paste_end => {
|
.paste_end => {
|
||||||
if (@hasField(EventType, "paste_end")) {
|
if (@hasField(Event, "paste_end")) {
|
||||||
vx.postEvent(.paste_end);
|
vx.postEvent(.paste_end);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,8 +4,8 @@ const WordIterator = ziglyph.WordIterator;
|
||||||
const GraphemeIterator = ziglyph.GraphemeIterator;
|
const GraphemeIterator = ziglyph.GraphemeIterator;
|
||||||
|
|
||||||
const Screen = @import("Screen.zig");
|
const Screen = @import("Screen.zig");
|
||||||
const Cell = @import("cell.zig").Cell;
|
const Cell = @import("Cell.zig");
|
||||||
const Segment = @import("cell.zig").Segment;
|
const Segment = @import("Cell.zig").Segment;
|
||||||
const gw = @import("gwidth.zig");
|
const gw = @import("gwidth.zig");
|
||||||
|
|
||||||
const log = std.log.scoped(.window);
|
const log = std.log.scoped(.window);
|
||||||
|
@ -118,7 +118,7 @@ pub fn wrap(self: Window, segments: []Segment) !void {
|
||||||
var word_iter = try WordIterator.init(segment.text);
|
var word_iter = try WordIterator.init(segment.text);
|
||||||
while (word_iter.next()) |word| {
|
while (word_iter.next()) |word| {
|
||||||
// break lines when we need
|
// break lines when we need
|
||||||
if (isLineBreak(word.bytes)) {
|
if (word.bytes[0] == '\r' or word.bytes[0] == '\n') {
|
||||||
row += 1;
|
row += 1;
|
||||||
col = 0;
|
col = 0;
|
||||||
wrapped = false;
|
wrapped = false;
|
||||||
|
@ -158,18 +158,6 @@ pub fn wrap(self: Window, segments: []Segment) !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn isLineBreak(str: []const u8) bool {
|
|
||||||
if (std.mem.eql(u8, str, "\r\n")) {
|
|
||||||
return true;
|
|
||||||
} else if (std.mem.eql(u8, str, "\r")) {
|
|
||||||
return true;
|
|
||||||
} else if (std.mem.eql(u8, str, "\n")) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test "Window size set" {
|
test "Window size set" {
|
||||||
var parent = Window{
|
var parent = Window{
|
||||||
.x_off = 0,
|
.x_off = 0,
|
||||||
|
|
35
src/main.zig
35
src/main.zig
|
@ -1,40 +1,21 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
pub const Vaxis = @import("vaxis.zig").Vaxis;
|
pub const Vaxis = @import("vaxis.zig").Vaxis;
|
||||||
pub const Options = @import("Options.zig");
|
pub const Options = @import("Options.zig");
|
||||||
|
|
||||||
const cell = @import("cell.zig");
|
|
||||||
pub const Cell = cell.Cell;
|
|
||||||
pub const Style = cell.Style;
|
|
||||||
pub const Segment = cell.Segment;
|
|
||||||
pub const Color = cell.Color;
|
|
||||||
|
|
||||||
pub const Key = @import("Key.zig");
|
pub const Key = @import("Key.zig");
|
||||||
|
pub const Cell = @import("Cell.zig");
|
||||||
|
pub const Image = @import("Image.zig");
|
||||||
pub const Mouse = @import("Mouse.zig");
|
pub const Mouse = @import("Mouse.zig");
|
||||||
pub const Winsize = @import("Tty.zig").Winsize;
|
pub const Winsize = @import("Tty.zig").Winsize;
|
||||||
|
|
||||||
pub const widgets = @import("widgets/main.zig");
|
pub const widgets = @import("widgets.zig");
|
||||||
pub const alignment = widgets.alignment;
|
|
||||||
pub const border = widgets.border;
|
|
||||||
|
|
||||||
pub const Image = @import("Image.zig");
|
|
||||||
|
|
||||||
/// Initialize a Vaxis application.
|
/// Initialize a Vaxis application.
|
||||||
pub fn init(comptime EventType: type, opts: Options) !Vaxis(EventType) {
|
pub fn init(comptime Event: type, opts: Options) !Vaxis(Event) {
|
||||||
return Vaxis(EventType).init(opts);
|
return Vaxis(Event).init(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
_ = @import("GraphemeCache.zig");
|
std.testing.refAllDecls(@This());
|
||||||
_ = @import("Key.zig");
|
|
||||||
_ = @import("Mouse.zig");
|
|
||||||
_ = @import("Options.zig");
|
|
||||||
_ = @import("Parser.zig");
|
|
||||||
_ = @import("Screen.zig");
|
|
||||||
_ = @import("Tty.zig");
|
|
||||||
_ = @import("Window.zig");
|
|
||||||
_ = @import("cell.zig");
|
|
||||||
_ = @import("ctlseqs.zig");
|
|
||||||
_ = @import("event.zig");
|
|
||||||
_ = @import("gwidth.zig");
|
|
||||||
_ = @import("queue.zig");
|
|
||||||
_ = @import("vaxis.zig");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@ const Screen = @import("Screen.zig");
|
||||||
const InternalScreen = @import("InternalScreen.zig");
|
const InternalScreen = @import("InternalScreen.zig");
|
||||||
const Window = @import("Window.zig");
|
const Window = @import("Window.zig");
|
||||||
const Options = @import("Options.zig");
|
const Options = @import("Options.zig");
|
||||||
const Style = @import("cell.zig").Style;
|
const Style = @import("Cell.zig").Style;
|
||||||
const Hyperlink = @import("cell.zig").Hyperlink;
|
const Hyperlink = @import("Cell.zig").Hyperlink;
|
||||||
const gwidth = @import("gwidth.zig");
|
const gwidth = @import("gwidth.zig");
|
||||||
const Shape = @import("Mouse.zig").Shape;
|
const Shape = @import("Mouse.zig").Shape;
|
||||||
const Image = @import("Image.zig");
|
const Image = @import("Image.zig");
|
||||||
|
@ -34,7 +34,7 @@ pub fn Vaxis(comptime T: type) type {
|
||||||
|
|
||||||
const log = std.log.scoped(.vaxis);
|
const log = std.log.scoped(.vaxis);
|
||||||
|
|
||||||
pub const EventType = T;
|
pub const Event = T;
|
||||||
|
|
||||||
pub const Capabilities = struct {
|
pub const Capabilities = struct {
|
||||||
kitty_keyboard: bool = false,
|
kitty_keyboard: bool = false,
|
||||||
|
@ -83,7 +83,7 @@ pub fn Vaxis(comptime T: type) type {
|
||||||
|
|
||||||
/// Initialize Vaxis with runtime options
|
/// Initialize Vaxis with runtime options
|
||||||
pub fn init(_: Options) !Self {
|
pub fn init(_: Options) !Self {
|
||||||
return Self{
|
return .{
|
||||||
.queue = .{},
|
.queue = .{},
|
||||||
.tty = null,
|
.tty = null,
|
||||||
.screen = .{},
|
.screen = .{},
|
||||||
|
@ -151,7 +151,7 @@ pub fn Vaxis(comptime T: type) type {
|
||||||
self.queue.push(event);
|
self.queue.push(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// resize allocates a slice of cellsequal to the number of cells
|
/// resize allocates a slice of cells equal to the number of cells
|
||||||
/// required to display the screen (ie width x height). Any previous screen is
|
/// required to display the screen (ie width x height). Any previous screen is
|
||||||
/// freed when resizing
|
/// freed when resizing
|
||||||
pub fn resize(self: *Self, alloc: std.mem.Allocator, winsize: Winsize) !void {
|
pub fn resize(self: *Self, alloc: std.mem.Allocator, winsize: Winsize) !void {
|
||||||
|
@ -169,7 +169,7 @@ pub fn Vaxis(comptime T: type) type {
|
||||||
|
|
||||||
/// returns a Window comprising of the entire terminal screen
|
/// returns a Window comprising of the entire terminal screen
|
||||||
pub fn window(self: *Self) Window {
|
pub fn window(self: *Self) Window {
|
||||||
return Window{
|
return .{
|
||||||
.x_off = 0,
|
.x_off = 0,
|
||||||
.y_off = 0,
|
.y_off = 0,
|
||||||
.width = self.screen.width,
|
.width = self.screen.width,
|
||||||
|
@ -207,7 +207,7 @@ pub fn Vaxis(comptime T: type) type {
|
||||||
if (std.mem.eql(u8, colorterm, "truecolor") or
|
if (std.mem.eql(u8, colorterm, "truecolor") or
|
||||||
std.mem.eql(u8, colorterm, "24bit"))
|
std.mem.eql(u8, colorterm, "24bit"))
|
||||||
{
|
{
|
||||||
if (@hasField(EventType, "cap_rgb")) {
|
if (@hasField(Event, "cap_rgb")) {
|
||||||
self.postEvent(.cap_rgb);
|
self.postEvent(.cap_rgb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,7 +348,7 @@ pub fn Vaxis(comptime T: type) type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// something is different, so let's loop throuugh everything and
|
// something is different, so let's loop through everything and
|
||||||
// find out what
|
// find out what
|
||||||
|
|
||||||
// foreground
|
// foreground
|
||||||
|
@ -642,7 +642,7 @@ pub fn Vaxis(comptime T: type) type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try tty.buffered_writer.flush();
|
try tty.buffered_writer.flush();
|
||||||
return Image{
|
return .{
|
||||||
.id = id,
|
.id = id,
|
||||||
.width = img.width,
|
.width = img.width,
|
||||||
.height = img.height,
|
.height = img.height,
|
||||||
|
|
3
src/widgets.zig
Normal file
3
src/widgets.zig
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
pub const border = @import("widgets/border.zig");
|
||||||
|
pub const alignment = @import("widgets/alignment.zig");
|
||||||
|
pub const TextInput = @import("widgets/TextInput.zig");
|
|
@ -1,6 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Cell = @import("../cell.zig").Cell;
|
|
||||||
const Key = @import("../Key.zig");
|
const Key = @import("../Key.zig");
|
||||||
|
const Cell = @import("../Cell.zig");
|
||||||
const Window = @import("../Window.zig");
|
const Window = @import("../Window.zig");
|
||||||
const GraphemeIterator = @import("ziglyph").GraphemeIterator;
|
const GraphemeIterator = @import("ziglyph").GraphemeIterator;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
const Cell = @import("../Cell.zig");
|
||||||
const Window = @import("../Window.zig");
|
const Window = @import("../Window.zig");
|
||||||
const cell = @import("../cell.zig");
|
|
||||||
const Character = cell.Character;
|
const Style = Cell.Style;
|
||||||
const Style = cell.Style;
|
const Character = Cell.Character;
|
||||||
|
|
||||||
const horizontal = Character{ .grapheme = "─", .width = 1 };
|
const horizontal = Character{ .grapheme = "─", .width = 1 };
|
||||||
const vertical = Character{ .grapheme = "│", .width = 1 };
|
const vertical = Character{ .grapheme = "│", .width = 1 };
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
pub const TextInput = @import("TextInput.zig");
|
|
||||||
pub const border = @import("border.zig");
|
|
||||||
pub const alignment = @import("align.zig");
|
|
Loading…
Reference in a new issue