nandi/jolt-nativepublic Fork 0
7289263310c2fffb5ba5907381ff86a8cfef49e6
Commits
Clone
git clone https://git.rickub.com/nandi/jolt-native.git
git clone ssh://git@rickub.com/nandi/jolt-native.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

README.md · 83 lines · 3.5 KBmarkdown Blame HistoryRaw
Paint the tree ABI a third way: Zig and dvui 7289263 nandi 9d ago1# jolt-zvui
2
3The retained-tree C ABI, in Zig, painted by [dvui](https://github.com/david-vanderson/dvui).
4
5`crates/jolt-vidya` exports this shape on egui and `crates/jolt-tui` exports it
6again over terminal cells. This is a third painter under the same shape: a tree
7the caller mutates between frames, one call that walks it, and a queue of what
8the person did. Nothing in the tree knows what paints it, which is the property
9that makes a third backend possible at all.
10
11The prefix is `zvui_` and the object is `libjoltzvui.so`, for the same reason
12jolt-tui's are `tui_` and `libjolttui.so`: a consumer names one object in
13`:jolt/native` and binds one set of symbols.
14
15```
16src/tree.zig nodes, props, children, the event queue — no dvui in it
17src/paint.zig one walk per frame, in dvui widgets
18src/lib.zig the 32 exported symbols
19include/zvui.h the header a C caller (or a jolt.ffi/defcfn) reads
20demo.c a caller: builds a tree, paints it, drains events
21```
22
23## Building
24
25Zig 0.16 and nothing else installed — dvui, SDL3, FreeType and tree-sitter are
26fetched and built by the Zig package manager, at the revs `build.zig.zon` pins.
27
28```bash
29zig build --release # zig-out/lib/libjoltzvui.so
30zig build test # the tree, without a window
31```
32
33`--release` rather than `-Doptimize=`: this library sets a preferred optimize
34mode (ReleaseSafe), and Zig spells that choice `--release`.
35
36## The demo
37
38```bash
39gcc demo.c ./zig-out/lib/libjoltzvui.so -Wl,-rpath,'$ORIGIN/zig-out/lib' -o demo
40./demo # a window
41./demo --dump # the tree on stdout, no window
42./demo --frames 3 # paint three frames and leave
43```
44
45## The vocabulary
46
47Tags: `window` `box` `hbox` `vbox` `page` `card` `frame` `scroll` `label`
48`title` `dim-label` `button` `checkbox` `entry` `separator` `spacer`/`gap`
49`progress`. An unknown tag is a container rather than an error, so a tree
50written against a richer painter still shows its contents here.
51
52Props: `text` `label` `orientation` `spacing` `margin` `align` `max-width`
53`width-request` `placeholder` `value` `active` `sensitive` `kind` `multiline`
54`size` `fill-height`.
55
56Events: `click` `change` `toggled` `activate`.
57
58## Two things worth knowing
59
60**Ids come back; identities do not.** The free list hands a node id out again
61after a free — but widget identity is `(generation, index)`, so a node freed and
62reallocated in the same frame does not inherit the cursor, scroll position or
63animation of the node that used to live in that slot. That is the bug class
64frq's `deps.edn` describes from the reconciler's side, closed here at the
65backend rather than only upstream.
66
67**Zig cannot keep jolt-abi's unwinding rule.** There is no `catch_unwind`, so
68`jolt_abi::guard`'s bargain — a panicking decoder is a black tile rather than a
69dead process — is not available. A Zig panic aborts. The answer here is to not
70panic: every entry point is total, a bad node id is a miss rather than an index,
71and allocation failure answers the fallback a caught panic would have. The build
72is ReleaseSafe by default for the same reason — a trap inside this library beats
73quiet corruption of the caller's heap.
74
75The other two rules are kept exactly. Strings out live in one scratch slot until
76the next string-returning call, and nothing here calls back: events are queued
77and polled.
78
79## Not done
80
81No `page`/`card` push-pop immediate API (the tree is the only interface), no
82images, avatars, video frames, clipboard, file picking, font loading, or Android
83entry points. `jolt-vidya` exports 57 symbols; this exports 32.