Skip to content

feat(tui): colored HTTP/JSON TUI (Phases 1-4) + interpolated-string heap fix#132

Merged
MelbourneDeveloper merged 18 commits into
mainfrom
feature/tui-phase5
Jun 1, 2026
Merged

feat(tui): colored HTTP/JSON TUI (Phases 1-4) + interpolated-string heap fix#132
MelbourneDeveloper merged 18 commits into
mainfrom
feature/tui-phase5

Conversation

@MelbourneDeveloper
Copy link
Copy Markdown
Owner

Colored HTTP/JSON TUI — Phases 1–4 of docs/plans/tui-http-app.md

Lands the "write a colored TUI in Osprey that calls an HTTP API and renders the
response" capability, plus the core codegen fix that makes string-wrapper
helpers usable. Supersedes the closed #131 (rebuilt cleanly on top of main).

Core codegen fix

generateInterpolatedString built every interpolated string into a stack
alloca and returned that pointer. The value dangled the moment it escaped the
frame — a function returning an interpolated string, or a nested/subsequent
interpolation reusing the frame — producing empty or garbage output. It only
looked fine when consumed immediately by print. Now the buffer is
heap-allocated (malloc), matching generateIntToString. This is what
makes pure ANSI colour helpers (fn red(s) = "\e[31m${s}\e[0m") work when their
result is stored in a let or re-interpolated.

Runtime & examples

  • http_server_runtime.c — server "listening"/request diagnostics now go to
    stderr, so tested-example stdout is deterministic.
  • examples/tested/http/tui_repo_table.osp (+ golden) — local server →
    httpResponseBodyjsonParse/jsonGet/jsonLength → colored, aligned
    table. Proves the end-to-end pitch. [HTTP-RESPONSE-HANDLE], [BUILTIN-JSON].
  • examples/tested/http/http_response_handle.osp (+ golden) — full handle
    lifecycle: status, body, header, missing-header error, free, and a
    double-free that reports Error (no crash). [HTTP-RESPONSE-HANDLE].
  • examples/tui/api_browser.osp — interactive arrow-key repo browser
    (raw mode, termReadKey, termClear, colored render, detail view).
    [BUILTIN-TERM].
  • Regenerated the two .expectedoutput golden files that had previously been
    committed empty (the cause of the earlier red CI).

Verification

  • make test (lint + integration + unit + coverage threshold) passes locally
    with no regressions; the interpolation change is exercised across the suite.
  • tui_repo_table / http_response_handle / http_server_example goldens
    match real program output.
  • api_browser.osp compiles and renders the colored frame (verified by a
    scripted non-interactive run).

- spawn with a non-constant captured arg (record/runtime value): spill
  captures through per-spawn globals so the fiber closure reloads them
  instead of referencing out-of-scope parent SSA values.
- discriminated union construction: heap-allocate (malloc) instead of
  stack alloca so a union returned from a function no longer dangles
  (garbage int payload / string-payload segfault).
- m[key] on a runtime-built map (Map()/mapSet): route through the C
  runtime get (osprey_map_contains/get) instead of the flat-literal
  array reader, which segfaulted on the opaque OspreyMap* handle.

Covered by examples/tested/basics/knownbugs/bug1..bug4.
Completes the TUI work that did not make it into the squash of #130:
- examples/tui/api_browser.osp: interactive colored arrow-key API browser.
- jit_executor.go: link only the libs the Windows core build provides
  (fiber + winpthreads), prefer MinGW gcc; Mac/Linux link args unchanged.
- select-based Result wrap, \e/\xHH escapes, lowercase example types.
The expectedoutput files for tui_repo_table and http_response_handle were empty
(generated earlier from the wrong working dir), which failed TestHTTPExamples
with "MISSING expected output". Regenerate them with real content and drop the
nonexistent --sandbox-http flag from the api_browser run instructions.
generateInterpolatedString built each interpolated string into a stack
alloca and returned that pointer, so the value dangled the instant it
escaped the frame — a function returning an interpolated string, or a
nested/subsequent interpolation reusing the frame — yielding empty or
garbage output. Allocate the result on the heap (malloc), matching
generateIntToString. This makes pure string-wrapper helpers (the ANSI
colour functions the TUI relies on) work when their result is stored or
re-interpolated.

Runtime + examples (Phases 1-4 of docs/plans/tui-http-app.md):
- http_server_runtime.c: emit the "listening" / request diagnostics on
  stderr so example stdout is deterministic; refresh the
  http_server_example golden accordingly.
- tui_repo_table.osp / http_response_handle.osp: write to the working
  idiom (one handle op per helper, named args, no handle reuse across a
  nested match) and regenerate the previously-empty .expectedoutput
  golden files. Implements [HTTP-RESPONSE-HANDLE], [BUILTIN-JSON].
- api_browser.osp: explicit Result unwrap for checked arithmetic
  (inc/dec) and named arguments throughout, so the interactive demo
  compiles and renders. Implements [BUILTIN-TERM].
The latest publish (0.5.4) of @nimblesite/shipwright-validate-manifest
ships without its bundled schemas/ directory and aborts with ENOENT
(schemas/shipwright.schema.json), failing the "Validate deployment
manifest" step on every PR — main carries the same unpinned invocation.
0.5.3 validates shipwright.json cleanly (verified locally); pin to it
until a fixed release is published.
@MelbourneDeveloper MelbourneDeveloper merged commit 30d7140 into main Jun 1, 2026
2 checks passed
@MelbourneDeveloper MelbourneDeveloper deleted the feature/tui-phase5 branch June 1, 2026 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant