renderer: assistant text, exec output frame, status line

Phase 0 minimal output formatting per PHASE0.md skeleton.

  M.assistant(text)              — line-by-line; `CMD: ` lines bold+cyan
  M.exec_output(output, code)    — top/bottom rules; exit code on closing
                                   rule (red on non-zero)
  M.status(line)                 — dim "[aish] ..." single-liner

ANSI table is local to the module (no external dep). Trailing-sentinel
pattern ((text..\"\\n\"):gmatch(\"([^\\n]*)\\n\")) preserves blank lines
in assistant output rather than squashing them, at the cost of one
extra trailing newline — acceptable for Phase 0. Real syntax-aware
formatting (tree-sitter) lands in Phase 6.

Smoke verifies escape codes are emitted (od -c shows \\033[1m\\033[36m
around CMD: line) and the visual layout looks right.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-10 14:42:56 +00:00
parent f9f8b0370c
commit f22a3b33c8
+37 -5
View File
@@ -1,19 +1,51 @@
-- renderer.lua — output formatting and ANSI sequences.
-- Phase 0: minimal — assistant text plain-printed; CMD: lines highlighted;
-- exec output framed. Syntax highlighting hooks land in Phase 5.
-- Phase 0: assistant text plain-printed with `CMD: ` lines highlighted;
-- exec output framed with the exit code on the closing rule. Syntax
-- highlighting hooks land in Phase 6 (was Phase 5 pre-MCP renumber).
local M = {}
local A = {
reset = "\27[0m",
bold = "\27[1m",
dim = "\27[2m",
cyan = "\27[36m",
red = "\27[31m",
}
local function emit(...) io.write(...); io.flush() end
-- Print assistant response text. Lines beginning with `CMD: ` (per the §3
-- substrate-locked extraction marker) are emitted bold+cyan so the user
-- can spot the suggestion without scanning prose.
function M.assistant(text)
error("renderer.assistant: not implemented (Phase 0 pending)")
for line in ((text or "") .. "\n"):gmatch("([^\n]*)\n") do
if line:sub(1, 5) == "CMD: " then
emit(A.bold, A.cyan, line, A.reset, "\n")
else
emit(line, "\n")
end
end
end
-- Frame captured shell-exec output with a top rule + the body + a closing
-- rule that carries the exit code (red on non-zero).
function M.exec_output(output, exit_code)
error("renderer.exec_output: not implemented (Phase 0 pending)")
output = (output or ""):gsub("\n$", "")
emit(A.dim, "─── exec output ───", A.reset, "\n")
if output ~= "" then emit(output, "\n") end
if exit_code and exit_code ~= 0 then
emit(A.dim, "─── exit ", A.reset,
A.red, tostring(exit_code), A.reset,
A.dim, " ───", A.reset, "\n")
else
emit(A.dim, "─── exit 0 ───", A.reset, "\n")
end
end
-- Single-line dim status (e.g. §8 eviction notice, model switch confirms).
function M.status(line)
error("renderer.status: not implemented (Phase 0 pending)")
emit(A.dim, "[aish] ", tostring(line), A.reset, "\n")
end
return M