add(widget): Text widget to display static Cell contents
This commit is contained in:
70
build.zig
70
build.zig
@@ -32,41 +32,46 @@ pub fn build(b: *std.Build) void {
|
||||
lib.addImport("interface", interface.module("interface"));
|
||||
lib.addImport("code_point", zg.module("code_point"));
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "zterm",
|
||||
.root_source_file = b.path("src/main.zig"),
|
||||
// example executables
|
||||
const stack_example = b.addExecutable(.{
|
||||
.name = "stack",
|
||||
.root_source_file = b.path("examples/stack.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.root_module.addImport("zterm", lib);
|
||||
stack_example.root_module.addImport("zterm", lib);
|
||||
|
||||
const container_example = b.addExecutable(.{
|
||||
.name = "container",
|
||||
.root_source_file = b.path("examples/container.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
container_example.root_module.addImport("zterm", lib);
|
||||
|
||||
const padding_example = b.addExecutable(.{
|
||||
.name = "padding",
|
||||
.root_source_file = b.path("examples/padding.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
padding_example.root_module.addImport("zterm", lib);
|
||||
|
||||
const exec_example = b.addExecutable(.{
|
||||
.name = "exec",
|
||||
.root_source_file = b.path("examples/exec.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exec_example.root_module.addImport("zterm", lib);
|
||||
|
||||
// This declares intent for the executable to be installed into the
|
||||
// standard location when the user invokes the "install" step (the default
|
||||
// step when running `zig build`).
|
||||
b.installArtifact(exe);
|
||||
|
||||
// This *creates* a Run step in the build graph, to be executed when another
|
||||
// step is evaluated that depends on it. The next line below will establish
|
||||
// such a dependency.
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
|
||||
// By making the run step depend on the install step, it will be run from the
|
||||
// installation directory rather than directly from within the cache directory.
|
||||
// This is not necessary, however, if the application depends on other installed
|
||||
// files, this ensures they will be present and in the expected location.
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
|
||||
// This allows the user to pass arguments to the application in the build
|
||||
// command itself, like this: `zig build run -- arg1 arg2 etc`
|
||||
if (b.args) |args| {
|
||||
run_cmd.addArgs(args);
|
||||
}
|
||||
|
||||
// This creates a build step. It will be visible in the `zig build --help` menu,
|
||||
// and can be selected like this: `zig build run`
|
||||
// This will evaluate the `run` step rather than the default, which is "install".
|
||||
const run_step = b.step("run", "Run the app");
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
b.installArtifact(stack_example);
|
||||
b.installArtifact(container_example);
|
||||
b.installArtifact(padding_example);
|
||||
b.installArtifact(exec_example);
|
||||
|
||||
// Creates a step for unit testing. This only builds the test executable
|
||||
// but does not run it.
|
||||
@@ -79,18 +84,9 @@ pub fn build(b: *std.Build) void {
|
||||
|
||||
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
|
||||
|
||||
const exe_unit_tests = b.addTest(.{
|
||||
.root_source_file = b.path("src/main.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
||||
|
||||
// Similar to creating the run step earlier, this exposes a `test` step to
|
||||
// the `zig build --help` menu, providing a way for the user to request
|
||||
// running the unit tests.
|
||||
const test_step = b.step("test", "Run unit tests");
|
||||
test_step.dependOn(&run_lib_unit_tests.step);
|
||||
test_step.dependOn(&run_exe_unit_tests.step);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ const std = @import("std");
|
||||
pub const Style = @import("Style.zig");
|
||||
|
||||
style: Style = .{},
|
||||
content: []u8 = undefined,
|
||||
content: []const u8 = undefined,
|
||||
|
||||
pub const Result = struct {
|
||||
idx: usize,
|
||||
|
||||
@@ -91,11 +91,13 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
|
||||
}
|
||||
|
||||
// import and export of `Widget` implementations
|
||||
pub const Text = @import("widget/Text.zig").Widget(Event, Renderer);
|
||||
pub const RawText = @import("widget/RawText.zig").Widget(Event, Renderer);
|
||||
pub const Spacer = @import("widget/Spacer.zig").Widget(Event, Renderer);
|
||||
};
|
||||
// test widget implementation satisfies the interface
|
||||
comptime Type.Interface.satisfiedBy(Type);
|
||||
comptime Type.Interface.satisfiedBy(Type.Text);
|
||||
comptime Type.Interface.satisfiedBy(Type.RawText);
|
||||
comptime Type.Interface.satisfiedBy(Type.Spacer);
|
||||
return Type;
|
||||
|
||||
50
src/widget/Text.zig
Normal file
50
src/widget/Text.zig
Normal file
@@ -0,0 +1,50 @@
|
||||
const std = @import("std");
|
||||
const terminal = @import("../terminal.zig");
|
||||
|
||||
const isTaggedUnion = @import("../event.zig").isTaggedUnion;
|
||||
const Error = @import("../event.zig").Error;
|
||||
const Cell = terminal.Cell;
|
||||
|
||||
const log = std.log.scoped(.widget_text);
|
||||
|
||||
pub fn Widget(comptime Event: type, comptime Renderer: type) type {
|
||||
if (!isTaggedUnion(Event)) {
|
||||
@compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`.");
|
||||
}
|
||||
return struct {
|
||||
contents: []const Cell = undefined,
|
||||
size: terminal.Size = undefined,
|
||||
require_render: bool = false,
|
||||
|
||||
pub fn init(contents: []const Cell) @This() {
|
||||
return .{
|
||||
.contents = contents,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(this: *@This()) void {
|
||||
this.* = undefined;
|
||||
}
|
||||
|
||||
pub fn handle(this: *@This(), event: Event) ?Event {
|
||||
switch (event) {
|
||||
// store the received size
|
||||
.resize => |size| {
|
||||
this.size = size;
|
||||
this.require_render = true;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn render(this: *@This(), renderer: *Renderer) !void {
|
||||
if (!this.require_render) {
|
||||
return;
|
||||
}
|
||||
try renderer.clear(this.size);
|
||||
try renderer.render(this.size, this.contents);
|
||||
this.require_render = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user