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:
+37
-5
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user