a73x

83a75672

build: wire ghostty-vt module

a73x   2026-04-08 05:57

Create src/vt.zig stub with API discovery doc-comments, update
src/main.zig to import vt, and wire b.lazyDependency("ghostty") +
module imports into build.zig. zig build and zig build test pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

diff --git a/build.zig b/build.zig
index b5f3c40..10e595b 100644
--- a/build.zig
+++ b/build.zig
@@ -4,11 +4,27 @@ pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // Lazy-fetch the ghostty dependency. On the first invocation this
    // materializes the package; subsequent builds use the local cache.
    const ghostty_dep = b.lazyDependency("ghostty", .{});

    // vt module — wraps ghostty-vt
    const vt_mod = b.createModule(.{
        .root_source_file = b.path("src/vt.zig"),
        .target = target,
        .optimize = optimize,
    });
    if (ghostty_dep) |dep| {
        vt_mod.addImport("ghostty-vt", dep.module("ghostty-vt"));
    }

    // Main executable module
    const exe_mod = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    exe_mod.addImport("vt", vt_mod);

    const exe = b.addExecutable(.{
        .name = "waystty",
@@ -25,13 +41,30 @@ pub fn build(b: *std.Build) void {
    run_step.dependOn(&run_cmd.step);

    const test_step = b.step("test", "Run unit tests");
    const test_mod = b.createModule(.{

    // Test main.zig (and transitively vt.zig via its import)
    const main_test_mod = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    const tests = b.addTest(.{
        .root_module = test_mod,
    main_test_mod.addImport("vt", vt_mod);
    const main_tests = b.addTest(.{
        .root_module = main_test_mod,
    });
    test_step.dependOn(&b.addRunArtifact(main_tests).step);

    // Test vt.zig directly (runs the ghostty-vt smoke test)
    const vt_test_mod = b.createModule(.{
        .root_source_file = b.path("src/vt.zig"),
        .target = target,
        .optimize = optimize,
    });
    if (ghostty_dep) |dep| {
        vt_test_mod.addImport("ghostty-vt", dep.module("ghostty-vt"));
    }
    const vt_tests = b.addTest(.{
        .root_module = vt_test_mod,
    });
    test_step.dependOn(&b.addRunArtifact(tests).step);
    test_step.dependOn(&b.addRunArtifact(vt_tests).step);
}
diff --git a/src/main.zig b/src/main.zig
index 2fda07a..233696c 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -1,5 +1,7 @@
const std = @import("std");
const vt = @import("vt");

pub fn main() !void {
    std.debug.print("waystty\n", .{});
    _ = vt;
}
diff --git a/src/vt.zig b/src/vt.zig
new file mode 100644
index 0000000..512d818
--- /dev/null
+++ b/src/vt.zig
@@ -0,0 +1,56 @@
//! Thin wrapper around the ghostty-vt Zig module.
//!
//! ## ghostty-vt API notes (as of ghostty-1.3.2-dev)
//!
//! ### Terminal lifecycle
//!   var t: Terminal = try .init(alloc, .{ .cols = N, .rows = N });
//!   defer t.deinit(alloc);
//!   try t.printString("raw text");          // writes plain text
//!   try t.resize(alloc, new_cols, new_rows);
//!   const s = try t.plainString(alloc);     // heap copy of visible text
//!   defer alloc.free(s);
//!
//! ### VT stream processing
//!   TerminalStream wraps a Terminal and processes raw VT byte sequences.
//!   Stream is the lower-level parser/dispatcher.
//!
//! ### RenderState (stateful renderer helper)
//!   var state: RenderState = .empty;
//!   defer state.deinit(alloc);
//!   try state.update(alloc, &terminal);
//!   // state.rows (CellCountInt), state.cols, state.colors, state.cursor
//!   // state.row_data: std.MultiArrayList(RenderState.Row)
//!   // state.dirty: RenderState.Dirty — caller should clear after use
//!
//! ### Input encoding
//!   ghostty_vt.input.encodeKey(buf, key_event, opts)  -> encode a KeyEvent
//!   ghostty_vt.input.encodeMouse(buf, event, opts)    -> encode a mouse event
//!   ghostty_vt.input.encodeFocus(buf, event)          -> encode focus in/out
//!   ghostty_vt.input.encodePaste(buf, data, opts)     -> bracketed-paste wrap
//!
//! ### Key types
//!   input.Key, input.KeyAction, input.KeyEvent, input.KeyMods
//!   input.KeyEncodeOptions
//!
//! ### Mouse types
//!   input.MouseAction, input.MouseButton, input.MouseEncodeOptions,
//!   input.MouseEncodeEvent
//!
//! ### Namespaces re-exported at top level
//!   apc, dcs, osc, point, color, device_status, formatter, highlight,
//!   kitty, modes, page, parse_table, search, sgr, size, x11_color, sys
//!
//! ### Sizes
//!   size.CellCountInt — integer type for column/row counts
//!
//! ### Cursor
//!   Screen.Cursor / Cursor — position and style within a Screen
//!   CursorStyle, CursorStyleReq

const std = @import("std");
const ghostty_vt = @import("ghostty-vt");

test "ghostty-vt module imports" {
    // Smoke test — just reference the module so the import is verified
    _ = ghostty_vt;
}