A large RPC result was fully split into lines and copied before being handed to the console, even though only the last few lines could survive the model's line cap. - The formatter now takes a line cap and keeps only the last N lines, located by a backward newline scan, so a huge result is never fully split or copied. JSON classification still keys off the first character of the whole result. - It works over a string view and moves line text through, and fold spans are computed over the formatted lines directly instead of a separate vector of copies. - getline semantics are preserved: a trailing newline adds no empty line and an empty result yields no lines. Tests: getline parity for empty, trailing-newline and blank-line inputs, the backward tail cap, and JSON classification and fold spans over a capped result. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
78 lines
3.2 KiB
C++
78 lines
3.2 KiB
C++
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <nlohmann/json.hpp>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
namespace dragonx {
|
|
namespace ui {
|
|
|
|
struct ConsoleCompletionResult {
|
|
std::vector<std::string> matches;
|
|
std::string commonPrefix;
|
|
};
|
|
|
|
struct ConsoleRpcCall {
|
|
bool valid = false;
|
|
std::string method;
|
|
nlohmann::json params = nlohmann::json::array();
|
|
std::string error; // set (with valid=false) when an argument fails to parse
|
|
};
|
|
|
|
enum class ConsoleResultLineRole {
|
|
Result,
|
|
Error,
|
|
JsonKey,
|
|
JsonString,
|
|
JsonNumber,
|
|
JsonBrace
|
|
};
|
|
|
|
struct ConsoleResultLine {
|
|
std::string text;
|
|
ConsoleResultLineRole role = ConsoleResultLineRole::Result;
|
|
};
|
|
|
|
const std::vector<std::string>& ConsoleRpcCommandNames();
|
|
void AppendConsoleHistory(std::vector<std::string>& history,
|
|
const std::string& command,
|
|
std::size_t maxEntries = 100);
|
|
int NavigateConsoleHistoryIndex(int currentIndex,
|
|
std::size_t historySize,
|
|
bool up);
|
|
std::string ConsoleHistoryEntry(const std::vector<std::string>& history,
|
|
int historyIndex);
|
|
ConsoleCompletionResult CompleteConsoleCommand(const std::string& input);
|
|
std::vector<std::string> FormatConsoleCompletionLines(const std::vector<std::string>& matches,
|
|
std::size_t maxLineLength = 60);
|
|
// A tokenized console argument. `quoted` is true when the token came from a "..."/'...' literal,
|
|
// so BuildConsoleRpcCall must send it verbatim as a JSON string (never coerce it to a number/bool).
|
|
struct ConsoleArg {
|
|
std::string text;
|
|
bool quoted = false;
|
|
};
|
|
std::vector<ConsoleArg> ParseConsoleCommandArgsTagged(const std::string& command);
|
|
std::vector<std::string> ParseConsoleCommandArgs(const std::string& command);
|
|
ConsoleRpcCall BuildConsoleRpcCall(const std::string& command);
|
|
// Splits an RPC result into classified lines (std::getline semantics: a trailing '\n' adds no
|
|
// empty line, an empty result yields none). `maxLines` > 0 keeps only the LAST maxLines lines,
|
|
// found by a backward newline scan so a huge result is never fully split/copied. The JSON
|
|
// classification still keys off the first char of the whole result. 0 = no cap.
|
|
std::vector<ConsoleResultLine> FormatConsoleRpcResultLines(std::string_view result,
|
|
bool isError,
|
|
std::size_t maxLines = 0);
|
|
|
|
// For a block of pretty-printed JSON lines, return a per-line fold span: for a line that
|
|
// opens a collapsible block (its last non-space char is '{' or '[') the value is the offset
|
|
// to its matching closing-bracket line at the same indentation; 0 for every other line and
|
|
// for empty/one-line blocks not worth folding (span < 2). Pure; used to drive console
|
|
// JSON folding.
|
|
std::vector<int> ComputeConsoleFoldSpans(const std::vector<std::string>& lines);
|
|
// Same as ComputeConsoleFoldSpans, over formatted result lines directly (no text copies).
|
|
std::vector<int> ComputeConsoleResultFoldSpans(const std::vector<ConsoleResultLine>& lines);
|
|
|
|
} // namespace ui
|
|
} // namespace dragonx
|