#include #include #include #include "multilog.h" static int uniqid() { static int i = 0; return i++; } MultiLog::Item::Item() : id{uniqid()} {} MultiLog::MultiLog(bool fancy) : fancy{fancy} {} int MultiLog::add(const string_view prefix) { lock_guard guard(mut); assert(prefix.find('\n') == string::npos); items.emplace_back(); items.back().line = prefix; if (fancy) { cout << prefix << endl; } else { cout << "[" << items.back().id << "] " << prefix << endl; } return items.back().id; } void MultiLog::append(int id, const string_view text) { lock_guard guard(mut); assert(text.find('\n') == string::npos); size_t idx = findId(id); items[idx].line += text; if (fancy) { redrawLine(idx); } else { cout << "[" << items[idx].id << "]... " << text << endl; } } void MultiLog::complete(int id) { lock_guard guard(mut); size_t idx = findId(id); items[idx].complete = true; size_t nextIdx; for (nextIdx = 0; nextIdx < items.size(); nextIdx++) { if (!items[nextIdx].complete) break; } if (nextIdx > 0) items.erase(items.begin(), items.begin() + (nextIdx - 1)); } size_t MultiLog::findId(int id) { for (int i = 0; i < (int)items.size(); i++) { if (items[i].id == id) return i; } assert(false); } void MultiLog::redrawLine(size_t idx) { size_t offset = items.size() - idx; cout << "\r\x1B[" << offset << "A\x1B[K" << items[idx].line << "\r\x1B[" << offset << "B" << flush; }