tui: chat scene, markdown and row builders, live stream; differential tests vs tai.py
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
// tui_rows: differential harness for the chat row builders and markdown helpers.
|
||||
// Reads one JSON case per line on stdin, prints the rendered rows (each span as
|
||||
// <sgr>text) so the output can be diffed byte for byte against the python functions.
|
||||
#include "TuiChatRows.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace detz::tui;
|
||||
|
||||
static std::string spans_out(const SpanRows& rows) {
|
||||
std::string out;
|
||||
for (auto& row : rows) {
|
||||
for (auto& span : row) out += "<" + span.style->sgr().substr(1) + ">" + TuiStr::s(span.text);
|
||||
out += "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
static std::string segs_out(const TuiMarkdown::Segs& segs) {
|
||||
std::string out = "[";
|
||||
for (auto& s : segs) out += "(" + TuiValue(TuiStr::s(s.first)).repr() + "," + TuiValue(s.second).repr() + ")";
|
||||
return out + "]";
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
bool ok = false;
|
||||
TuiValue c = TuiValue::loads(line, &ok);
|
||||
if (!ok) { std::cout << "BAD JSON\n"; continue; }
|
||||
std::string fn = c.get("fn").as_str();
|
||||
UStr text = TuiStr::u(c.get("text").as_str());
|
||||
long width = static_cast<long>(c.get("width").as_int());
|
||||
if (fn == "bubble") {
|
||||
auto st = TuiChatRows::styles(c.get("side").as_str());
|
||||
std::cout << spans_out(TuiChatRows::bubble_rows(text, width, c.get("side").as_str(), st, TuiStr::u(c.get("stamp").as_str()),
|
||||
TuiStr::u(c.get("ticks").as_str()), c.get("read").truthy(),
|
||||
TuiStr::u(c.get("sender").as_str()), c.get("markdown").truthy(), c.get("boxed").truthy()));
|
||||
} else if (fn == "tool") {
|
||||
auto base = TuiChatRows::styles("in")["base"];
|
||||
std::cout << spans_out(SpanRows{TuiChatRows::tool_row(TuiStr::u(c.get("name").as_str()), c.get("args").as_str(), width, base)});
|
||||
} else if (fn == "live") {
|
||||
auto base = TuiChatRows::styles("in")["base"];
|
||||
std::vector<UStr> lines;
|
||||
for (auto& l : c.get("lines").items()) lines.push_back(TuiStr::u(l.as_str()));
|
||||
std::cout << spans_out(TuiChatRows::live_rows(text, lines, TuiStr::u(c.get("status").as_str()), width, base));
|
||||
} else if (fn == "note") {
|
||||
auto base = TuiChatRows::styles("in")["base"];
|
||||
std::cout << spans_out(TuiChatRows::note_rows(text, width, c.get("side").as_str(), base));
|
||||
} else if (fn == "pill") {
|
||||
auto st = TuiChatRows::styles("in");
|
||||
std::cout << spans_out(SpanRows{TuiChatRows::pill_row(text, width, st["base"], st["bubble"])});
|
||||
} else if (fn == "welcome") {
|
||||
std::cout << spans_out(TuiChatRows::welcome_rows(width, text));
|
||||
} else if (fn == "md") {
|
||||
for (auto& b : TuiMarkdown::blocks(text)) std::cout << b.kind << " " << segs_out(b.segs) << " " << TuiValue(TuiStr::s(b.lead)).repr() << "\n";
|
||||
} else if (fn == "wrap") {
|
||||
auto segs = TuiMarkdown::inline_segs(text);
|
||||
for (auto& l : TuiMarkdown::wrap_segs(segs, width)) std::cout << segs_out(l) << "\n";
|
||||
} else if (fn == "textwrap") {
|
||||
auto parts = TuiMarkdown::textwrap(text, width);
|
||||
if (parts.empty()) parts = {UStr()};
|
||||
for (auto& l : parts) std::cout << TuiValue(TuiStr::s(l)).repr() << "\n";
|
||||
} else if (fn == "strip") {
|
||||
std::cout << TuiValue(TuiStr::s(TuiMarkdown::strip_ansi(text))).repr() << "\n";
|
||||
} else if (fn == "sidebar") {
|
||||
std::cout << TuiChatRows::sidebar_w(static_cast<int>(width)) << "\n";
|
||||
}
|
||||
std::cout << "==\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user