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,87 @@
|
||||
// tui_script: scripted headless session over the demo scene, to diff against python.
|
||||
// Script lines (stdin):
|
||||
// feed <hex> stdin bytes -> TuiInput -> app.dispatch
|
||||
// flush TuiInput.flush() -> dispatch (lone ESC resolution)
|
||||
// frame print hex of app.frame_bytes()
|
||||
// text print app.render_text()
|
||||
// resize R C like SIGWINCH: new size, invalidate, dirty_layout, Resize event
|
||||
// shell <text> feed text (with \r\n for \n) into the demo shell screen
|
||||
// ask open the demo question dialog (F1 path)
|
||||
// sources install the completion sources used by the prompt dialog
|
||||
#include "TuiComplete.h"
|
||||
#include "TuiDemo.h"
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
using namespace detz::tui;
|
||||
|
||||
static std::string unhex(const std::string& h) {
|
||||
std::string out;
|
||||
for (size_t i = 0; i + 1 < h.size(); i += 2) out.push_back(static_cast<char>(std::stoi(h.substr(i, 2), nullptr, 16)));
|
||||
return out;
|
||||
}
|
||||
static std::string hex(const std::string& s) {
|
||||
static const char* d = "0123456789abcdef";
|
||||
std::string out;
|
||||
for (unsigned char c : s) { out.push_back(d[c >> 4]); out.push_back(d[c & 15]); }
|
||||
return out;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int rows = argc > 1 ? std::atoi(argv[1]) : 30;
|
||||
int cols = argc > 2 ? std::atoi(argv[2]) : 100;
|
||||
TuiApp app;
|
||||
app.rows = rows;
|
||||
app.cols = cols;
|
||||
auto built = TuiDemo::build(app, false);
|
||||
app.mount(built.first);
|
||||
auto& refs = *built.second;
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
std::istringstream in(line);
|
||||
std::string cmd;
|
||||
in >> cmd;
|
||||
if (cmd == "feed") {
|
||||
std::string h;
|
||||
in >> h;
|
||||
for (auto& ev : app.input.feed(unhex(h))) app.dispatch(*ev);
|
||||
} else if (cmd == "flush") {
|
||||
for (auto& ev : app.input.flush()) app.dispatch(*ev);
|
||||
} else if (cmd == "frame") {
|
||||
std::printf("%s\n", hex(app.frame_bytes()).c_str());
|
||||
} else if (cmd == "text") {
|
||||
std::printf("%s\n--\n", app.render_text().c_str());
|
||||
} else if (cmd == "resize") {
|
||||
int r, c;
|
||||
in >> r >> c;
|
||||
app.rows = r;
|
||||
app.cols = c;
|
||||
app.compositor.invalidate();
|
||||
app.dirty_layout();
|
||||
TuiResize ev;
|
||||
ev.panel = app.root.get();
|
||||
ev.rows = r;
|
||||
ev.cols = c;
|
||||
app.root->emit(ev);
|
||||
} else if (cmd == "shell") {
|
||||
std::string h;
|
||||
in >> h;
|
||||
refs.shell->screen.feed(unhex(h));
|
||||
} else if (cmd == "ask") {
|
||||
refs.ask();
|
||||
} else if (cmd == "spawn") {
|
||||
refs.spawn();
|
||||
} else if (cmd == "sources") {
|
||||
auto& s = TuiComplete::sources();
|
||||
s.commands = {"help", "profile", "bots", "quit"};
|
||||
s.help_text = " /help show help Show this help\n /profile NAME switch Switch profile\n /bots list bots\n";
|
||||
s.provider_labels = {"Muse", "Grok"};
|
||||
s.default_models = [] { return std::vector<std::string>{"model-a", "model-b"}; };
|
||||
s.complete_files = [](const std::string&, const std::string&) { return std::vector<std::string>{"src/a.txt"}; };
|
||||
s.dir_key = [] { return std::string("/tmp"); };
|
||||
TuiComplete::reset_command_help();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user