Repository navigation
refactor(codegen): extract preview.zig from main_zig.zig (part of #183) - #201
Conversation
The biggest single extraction from main_zig.zig: ~1200 lines of
preview-mode codegen — the PREVIEW_* literal constants (plus the
WASM_PANIC_WORKAROUND companion that lives in the same section) for
the raylib desktop / sokol GL / sokol D3D11 / sokol Metal backend
variants. Moved to src/codegen/preview.zig (1202 lines).
main_zig.zig drops from 3817 -> 2660 lines. The 25 string-literal
constants now live in one module with `pub const` declarations and
are re-exported from main_zig.zig so every existing reference in
generateMainZigFromTemplate (the `std.mem.concat` chains, the
`PREVIEW_INPUT_DISPATCH` ternary, etc.) stays byte-identical.
The plan flagged this cut as medium risk because of the 1200 lines
of inline string literals. Verified:
- String-literal bodies moved verbatim (diff of the moved block
against the pre-extraction block shows only the `pub ` prefix
on the 25 `const` lines).
- Bit-identical generated output across all 8 working bundled
examples (sokol_imgui needs the labelle-imgui sibling, soft-
fails per scripts/gen_all_examples.sh's contract). 110 generated
files byte-identical; the only diffs are the 9 documented
flow_catalog.json `generated_at` timestamp drifts.
- `zig build test` -> 506/510 passed, 4 skipped (matches base).
No string-literal edits. No logic changes. No `--force`-eligible
moves anywhere. Pure move + re-export shim.
Refs: #183
Builds on: #195
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request initiates a refactoring plan to split the large src/main_zig.zig file into smaller, more maintainable submodules. It introduces a detailed refactor plan document, a verification script to ensure bit-identical output, and extracts identifier helpers, preview-mode codegen templates, and discovery/scanning helpers into separate files under src/codegen/. The reviewer feedback focuses on improving code readability and idiomatic style by utilizing standard library functions for ASCII checks, and adhering to CLI best practices by replacing debug-specific printing with standard logging facilities.
| pub fn isValidZigIdentifier(name: []const u8) bool { | ||
| if (name.len == 0) return false; | ||
| const first = name[0]; | ||
| const first_ok = (first >= 'A' and first <= 'Z') or (first >= 'a' and first <= 'z') or first == '_'; | ||
| if (!first_ok) return false; | ||
| for (name[1..]) |c| { | ||
| const ok = (c >= 'A' and c <= 'Z') or (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9') or c == '_'; | ||
| if (!ok) return false; | ||
| } | ||
| return true; | ||
| } |
There was a problem hiding this comment.
Use standard library functions std.ascii.isAlphabetic and std.ascii.isAlphanumeric instead of manual range checks to improve readability and idiomatic style.
pub fn isValidZigIdentifier(name: []const u8) bool {
if (name.len == 0) return false;
const first = name[0];
const first_ok = std.ascii.isAlphabetic(first) or first == '_';
if (!first_ok) return false;
for (name[1..]) |c| {
const ok = std.ascii.isAlphanumeric(c) or c == '_';
if (!ok) return false;
}
return true;
}
| const append = struct { | ||
| fn f(b: *[256]u8, idx: *usize, bytes: []const u8) void { | ||
| if (idx.* + bytes.len > b.len) { | ||
| std.debug.print("labelle: path too long for identifier (max {d} chars): too many escaped chars\n", .{b.len}); | ||
| @panic("path exceeds identifier buffer size"); | ||
| } |
There was a problem hiding this comment.
In CLI tools, avoid using debug-specific print functions like std.debug.print for user-facing errors or warnings. Instead, use standard logging facilities like std.log.err or write directly to stderr.
fn f(b: *[256]u8, idx: *usize, bytes: []const u8) void {
if (idx.* + bytes.len > b.len) {
std.log.err("labelle: path too long for identifier (max {d} chars): too many escaped chars", .{b.len});
@panic("path exceeds identifier buffer size");
}
@memcpy(b[idx.*..][0..bytes.len], bytes);
References
- In CLI tools, use standard logging facilities (e.g.
std.log.warn) or write tostderrfor user-facing warnings, rather than using debug-specific print functions (e.g.std.debug.print).
PR SummaryLow Risk Overview
No edits to template bodies beyond making them Reviewed by Cursor Bugbot for commit 03d553f. Bugbot is set up for automated code reviews on this repo. Configure here. |
Summary
The biggest single extraction from
src/main_zig.zigso far: the~1200-line preview-mode codegen block. Moved to
src/codegen/preview.zig(1202 lines) and re-exported as
pub consts frommain_zig.zigsoevery
generateMainZigFromTemplatecall site (thestd.mem.concatchains, the
PREVIEW_INPUT_DISPATCHternary, etc.) stays byte-identical.main_zig.zigdrops 3817 -> 2660 lines.What moved
25 module-scope string-literal constants for the preview-mode runtime —
raylib desktop + sokol GL + sokol D3D11 + sokol Metal backend variants.
Names (all
PREVIEW_*plus the WASM panic workaround living in thesame section per its docstring's note about
PREVIEW_INIT_CALLBACK):WASM_PANIC_WORKAROUND,PREVIEW_HELPERS,PREVIEW_READBACK_HELPERS,PREVIEW_LOOP_SETUP,PREVIEW_READBACK_SETUP,PREVIEW_HEARTBEAT_LOOP,PREVIEW_INPUT_DISPATCH,PREVIEW_INPUT_DISPATCH_STUB,PREVIEW_READBACK_LOOP,PREVIEW_INIT_CALLBACK,PREVIEW_CLEANUP_CALLBACK,PREVIEW_HEARTBEAT_CALLBACK,PREVIEW_READBACK_HELPERS_SOKOL,PREVIEW_READBACK_INIT_SOKOL,PREVIEW_READBACK_FRAME_SOKOL,PREVIEW_READBACK_CLEANUP_SOKOL,PREVIEW_READBACK_HELPERS_SOKOL_D3D11,PREVIEW_READBACK_HELPERS_METAL_SOKOL,PREVIEW_READBACK_INIT_SOKOL_D3D11,PREVIEW_READBACK_INIT_METAL_SOKOL,PREVIEW_READBACK_FRAME_SOKOL_D3D11,PREVIEW_PRE_RENDER_METAL_SOKOL,PREVIEW_READBACK_FRAME_METAL_SOKOL,PREVIEW_READBACK_CLEANUP_SOKOL_D3D11,PREVIEW_READBACK_CLEANUP_METAL_SOKOL.No wiring helper functions lived in the section the plan pointed at on
the current branch — only the constants. The 3 backend-variant
orchestration (loop / callback / readback) still lives in the
generateMainZigFromTemplatebody and will move with thelifecycle/*.zigandmain_template.zigcuts later in the plan.Risk mitigation
The plan flagged this cut as medium risk because of the 1200 lines
of inline string literals — a single whitespace edit would surface as a
generated-output diff. Verified:
block against the pre-extraction block shows zero changes (the only
textual edit is the
pubprefix added to the 25constlines sothey can be re-exported).
scripts/gen_all_examples.shgreen on all 8 working bundled examples (sokol_imgui requires the
labelle-imgui sibling repo and soft-fails per the script's contract).
110 generated files byte-identical; the only diffs are the 9
documented
flow_catalog.jsongenerated_attimestamp drifts.main.zigfiles byte-identical before vs after.zig build test: 506/510 passed, 4 skipped — matches base.No string-literal edits. No logic changes. Pure move + re-export shim.
Base-branch dependency
Stacks on top of
refactor/183-extract-next(PR #195). Once thatlands, this PR's base should retarget to
main.Test plan
zig buildcleanzig build test(506/510 passed, 4 skipped)scripts/gen_all_examples.shproduces bit-identical generatedoutput (excluding the documented
flow_catalog.jsontimestamp)