f22a3b33c8
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>
52 lines
1.7 KiB
Lua
52 lines
1.7 KiB
Lua
-- renderer.lua — output formatting and ANSI sequences.
|
|
-- 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)
|
|
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)
|
|
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)
|
|
emit(A.dim, "[aish] ", tostring(line), A.reset, "\n")
|
|
end
|
|
|
|
return M
|