[READ-ONLY] Mirror of https://github.com/bombshell-dev/tty. Platform independent 2D layout engine for terminal applications based on Clay
5

Configure Feed

Select the types of activity you want to include in your feed.

ref(wasm): split layout and input entrypoints

authored by

Nate Moore and committed by
Nate Moore
(Jul 1, 2026, 9:48 PM EDT) c9ed97a2 35ce6a0d

+72 -35
+4 -2
.gitignore
··· 1 1 /.agent-shell/ 2 - /clayterm.wasm 3 - /wasm.ts 2 + /clayterm-layout.wasm 3 + /clayterm-input.wasm 4 + /wasm-layout.ts 5 + /wasm-input.ts 4 6 /build/ 5 7 /node_modules/
+32 -19
Makefile
··· 1 1 CC = clang 2 - TARGET = clayterm.wasm 3 - SRC = src/module.c 4 2 5 3 CFLAGS = --target=wasm32 -nostdlib -O2 \ 6 4 -ffunction-sections -fdata-sections \ ··· 8 6 -DCLAY_IMPLEMENTATION -DCLAY_WASM \ 9 7 -Isrc -I. 10 8 11 - EXPORTS = \ 9 + LDFLAGS_COMMON = -Wl,--no-entry \ 10 + -Wl,--import-memory \ 11 + -Wl,--stack-first \ 12 + -Wl,--strip-all \ 13 + -Wl,--gc-sections 14 + 15 + LAYOUT_EXPORTS = \ 12 16 -Wl,--export=__heap_base \ 13 17 -Wl,--export=clayterm_size \ 14 18 -Wl,--export=init \ ··· 25 29 -Wl,--export=error_count \ 26 30 -Wl,--export=error_type \ 27 31 -Wl,--export=error_message_length \ 28 - -Wl,--export=error_message_ptr \ 32 + -Wl,--export=error_message_ptr 33 + 34 + INPUT_EXPORTS = \ 35 + -Wl,--export=__heap_base \ 29 36 -Wl,--export=input_size \ 30 37 -Wl,--export=input_init \ 31 38 -Wl,--export=input_scan \ ··· 33 40 -Wl,--export=input_event \ 34 41 -Wl,--export=input_delay 35 42 36 - LDFLAGS = -Wl,--no-entry \ 37 - -Wl,--import-memory \ 38 - -Wl,--stack-first \ 39 - -Wl,--strip-all \ 40 - -Wl,--gc-sections \ 41 - -Wl,--undefined=Clay__MeasureText \ 42 - -Wl,--undefined=Clay__QueryScrollOffset \ 43 - $(EXPORTS) 43 + LAYOUT_LDFLAGS = $(LDFLAGS_COMMON) \ 44 + -Wl,--undefined=Clay__MeasureText \ 45 + -Wl,--undefined=Clay__QueryScrollOffset \ 46 + $(LAYOUT_EXPORTS) 44 47 45 - all: $(TARGET) wasm.ts 46 - @echo "Built $(TARGET) ($$(wc -c < $(TARGET)) bytes raw, $$(gzip -c $(TARGET) | wc -c) bytes gzip)" 48 + INPUT_LDFLAGS = $(LDFLAGS_COMMON) \ 49 + $(INPUT_EXPORTS) 47 50 48 51 DEPS = $(wildcard src/*.c src/*.h) 49 52 50 - $(TARGET): $(DEPS) 51 - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SRC) 53 + all: clayterm-layout.wasm clayterm-input.wasm wasm-layout.ts wasm-input.ts 54 + @echo "Built clayterm-layout.wasm ($$(wc -c < clayterm-layout.wasm) bytes raw, $$(gzip -c clayterm-layout.wasm | wc -c) bytes gzip)" 55 + @echo "Built clayterm-input.wasm ($$(wc -c < clayterm-input.wasm) bytes raw, $$(gzip -c clayterm-input.wasm | wc -c) bytes gzip)" 56 + 57 + clayterm-layout.wasm: $(DEPS) 58 + $(CC) $(CFLAGS) $(LAYOUT_LDFLAGS) -o $@ src/module-layout.c 59 + 60 + clayterm-input.wasm: $(DEPS) 61 + $(CC) $(filter-out -DCLAY_IMPLEMENTATION -DCLAY_WASM, $(CFLAGS)) $(INPUT_LDFLAGS) -o $@ src/module-input.c 52 62 53 - wasm.ts: $(TARGET) 54 - deno run --allow-read --allow-write tasks/bundle-wasm.ts 63 + wasm-layout.ts: clayterm-layout.wasm 64 + deno run --allow-read --allow-write tasks/bundle-wasm.ts clayterm-layout.wasm wasm-layout.ts 65 + 66 + wasm-input.ts: clayterm-input.wasm 67 + deno run --allow-read --allow-write tasks/bundle-wasm.ts clayterm-input.wasm wasm-input.ts 55 68 56 69 clean: 57 - rm -f $(TARGET) wasm.ts 70 + rm -f clayterm.wasm clayterm-layout.wasm clayterm-input.wasm wasm.ts wasm-layout.ts wasm-input.ts 58 71 59 72 .PHONY: all clean
+2
deno.json
··· 20 20 }, 21 21 "exports": { 22 22 ".": "./mod.ts", 23 + "./layout": "./layout.ts", 24 + "./input": "./input.ts", 23 25 "./validate": "./validate.ts" 24 26 }, 25 27 "nodeModulesDir": "auto",
+1 -9
input-native.ts
··· 169 169 delay(st: number): number; 170 170 } 171 171 172 - import { compiled } from "./wasm.ts"; 172 + import { compiled } from "./wasm-input.ts"; 173 173 174 174 export async function createInputNative( 175 175 escLatency: number, ··· 178 178 179 179 let instance = await WebAssembly.instantiate(compiled, { 180 180 env: { memory }, 181 - clay: { 182 - measureTextFunction() {}, 183 - queryScrollOffsetFunction(ret: number) { 184 - let v = new DataView(memory.buffer); 185 - v.setFloat32(ret, 0, true); 186 - v.setFloat32(ret + 4, 0, true); 187 - }, 188 - }, 189 181 }); 190 182 191 183 let exports = instance.exports as unknown as {
+4
layout.ts
··· 1 + export * from "./ops.ts"; 2 + export * from "./term.ts"; 3 + export * from "./settings.ts"; 4 + export * from "./termcodes.ts";
+6
src/module-input.c
··· 1 + /* module-input.c — input-only compilation unit, no Clay layout engine */ 2 + 3 + #include "mem.c" 4 + #include "utf8.c" 5 + #include "trie.c" 6 + #include "input.c"
+11
src/module-layout.c
··· 1 + /* module-layout.c — layout-only compilation unit, no input parser */ 2 + 3 + #include "../clay/clay.h" 4 + 5 + #include "mem.c" 6 + #include "buffer.c" 7 + #include "cell.c" 8 + #include "utf8.c" 9 + #include "wcwidth.c" 10 + #include "clayterm.c" 11 + #include "transitions.c"
+6 -1
tasks/build-npm.ts
··· 10 10 } 11 11 12 12 await build({ 13 - entryPoints: ["./mod.ts"], 13 + entryPoints: [ 14 + "./mod.ts", 15 + { name: "./layout", path: "./layout.ts" }, 16 + { name: "./input", path: "./input.ts" }, 17 + { name: "./validate", path: "./validate.ts" }, 18 + ], 14 19 outDir, 15 20 shims: { 16 21 deno: false,
+5 -3
tasks/bundle-wasm.ts
··· 27 27 return out.join(""); 28 28 } 29 29 30 - const wasm = await Deno.readFile("clayterm.wasm"); 30 + const [input = "clayterm.wasm", output = "wasm.ts"] = Deno.args; 31 + 32 + const wasm = await Deno.readFile(input); 31 33 32 34 const compressed = new Uint8Array( 33 35 brotliCompressSync(wasm, { ··· 50 52 export const compiled=await WebAssembly.compile(new Uint8Array(brotliDecompressSync(compressed))); 51 53 `; 52 54 53 - await Deno.writeTextFile("wasm.ts", source); 55 + await Deno.writeTextFile(output, source); 54 56 console.log( 55 - `wrote wasm.ts (${wasm.length} → ${compressed.byteLength} bytes compressed, ${z85.length} bytes z85, ${ 57 + `wrote ${output} (${wasm.length} → ${compressed.byteLength} bytes compressed, ${z85.length} bytes z85, ${ 56 58 Math.round(z85.length / wasm.length * 100) 57 59 }%)`, 58 60 );
+1 -1
term-native.ts
··· 48 48 errorMessage(ct: number, index: number): string; 49 49 } 50 50 51 - import { compiled } from "./wasm.ts"; 51 + import { compiled } from "./wasm-layout.ts"; 52 52 53 53 export async function createTermNative( 54 54 w: number,