Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e8fc818
upgrade to zig 0.15.2 with ghostty-vt dependency
remorses Dec 23, 2025
fda777b
fix(ci): update zig to 0.15.2 and skip macOS cross-compilation from L…
remorses Dec 23, 2025
0828eb1
fix: add macOS SDK for cross-compilation from Linux
remorses Dec 23, 2025
fc7907e
fix: add explicit refs to git URLs in build.zig.zon
remorses Dec 23, 2025
c24c7b0
fix: correct hash for macos_sdk dependency
remorses Dec 23, 2025
f6976e8
fix: use raw macOS SDK tarball instead of outdated zig package
remorses Dec 23, 2025
d4d4b44
fix(ci): only build lib, not native binaries for all platforms
remorses Dec 23, 2025
486901b
fix(ci): use macos-latest runners for cross-compilation
remorses Dec 23, 2025
b3d1e91
fix: build only native platform by default, add --all for all platforms
remorses Dec 23, 2025
6654359
fix: remove reference to non-existent ghostty-terminal.zig test file
remorses Dec 23, 2025
4c01c2d
fix: update zig tests for 0.15 API changes
remorses Dec 23, 2025
9e40564
ci: retry
remorses Dec 23, 2025
6186eef
fix: use arena allocator for ZON parser to avoid memory leaks in tests
remorses Dec 23, 2025
ee40287
ci: use macos-large runner for faster builds
remorses Dec 23, 2025
28f6554
ci: revert to macos-latest, skip native tests (hang issue)
remorses Dec 23, 2025
4f1ccbe
ci: trigger rebuild (transient network error)
remorses Dec 23, 2025
68739bd
fix: skip stdout writes in testing mode to prevent hanging tests
remorses Dec 23, 2025
7ffb039
Merge branch 'main' into zig15
remorses Dec 27, 2025
ab87708
Merge branch 'main' into zig15
kommander Jan 2, 2026
1635708
Merge branch 'main' into zig15
kommander Jan 2, 2026
4513365
Merge branch 'main' into zig15
kommander Jan 2, 2026
81ec988
document xcode dependency
kommander Jan 2, 2026
58391cd
run all tests
kommander Jan 2, 2026
7845ffc
Merge upstream/main into zig15, use gpa allocator
remorses Jan 3, 2026
26a5c46
remove ghostty dependency, restore ubuntu ci
remorses Jan 6, 2026
4cb17ae
merge upstream/main
remorses Jan 6, 2026
91374f0
fix toOwnedSlice api for zig 0.15
remorses Jan 6, 2026
afa9d38
remove -gnu suffix from linux targets to fix uucode build
remorses Jan 6, 2026
da26529
use macos-latest for ci (uucode crashes on linux with zig 0.15)
remorses Jan 6, 2026
95baf05
update uucode to latest main (84ceda85) to fix linux build
remorses Jan 6, 2026
594d95c
remove outdated macos-only cross-compilation comments
remorses Jan 6, 2026
5abd0d3
fix snapshot release
kommander Jan 6, 2026
5486ad3
build all for snapshot
kommander Jan 6, 2026
8ab4a25
update comment in readme
remorses Jan 6, 2026
e3125e8
Merge branch 'main' into zig15
remorses Jan 6, 2026
2e0344f
fix: make flaky performance and conceal tests more robust
remorses Jan 6, 2026
27a3729
fix: also fix native Zig wrap perf test
remorses Jan 6, 2026
5f770c2
migrate benchmarks
kommander Jan 6, 2026
c1f2f7f
fix leftover old api use
kommander Jan 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
jobs:
build:
name: Core - Build and Test
runs-on: ubuntu-latest
runs-on: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -21,7 +21,7 @@ jobs:
- name: Setup Zig
uses: goto-bus-stop/setup-zig@v2
with:
version: 0.14.1
version: 0.15.2

- name: Install dependencies
run: bun install
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/build-native.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
default: false

env:
ZIG_VERSION: 0.14.1
ZIG_VERSION: 0.15.2

jobs:
build-native:
Expand All @@ -39,7 +39,10 @@ jobs:
run: bun install

- name: Build packages (cross-compile for all platforms)
run: bun run build
run: |
cd packages/core
bun run build:native --all
bun run build:lib

- name: Verify build outputs
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-react.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Setup Zig
uses: goto-bus-stop/setup-zig@v2
with:
version: 0.14.1
version: 0.15.2

- name: Install dependencies
run: bun install
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-solid.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Setup Zig
uses: goto-bus-stop/setup-zig@v2
with:
version: 0.14.1
version: 0.15.2

- name: Install dependencies
run: bun install
Expand Down
11 changes: 8 additions & 3 deletions .github/workflows/npm-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Setup Zig
uses: goto-bus-stop/setup-zig@v2
with:
version: 0.14.1
version: 0.15.2

- name: Extract version from tag
id: extract_version
Expand All @@ -52,8 +52,13 @@ jobs:
- name: Prepare release versions
run: bun run prepare-release "${{ steps.version_scheme.outputs.version }}"

- name: Build packages
run: bun run build
- name: Build packages (cross-compile for all platforms)
run: |
cd packages/core
bun run build:native --all
bun run build:lib
cd ../solid && bun run build
cd ../react && bun run build
- name: Publish packages
run: bun run publish
Expand Down
2 changes: 1 addition & 1 deletion .zig-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.14.1
0.15.2
34 changes: 15 additions & 19 deletions packages/core/scripts/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const args = process.argv.slice(2)
const buildLib = args.find((arg) => arg === "--lib")
const buildNative = args.find((arg) => arg === "--native")
const isDev = args.includes("--dev")
const buildAll = args.includes("--all") // Build for all platforms

const variants: Variant[] = [
{ platform: "darwin", arch: "x64" },
Expand Down Expand Up @@ -78,16 +79,17 @@ if (missingRequired.length > 0) {
}

if (buildNative) {
console.log(`Building native ${isDev ? "dev" : "prod"} binaries...`)
console.log(`Building native ${isDev ? "dev" : "prod"} binaries${buildAll ? " for all platforms" : ""}...`)

const zigBuild: SpawnSyncReturns<Buffer> = spawnSync(
"zig",
["build", `-Doptimize=${isDev ? "Debug" : "ReleaseFast"}`],
{
cwd: join(rootDir, "src", "zig"),
stdio: "inherit",
},
)
const zigArgs = ["build", `-Doptimize=${isDev ? "Debug" : "ReleaseFast"}`]
if (buildAll) {
zigArgs.push("-Dall")
}

const zigBuild: SpawnSyncReturns<Buffer> = spawnSync("zig", zigArgs, {
cwd: join(rootDir, "src", "zig"),
stdio: "inherit",
})

if (zigBuild.error) {
console.error("Error: Zig is not installed or not in PATH")
Expand Down Expand Up @@ -124,16 +126,10 @@ if (buildNative) {
}

if (copiedFiles === 0) {
console.error(`Error: No dynamic libraries found for ${platform}-${arch} in ${libDir}`)
console.error(`Expected to find files like: libopentui.so, libopentui.dylib, opentui.dll`)
console.error(`Found files in ${libDir}:`)
if (existsSync(libDir)) {
const files = spawnSync("ls", ["-la", libDir], { stdio: "pipe" })
if (files.stdout) console.error(files.stdout.toString())
} else {
console.error("Directory does not exist")
}
process.exit(1)
// Skip platforms that weren't built
console.log(`Skipping ${platform}-${arch}: no libraries found`)
rmSync(nativeDir, { recursive: true, force: true })
continue
}

const indexTsContent = `const module = await import("./${libraryFileName}", { with: { type: "file" } })
Expand Down
14 changes: 12 additions & 2 deletions packages/core/src/renderables/Code.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1692,6 +1692,16 @@ test("CodeRenderable - streaming with conceal and drawUnstyledText=false should

currentRenderer.root.add(codeRenderable)

const waitForHighlightingCycle = async (timeout = 2000) => {
const start = Date.now()
await renderOnce()
await new Promise((resolve) => setTimeout(resolve, 10))
while (codeRenderable.isHighlighting && Date.now() - start < timeout) {
await new Promise((resolve) => setTimeout(resolve, 10))
}
await renderOnce()
}

// Use TestRecorder to capture frames
const { TestRecorder } = await import("../testing/test-recorder")
const recorder = new TestRecorder(currentRenderer)
Expand All @@ -1701,13 +1711,13 @@ test("CodeRenderable - streaming with conceal and drawUnstyledText=false should
recorder.rec()

// Wait for initial highlighting to complete
await new Promise((resolve) => setTimeout(resolve, 100))
await waitForHighlightingCycle()

// Now simulate streaming: add more content including fenced code block
codeRenderable.content = `# Example\n\nHere's some code:\n\n\`\`\`typescript\nconst x = 1;\n\`\`\``

// Wait for highlighting to process the update
await new Promise((resolve) => setTimeout(resolve, 150))
await waitForHighlightingCycle()

// Stop everything
currentRenderer.stop()
Expand Down
13 changes: 7 additions & 6 deletions packages/core/src/tests/wrap-resize-perf.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,16 @@ describe("Word wrap algorithmic complexity", () => {
const widths = [60, 70, 80, 90, 100]
const times: number[] = []

view.setWrapWidth(widths[0])
view.measureForDimensions(widths[0], 100)
// Warmup
view.setWrapWidth(50)
view.measureForDimensions(50, 100)

// Measure first (uncached) call for each width
for (const width of widths) {
view.setWrapWidth(width)
const time = measureMedian(() => {
view.measureForDimensions(width, 100)
})
times.push(time)
const start = performance.now()
view.measureForDimensions(width, 100)
times.push(performance.now() - start)
}

view.destroy()
Expand Down
17 changes: 10 additions & 7 deletions packages/core/src/zig/ansi.zig
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ pub const ANSI = struct {

// Direct writing to any writer - the most efficient option
pub fn moveToOutput(writer: anytype, x: u32, y: u32) AnsiError!void {
std.fmt.format(writer, "\x1b[{d};{d}H", .{ y, x }) catch return AnsiError.WriteFailed;
writer.print("\x1b[{d};{d}H", .{ y, x }) catch return AnsiError.WriteFailed;
}

pub fn fgColorOutput(writer: anytype, r: u8, g: u8, b: u8) AnsiError!void {
std.fmt.format(writer, "\x1b[38;2;{d};{d};{d}m", .{ r, g, b }) catch return AnsiError.WriteFailed;
writer.print("\x1b[38;2;{d};{d};{d}m", .{ r, g, b }) catch return AnsiError.WriteFailed;
}

pub fn bgColorOutput(writer: anytype, r: u8, g: u8, b: u8) AnsiError!void {
std.fmt.format(writer, "\x1b[48;2;{d};{d};{d}m", .{ r, g, b }) catch return AnsiError.WriteFailed;
writer.print("\x1b[48;2;{d};{d};{d}m", .{ r, g, b }) catch return AnsiError.WriteFailed;
}

// Text attribute constants
Expand All @@ -51,11 +51,11 @@ pub const ANSI = struct {
pub const cursorUnderlineBlink = "\x1b[3 q";

pub fn cursorColorOutputWriter(writer: anytype, r: u8, g: u8, b: u8) AnsiError!void {
std.fmt.format(writer, "\x1b]12;#{x:0>2}{x:0>2}{x:0>2}\x07", .{ r, g, b }) catch return AnsiError.WriteFailed;
writer.print("\x1b]12;#{x:0>2}{x:0>2}{x:0>2}\x07", .{ r, g, b }) catch return AnsiError.WriteFailed;
}

pub fn explicitWidthOutput(writer: anytype, width: u32, text: []const u8) AnsiError!void {
std.fmt.format(writer, "\x1b]66;w={d};{s}\x1b\\", .{ width, text }) catch return AnsiError.WriteFailed;
writer.print("\x1b]66;w={d};{s}\x1b\\", .{ width, text }) catch return AnsiError.WriteFailed;
}

pub const resetCursorColor = "\x1b]112\x07";
Expand Down Expand Up @@ -131,12 +131,15 @@ pub const ANSI = struct {
pub const setTerminalTitle = "\x1b]0;{s}\x07";

pub fn setTerminalTitleOutput(writer: anytype, title: []const u8) AnsiError!void {
std.fmt.format(writer, setTerminalTitle, .{title}) catch return AnsiError.WriteFailed;
writer.print(setTerminalTitle, .{title}) catch return AnsiError.WriteFailed;
}

pub fn makeRoomForRendererOutput(writer: anytype, height: u32) AnsiError!void {
if (height > 1) {
writer.writeByteNTimes('\n', height - 1) catch return AnsiError.WriteFailed;
var i: u32 = 0;
while (i < height - 1) : (i += 1) {
writer.writeByte('\n') catch return AnsiError.WriteFailed;
}
}
}
};
Expand Down
Loading
Loading