[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
(Jun 1, 2026, 2:48 PM -0500) 6bef3f5d ebaf397f

+72 -36
+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 \ ··· 24 28 -Wl,--export=error_count \ 25 29 -Wl,--export=error_type \ 26 30 -Wl,--export=error_message_length \ 27 - -Wl,--export=error_message_ptr \ 31 + -Wl,--export=error_message_ptr 32 + 33 + INPUT_EXPORTS = \ 34 + -Wl,--export=__heap_base \ 28 35 -Wl,--export=input_size \ 29 36 -Wl,--export=input_init \ 30 37 -Wl,--export=input_scan \ ··· 32 39 -Wl,--export=input_event \ 33 40 -Wl,--export=input_delay 34 41 35 - LDFLAGS = -Wl,--no-entry \ 36 - -Wl,--import-memory \ 37 - -Wl,--stack-first \ 38 - -Wl,--strip-all \ 39 - -Wl,--gc-sections \ 40 - -Wl,--undefined=Clay__MeasureText \ 41 - -Wl,--undefined=Clay__QueryScrollOffset \ 42 - $(EXPORTS) 42 + LAYOUT_LDFLAGS = $(LDFLAGS_COMMON) \ 43 + -Wl,--undefined=Clay__MeasureText \ 44 + -Wl,--undefined=Clay__QueryScrollOffset \ 45 + $(LAYOUT_EXPORTS) 43 46 44 - all: $(TARGET) wasm.ts 45 - @echo "Built $(TARGET) ($$(wc -c < $(TARGET)) bytes raw, $$(gzip -c $(TARGET) | wc -c) bytes gzip)" 47 + INPUT_LDFLAGS = $(LDFLAGS_COMMON) \ 48 + $(INPUT_EXPORTS) 46 49 47 50 DEPS = $(wildcard src/*.c src/*.h) 48 51 49 - $(TARGET): $(DEPS) 50 - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SRC) 52 + all: clayterm-layout.wasm clayterm-input.wasm wasm-layout.ts wasm-input.ts 53 + @echo "Built clayterm-layout.wasm ($$(wc -c < clayterm-layout.wasm) bytes raw, $$(gzip -c clayterm-layout.wasm | wc -c) bytes gzip)" 54 + @echo "Built clayterm-input.wasm ($$(wc -c < clayterm-input.wasm) bytes raw, $$(gzip -c clayterm-input.wasm | wc -c) bytes gzip)" 55 + 56 + clayterm-layout.wasm: $(DEPS) 57 + $(CC) $(CFLAGS) $(LAYOUT_LDFLAGS) -o $@ src/module-layout.c 58 + 59 + clayterm-input.wasm: $(DEPS) 60 + $(CC) $(filter-out -DCLAY_IMPLEMENTATION -DCLAY_WASM, $(CFLAGS)) $(INPUT_LDFLAGS) -o $@ src/module-input.c 51 61 52 - wasm.ts: $(TARGET) 53 - deno run --allow-read --allow-write tasks/bundle-wasm.ts 62 + wasm-layout.ts: clayterm-layout.wasm 63 + deno run --allow-read --allow-write tasks/bundle-wasm.ts clayterm-layout.wasm wasm-layout.ts 64 + 65 + wasm-input.ts: clayterm-input.wasm 66 + deno run --allow-read --allow-write tasks/bundle-wasm.ts clayterm-input.wasm wasm-input.ts 54 67 55 68 clean: 56 - rm -f $(TARGET) wasm.ts 69 + rm -f clayterm.wasm clayterm-layout.wasm clayterm-input.wasm wasm.ts wasm-layout.ts wasm-input.ts 57 70 58 71 .PHONY: all clean
+3 -1
deno.json
··· 21 21 }, 22 22 "exports": { 23 23 ".": "./mod.ts", 24 + "./layout": "./layout.ts", 25 + "./input": "./input.ts", 24 26 "./validate": "./validate.ts" 25 27 }, 26 28 "publish": { 27 29 "include": ["*.ts"], 28 - "exclude": ["!wasm.ts"] 30 + "exclude": ["!wasm-layout.ts", "!wasm-input.ts"] 29 31 }, 30 32 "nodeModulesDir": "auto", 31 33 "fmt": {
+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"
+10
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"
+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
··· 31 31 errorMessage(ct: number, index: number): string; 32 32 } 33 33 34 - import { compiled } from "./wasm.ts"; 34 + import { compiled } from "./wasm-layout.ts"; 35 35 36 36 export async function createTermNative( 37 37 w: number,