diff --git a/build.zig b/build.zig index 5820340..f733ea9 100644 --- a/build.zig +++ b/build.zig @@ -22,9 +22,13 @@ pub fn build(b: *std.Build) void { }; const example = b.option(Examples, "example", "Example to build and/or run. (default: all)") orelse .all; + const debug_rendering = b.option(bool, "debug", "Enable debug rendering. Highlight origin's, size's, padding's, gap's, etc. (default: false)") orelse false; + // NOTE do not support debug rendering in release builds + if (debug_rendering == true and optimize != .Debug) @panic("Cannot enable debug rendering in non-debug builds."); const options = b.addOptions(); - options.addOption(Examples, "example", example); + options.addOption(bool, "debug", debug_rendering); + const options_module = options.createModule(); // dependencies const zg = b.dependency("zg", .{ @@ -39,146 +43,40 @@ pub fn build(b: *std.Build) void { .optimize = optimize, }); lib.addImport("code_point", zg.module("code_point")); + lib.addImport("build_options", options_module); //--- Examples --- - - // demo: - const demo = b.addExecutable(.{ - .name = "demo", - .root_source_file = b.path("examples/demo.zig"), - .target = target, - .optimize = optimize, - }); - demo.root_module.addImport("zterm", lib); - - // elements: - const button = b.addExecutable(.{ - .name = "button", - .root_source_file = b.path("examples/elements/button.zig"), - .target = target, - .optimize = optimize, - }); - button.root_module.addImport("zterm", lib); - - const input = b.addExecutable(.{ - .name = "input", - .root_source_file = b.path("examples/elements/input.zig"), - .target = target, - .optimize = optimize, - }); - input.root_module.addImport("zterm", lib); - - const scrollable = b.addExecutable(.{ - .name = "scrollable", - .root_source_file = b.path("examples/elements/scrollable.zig"), - .target = target, - .optimize = optimize, - }); - scrollable.root_module.addImport("zterm", lib); - - // layouts: - const vertical = b.addExecutable(.{ - .name = "vertical", - .root_source_file = b.path("examples/layouts/vertical.zig"), - .target = target, - .optimize = optimize, - }); - vertical.root_module.addImport("zterm", lib); - - const horizontal = b.addExecutable(.{ - .name = "horizontal", - .root_source_file = b.path("examples/layouts/horizontal.zig"), - .target = target, - .optimize = optimize, - }); - horizontal.root_module.addImport("zterm", lib); - - const grid = b.addExecutable(.{ - .name = "grid", - .root_source_file = b.path("examples/layouts/grid.zig"), - .target = target, - .optimize = optimize, - }); - grid.root_module.addImport("zterm", lib); - - const mixed = b.addExecutable(.{ - .name = "mixed", - .root_source_file = b.path("examples/layouts/mixed.zig"), - .target = target, - .optimize = optimize, - }); - mixed.root_module.addImport("zterm", lib); - - // styles: - const palette = b.addExecutable(.{ - .name = "palette", - .root_source_file = b.path("examples/styles/palette.zig"), - .target = target, - .optimize = optimize, - }); - palette.root_module.addImport("zterm", lib); - - const text = b.addExecutable(.{ - .name = "text", - .root_source_file = b.path("examples/styles/text.zig"), - .target = target, - .optimize = optimize, - }); - text.root_module.addImport("zterm", lib); - - // error handling: - const errors = b.addExecutable(.{ - .name = "errors", - .root_source_file = b.path("examples/errors.zig"), - .target = target, - .optimize = optimize, - }); - errors.root_module.addImport("zterm", lib); - - // mapping of user selected example to compile step - const exe = switch (example) { - .demo => demo, - // elements: - .button => button, - .input => input, - .scrollable => scrollable, - // layouts: - .vertical => vertical, - .horizontal => horizontal, - .grid => grid, - .mixed => mixed, - // styles: - .text => text, - .palette => palette, - // error handling: - .errors => errors, - else => blk: { - b.installArtifact(button); - b.installArtifact(input); - b.installArtifact(scrollable); - b.installArtifact(vertical); - b.installArtifact(horizontal); - b.installArtifact(grid); - b.installArtifact(mixed); - b.installArtifact(text); - b.installArtifact(palette); - b.installArtifact(errors); - break :blk demo; - }, - }; - b.installArtifact(exe); - - // zig build run - const run_cmd = b.addRunArtifact(exe); - run_cmd.step.dependOn(b.getInstallStep()); - // Allow additional arguments, 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); + const examples = std.meta.fields(Examples); + inline for (examples) |e| { + if (@as(Examples, @enumFromInt(e.value)) == .all) continue; // skip `.all` entry + const demo = b.addExecutable(.{ + .name = e.name, + .root_source_file = b.path(switch (@as(Examples, @enumFromInt(e.value))) { + .demo => "examples/demo.zig", + // elements: + .button => "examples/elements/button.zig", + .input => "examples/elements/input.zig", + .scrollable => "examples/elements/scrollable.zig", + // layouts: + .vertical => "examples/layouts/vertical.zig", + .horizontal => "examples/layouts/horizontal.zig", + .grid => "examples/layouts/grid.zig", + .mixed => "examples/layouts/mixed.zig", + // styles: + .text => "examples/styles/text.zig", + .palette => "examples/styles/palette.zig", + // error handling + .errors => "examples/errors.zig", + .all => unreachable, // should never happen + }), + .target = target, + .optimize = optimize, + }); + // import dependencies + demo.root_module.addImport("zterm", lib); + // mapping of user selected example to compile step + if (@intFromEnum(example) == e.value or example == .all) b.installArtifact(demo); + } // zig build test const lib_unit_tests = b.addTest(.{ @@ -188,6 +86,7 @@ pub fn build(b: *std.Build) void { }); lib_unit_tests.root_module.addImport("code_point", zg.module("code_point")); lib_unit_tests.root_module.addImport("DisplayWidth", zg.module("DisplayWidth")); + lib_unit_tests.root_module.addImport("build_options", options_module); const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests); diff --git a/src/container.zig b/src/container.zig index c4ea65e..05abd46 100644 --- a/src/container.zig +++ b/src/container.zig @@ -145,6 +145,13 @@ pub const Rectangle = packed struct { cells[(row * size.x) + col].style.bg = this.fill; } } + + // DEBUG render corresponding beginning of the rectangle for this `Container` *red* + if (comptime build_options.debug) { + cells[0].style.fg = .red; + cells[0].style.bg = .black; + cells[0].cp = 'r'; // 'r' for *rectangle* + } } test "fill color overwrite parent fill" { @@ -349,8 +356,11 @@ pub const Layout = packed struct { } // DEBUG render corresponding beginning of the separator for this `Container` *red* - // cells[anchor].style.fg = .red; - // cells[anchor].style.bg = .red; + if (comptime build_options.debug) { + cells[anchor].style.fg = .red; + cells[anchor].style.bg = .black; + cells[anchor].cp = 's'; // 's' for *separator* + } } } } @@ -875,9 +885,21 @@ pub fn Container(comptime Event: type) type { try this.element.content(cells, this.size); - // DEBUG render corresponding top left corner of this `Container` *red* - // cells[0].style.fg = .red; - // cells[0].style.bg = .red; + // DEBUG render corresponding corners (except top left) of this `Container` *red* + if (comptime build_options.debug) { + // top right + cells[this.size.x -| 1].style.fg = .red; + cells[this.size.x -| 1].style.bg = .black; + cells[this.size.x -| 1].cp = 'c'; // 'c' for *container* + // bottom left + cells[this.size.x * (this.size.y -| 1)].style.fg = .red; + cells[this.size.x * (this.size.y -| 1)].style.bg = .black; + cells[this.size.x * (this.size.y -| 1)].cp = 'c'; // 'c' for *container* + // bottom right + cells[this.size.x * this.size.y -| 1].style.fg = .red; + cells[this.size.x * this.size.y -| 1].style.bg = .black; + cells[this.size.x * this.size.y -| 1].cp = 'c'; // 'c' for *container* + } return cells; } @@ -889,6 +911,7 @@ const log = std.log.scoped(.container); const std = @import("std"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; +const build_options = @import("build_options"); const input = @import("input.zig"); const isTaggedUnion = @import("event.zig").isTaggedUnion; const Cell = @import("cell.zig"); diff --git a/src/element.zig b/src/element.zig index 665b614..2f8ece7 100644 --- a/src/element.zig +++ b/src/element.zig @@ -52,8 +52,17 @@ pub fn Element(Event: type) type { /// Otherwise user specific errors should be caught using the `handle` /// function before the rendering of the `Container` happens. pub inline fn content(this: @This(), cells: []Cell, size: Point) !void { - if (this.vtable.content) |content_fn| + if (this.vtable.content) |content_fn| { try content_fn(this.ptr, cells, size); + + // DEBUG render corresponding top left corner of this `Element` *red* + // - only rendered if the corresponding associated element renders contents into the `Container` + if (comptime build_options.debug) { + cells[0].style.fg = .red; + cells[0].style.bg = .black; + cells[0].cp = 'e'; // 'e' for *element* + } + } } }; } @@ -260,6 +269,7 @@ pub fn Scrollable(Event: type) type { const std = @import("std"); const assert = std.debug.assert; +const build_options = @import("build_options"); const input = @import("input.zig"); const Container = @import("container.zig").Container; const Cell = @import("cell.zig");