refactor(console): phase 5b — decompose toolbar/input/commands-popup methods
Finish the thin-view pass on the remaining large render methods (pure code motion, no behavior change): - renderToolbar (225 -> 99 lines): extracted drawToolbarStatus(), the drawLogFilterToggles() checkbox group, drawFilterInput(), and drawZoomControls(). - renderInput: factored the command echo + built-in interception + submit into submitConsoleCommand(exec, cmd) -> bool, leaving renderInput to own just the glass panel + InputText + completion/history callback. - renderCommandsPopup (194 -> 135 lines): removed the duplicated lowercase-and- find filter logic (match-count loop and per-row filter now share consoleCommandMatchesFilter()) and extracted the [optional]-param dimming loop into drawConsoleCommandParams(). Full-node + lite build clean; ctest green; source hygiene clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -366,30 +366,8 @@ void ConsoleTab::renderToolbar(ConsoleCommandExecutor& exec)
|
|||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Layout::spacingMd());
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Layout::spacingMd());
|
||||||
|
|
||||||
// Backend status with colored dot (daemon state / lite connection).
|
// Backend status with colored dot (daemon state / lite connection).
|
||||||
{
|
drawToolbarStatus(exec);
|
||||||
ConsoleStatusLine st = exec.toolbarStatus();
|
|
||||||
if (!st.text.empty()) {
|
|
||||||
ImVec2 cp = ImGui::GetCursorScreenPos();
|
|
||||||
float dotR = schema::UI().drawElement("tabs.console", "status-dot-radius-base").size + schema::UI().drawElement("tabs.console", "status-dot-radius-scale").size * Layout::hScale();
|
|
||||||
float dotY = cp.y + ImGui::GetTextLineHeight() * 0.5f;
|
|
||||||
float dotX = cp.x + dotR + 2;
|
|
||||||
|
|
||||||
if (st.pulse) {
|
|
||||||
float a = schema::UI().drawElement("animations", "pulse-base-glow").size + schema::UI().drawElement("animations", "pulse-amp-glow").size * (float)std::sin((double)ImGui::GetTime() * schema::UI().drawElement("animations", "pulse-speed-fast").size);
|
|
||||||
ImU32 pCol = (st.color & 0x00FFFFFF) | ((ImU32)(255 * a) << 24);
|
|
||||||
dl->AddCircleFilled(ImVec2(dotX, dotY), dotR, pCol);
|
|
||||||
} else {
|
|
||||||
dl->AddCircleFilled(ImVec2(dotX, dotY), dotR, st.color);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Dummy(ImVec2(dotR * 2 + 6, 0));
|
|
||||||
ImGui::SameLine();
|
|
||||||
Type().textColored(TypeStyle::Caption, st.color, st.text.c_str());
|
|
||||||
} else {
|
|
||||||
Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), TR("console_no_daemon"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@@ -406,49 +384,8 @@ void ConsoleTab::renderToolbar(ConsoleCommandExecutor& exec)
|
|||||||
|
|
||||||
// Log filters (daemon/errors/rpc-trace/app) apply only to a daemon log source.
|
// Log filters (daemon/errors/rpc-trace/app) apply only to a daemon log source.
|
||||||
if (exec.hasLogFilters()) {
|
if (exec.hasLogFilters()) {
|
||||||
// Daemon messages toggle
|
drawLogFilterToggles();
|
||||||
ImGui::Checkbox(TR("console_daemon"), &s_daemon_messages_enabled);
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
material::Tooltip("%s", TR("console_show_daemon_output"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
// Errors-only toggle
|
|
||||||
ImGui::Checkbox(TR("console_errors"), &s_errors_only_enabled);
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
material::Tooltip("%s", TR("console_show_errors_only"));
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
// App RPC trace toggle — captures method/source only, never results or params
|
|
||||||
if (ImGui::Checkbox(TR("console_rpc_trace"), &s_rpc_trace_enabled)) {
|
|
||||||
rpc::RPCClient::setTraceEnabled(s_rpc_trace_enabled);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
material::Tooltip("%s", TR("console_show_rpc_trace"));
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
// App messages toggle — "[app] ..." wallet log lines
|
|
||||||
ImGui::Checkbox(TR("console_app"), &s_app_messages_enabled);
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
material::Tooltip("%s", TR("console_show_app_output"));
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
} // exec.hasLogFilters()
|
|
||||||
|
|
||||||
// Clear button
|
// Clear button
|
||||||
if (TactileButton(TR("console_clear"), ImVec2(0, 0), schema::UI().resolveFont("button"))) {
|
if (TactileButton(TR("console_clear"), ImVec2(0, 0), schema::UI().resolveFont("button"))) {
|
||||||
@@ -501,6 +438,90 @@ void ConsoleTab::renderToolbar(ConsoleCommandExecutor& exec)
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
// Output filter input
|
// Output filter input
|
||||||
|
drawFilterInput();
|
||||||
|
|
||||||
|
// Zoom +/- buttons (right side of toolbar)
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::SameLine();
|
||||||
|
drawZoomControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleTab::drawToolbarStatus(ConsoleCommandExecutor& exec)
|
||||||
|
{
|
||||||
|
using namespace material;
|
||||||
|
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||||
|
ConsoleStatusLine st = exec.toolbarStatus();
|
||||||
|
if (!st.text.empty()) {
|
||||||
|
ImVec2 cp = ImGui::GetCursorScreenPos();
|
||||||
|
float dotR = schema::UI().drawElement("tabs.console", "status-dot-radius-base").size + schema::UI().drawElement("tabs.console", "status-dot-radius-scale").size * Layout::hScale();
|
||||||
|
float dotY = cp.y + ImGui::GetTextLineHeight() * 0.5f;
|
||||||
|
float dotX = cp.x + dotR + 2;
|
||||||
|
|
||||||
|
if (st.pulse) {
|
||||||
|
float a = schema::UI().drawElement("animations", "pulse-base-glow").size + schema::UI().drawElement("animations", "pulse-amp-glow").size * (float)std::sin((double)ImGui::GetTime() * schema::UI().drawElement("animations", "pulse-speed-fast").size);
|
||||||
|
ImU32 pCol = (st.color & 0x00FFFFFF) | ((ImU32)(255 * a) << 24);
|
||||||
|
dl->AddCircleFilled(ImVec2(dotX, dotY), dotR, pCol);
|
||||||
|
} else {
|
||||||
|
dl->AddCircleFilled(ImVec2(dotX, dotY), dotR, st.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Dummy(ImVec2(dotR * 2 + 6, 0));
|
||||||
|
ImGui::SameLine();
|
||||||
|
Type().textColored(TypeStyle::Caption, st.color, st.text.c_str());
|
||||||
|
} else {
|
||||||
|
Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), TR("console_no_daemon"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleTab::drawLogFilterToggles()
|
||||||
|
{
|
||||||
|
// Daemon messages toggle
|
||||||
|
ImGui::Checkbox(TR("console_daemon"), &s_daemon_messages_enabled);
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
material::Tooltip("%s", TR("console_show_daemon_output"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
// Errors-only toggle
|
||||||
|
ImGui::Checkbox(TR("console_errors"), &s_errors_only_enabled);
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
material::Tooltip("%s", TR("console_show_errors_only"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
// App RPC trace toggle — captures method/source only, never results or params
|
||||||
|
if (ImGui::Checkbox(TR("console_rpc_trace"), &s_rpc_trace_enabled)) {
|
||||||
|
rpc::RPCClient::setTraceEnabled(s_rpc_trace_enabled);
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
material::Tooltip("%s", TR("console_show_rpc_trace"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
// App messages toggle — "[app] ..." wallet log lines
|
||||||
|
ImGui::Checkbox(TR("console_app"), &s_app_messages_enabled);
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
material::Tooltip("%s", TR("console_show_app_output"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::SameLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleTab::drawFilterInput()
|
||||||
|
{
|
||||||
|
using namespace material;
|
||||||
float zoomBtnSpace = ImGui::GetFrameHeight() * 2.0f + Layout::spacingSm() * 3.0f;
|
float zoomBtnSpace = ImGui::GetFrameHeight() * 2.0f + Layout::spacingSm() * 3.0f;
|
||||||
float filterAvail = ImGui::GetContentRegionAvail().x - zoomBtnSpace;
|
float filterAvail = ImGui::GetContentRegionAvail().x - zoomBtnSpace;
|
||||||
float filterW = std::min(schema::UI().drawElement("tabs.console", "filter-max-width").size, filterAvail * schema::UI().drawElement("tabs.console", "filter-width-ratio").size);
|
float filterW = std::min(schema::UI().drawElement("tabs.console", "filter-max-width").size, filterAvail * schema::UI().drawElement("tabs.console", "filter-width-ratio").size);
|
||||||
@@ -512,31 +533,29 @@ void ConsoleTab::renderToolbar(ConsoleCommandExecutor& exec)
|
|||||||
Type().textColored(TypeStyle::Caption,
|
Type().textColored(TypeStyle::Caption,
|
||||||
filter_match_count_ > 0 ? OnSurfaceMedium() : Error(), mc.c_str());
|
filter_match_count_ > 0 ? OnSurfaceMedium() : Error(), mc.c_str());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Zoom +/- buttons (right side of toolbar)
|
void ConsoleTab::drawZoomControls()
|
||||||
ImGui::SameLine();
|
{
|
||||||
ImGui::Spacing();
|
using namespace material;
|
||||||
ImGui::SameLine();
|
auto& S = schema::UI();
|
||||||
{
|
float zoomStep = S.drawElement("tabs.console", "zoom-step").sizeOr(0.1f);
|
||||||
auto& S = schema::UI();
|
float zoomMin = S.drawElement("tabs.console", "zoom-min").sizeOr(0.5f);
|
||||||
float zoomStep = S.drawElement("tabs.console", "zoom-step").sizeOr(0.1f);
|
float zoomMax = S.drawElement("tabs.console", "zoom-max").sizeOr(3.0f);
|
||||||
float zoomMin = S.drawElement("tabs.console", "zoom-min").sizeOr(0.5f);
|
float btnSz = ImGui::GetFrameHeight();
|
||||||
float zoomMax = S.drawElement("tabs.console", "zoom-max").sizeOr(3.0f);
|
|
||||||
float btnSz = ImGui::GetFrameHeight();
|
|
||||||
|
|
||||||
if (TactileButton(ICON_MD_REMOVE, ImVec2(btnSz, btnSz), Type().iconMed())) {
|
if (TactileButton(ICON_MD_REMOVE, ImVec2(btnSz, btnSz), Type().iconMed())) {
|
||||||
s_console_zoom = std::max(zoomMin, s_console_zoom - zoomStep);
|
s_console_zoom = std::max(zoomMin, s_console_zoom - zoomStep);
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
material::Tooltip(TR("console_zoom_out"), s_console_zoom * 100.0f);
|
material::Tooltip(TR("console_zoom_out"), s_console_zoom * 100.0f);
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (TactileButton(ICON_MD_ADD, ImVec2(btnSz, btnSz), Type().iconMed())) {
|
if (TactileButton(ICON_MD_ADD, ImVec2(btnSz, btnSz), Type().iconMed())) {
|
||||||
s_console_zoom = std::min(zoomMax, s_console_zoom + zoomStep);
|
s_console_zoom = std::min(zoomMax, s_console_zoom + zoomStep);
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
material::Tooltip(TR("console_zoom_in"), s_console_zoom * 100.0f);
|
material::Tooltip(TR("console_zoom_in"), s_console_zoom * 100.0f);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1108,34 +1127,7 @@ void ConsoleTab::renderInput(ConsoleCommandExecutor& exec)
|
|||||||
if (tb == std::string::npos) cmd.clear(); else cmd = cmd.substr(tb);
|
if (tb == std::string::npos) cmd.clear(); else cmd = cmd.substr(tb);
|
||||||
while (!cmd.empty() && (cmd.back() == ' ' || cmd.back() == '\t')) cmd.pop_back();
|
while (!cmd.empty() && (cmd.back() == ' ' || cmd.back() == '\t')) cmd.pop_back();
|
||||||
|
|
||||||
if (!cmd.empty()) {
|
if (submitConsoleCommand(exec, cmd)) {
|
||||||
addLine("> " + cmd, ConsoleChannel::Command);
|
|
||||||
AppendConsoleHistory(command_history_, cmd, 100);
|
|
||||||
history_index_ = -1;
|
|
||||||
|
|
||||||
// First token, lowercased, for built-in interception.
|
|
||||||
std::string first;
|
|
||||||
{
|
|
||||||
size_t fb = cmd.find_first_not_of(" \t");
|
|
||||||
size_t fe = cmd.find_first_of(" \t", fb);
|
|
||||||
first = cmd.substr(fb, fe == std::string::npos ? std::string::npos : fe - fb);
|
|
||||||
std::transform(first.begin(), first.end(), first.begin(),
|
|
||||||
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
|
|
||||||
}
|
|
||||||
auto add = [this](const std::string& l, ConsoleChannel c) { addLine(l, c); };
|
|
||||||
if (first == "clear" || first == "cls") {
|
|
||||||
// View-only clear — NEVER forwarded (the lite backend's `clear` wipes tx history).
|
|
||||||
clear();
|
|
||||||
selection_.clear();
|
|
||||||
} else if (first == "help") {
|
|
||||||
exec.printHelp(add);
|
|
||||||
} else if (first == "quit" || first == "exit") {
|
|
||||||
addLine(TR("console_quit_note"), ConsoleChannel::Info);
|
|
||||||
} else if (!exec.isReady()) {
|
|
||||||
addLine(TR("console_not_connected"), ConsoleChannel::Error);
|
|
||||||
} else {
|
|
||||||
exec.submit(cmd);
|
|
||||||
}
|
|
||||||
input_buffer_[0] = '\0';
|
input_buffer_[0] = '\0';
|
||||||
reclaim_focus = true;
|
reclaim_focus = true;
|
||||||
}
|
}
|
||||||
@@ -1150,6 +1142,94 @@ void ConsoleTab::renderInput(ConsoleCommandExecutor& exec)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ConsoleTab::submitConsoleCommand(ConsoleCommandExecutor& exec, const std::string& cmd)
|
||||||
|
{
|
||||||
|
if (cmd.empty()) return false;
|
||||||
|
|
||||||
|
addLine("> " + cmd, ConsoleChannel::Command);
|
||||||
|
AppendConsoleHistory(command_history_, cmd, 100);
|
||||||
|
history_index_ = -1;
|
||||||
|
|
||||||
|
// First token, lowercased, for built-in interception.
|
||||||
|
std::string first;
|
||||||
|
{
|
||||||
|
size_t fb = cmd.find_first_not_of(" \t");
|
||||||
|
size_t fe = cmd.find_first_of(" \t", fb);
|
||||||
|
first = cmd.substr(fb, fe == std::string::npos ? std::string::npos : fe - fb);
|
||||||
|
std::transform(first.begin(), first.end(), first.begin(),
|
||||||
|
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
|
||||||
|
}
|
||||||
|
auto add = [this](const std::string& l, ConsoleChannel c) { addLine(l, c); };
|
||||||
|
if (first == "clear" || first == "cls") {
|
||||||
|
// View-only clear — NEVER forwarded (the lite backend's `clear` wipes tx history).
|
||||||
|
clear();
|
||||||
|
selection_.clear();
|
||||||
|
} else if (first == "help") {
|
||||||
|
exec.printHelp(add);
|
||||||
|
} else if (first == "quit" || first == "exit") {
|
||||||
|
addLine(TR("console_quit_note"), ConsoleChannel::Info);
|
||||||
|
} else if (!exec.isReady()) {
|
||||||
|
addLine(TR("console_not_connected"), ConsoleChannel::Error);
|
||||||
|
} else {
|
||||||
|
exec.submit(cmd);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// True if any of a command's name/desc/params contains `filterLower` (already lowercased).
|
||||||
|
// An empty filter matches everything.
|
||||||
|
bool consoleCommandMatchesFilter(const char* name, const char* desc, const char* params,
|
||||||
|
const std::string& filterLower)
|
||||||
|
{
|
||||||
|
if (filterLower.empty()) return true;
|
||||||
|
auto contains = [&filterLower](const char* s) {
|
||||||
|
std::string v(s);
|
||||||
|
std::transform(v.begin(), v.end(), v.begin(), ::tolower);
|
||||||
|
return v.find(filterLower) != std::string::npos;
|
||||||
|
};
|
||||||
|
return contains(name) || contains(desc) || contains(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a command's parameter string into the current table cell, dimming optional [params].
|
||||||
|
void drawConsoleCommandParams(const char* params)
|
||||||
|
{
|
||||||
|
using namespace material;
|
||||||
|
const char* p = params;
|
||||||
|
bool first = true;
|
||||||
|
while (*p) {
|
||||||
|
const char* bracketStart = strchr(p, '[');
|
||||||
|
if (bracketStart) {
|
||||||
|
// Draw the required part before the bracket.
|
||||||
|
if (bracketStart > p) {
|
||||||
|
if (!first) ImGui::SameLine(0, 0);
|
||||||
|
std::string req(p, bracketStart);
|
||||||
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceDisabled()), "%s", req.c_str());
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
const char* bracketEnd = strchr(bracketStart, ']');
|
||||||
|
if (bracketEnd) {
|
||||||
|
if (!first) ImGui::SameLine(0, 0);
|
||||||
|
std::string opt(bracketStart, bracketEnd + 1);
|
||||||
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceMedium()), "%s", opt.c_str());
|
||||||
|
first = false;
|
||||||
|
p = bracketEnd + 1;
|
||||||
|
} else {
|
||||||
|
if (!first) ImGui::SameLine(0, 0);
|
||||||
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceDisabled()), "%s", bracketStart);
|
||||||
|
first = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!first) ImGui::SameLine(0, 0);
|
||||||
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceDisabled()), "%s", p);
|
||||||
|
first = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void ConsoleTab::renderCommandsPopup()
|
void ConsoleTab::renderCommandsPopup()
|
||||||
{
|
{
|
||||||
using namespace material;
|
using namespace material;
|
||||||
@@ -1190,15 +1270,8 @@ void ConsoleTab::renderCommandsPopup()
|
|||||||
matchCount = cat.count;
|
matchCount = cat.count;
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < cat.count; i++) {
|
for (int i = 0; i < cat.count; i++) {
|
||||||
std::string name(cat.commands[i].name);
|
if (consoleCommandMatchesFilter(cat.commands[i].name, cat.commands[i].desc,
|
||||||
std::string desc(cat.commands[i].desc);
|
cat.commands[i].params, filter)) {
|
||||||
std::string params(cat.commands[i].params);
|
|
||||||
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
|
|
||||||
std::transform(desc.begin(), desc.end(), desc.begin(), ::tolower);
|
|
||||||
std::transform(params.begin(), params.end(), params.begin(), ::tolower);
|
|
||||||
if (name.find(filter) != std::string::npos ||
|
|
||||||
desc.find(filter) != std::string::npos ||
|
|
||||||
params.find(filter) != std::string::npos) {
|
|
||||||
matchCount++;
|
matchCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1234,20 +1307,9 @@ void ConsoleTab::renderCommandsPopup()
|
|||||||
|
|
||||||
for (int i = 0; i < cat.count; i++) {
|
for (int i = 0; i < cat.count; i++) {
|
||||||
const auto& cmd = cat.commands[i];
|
const auto& cmd = cat.commands[i];
|
||||||
std::string nameLower(cmd.name);
|
if (!consoleCommandMatchesFilter(cmd.name, cmd.desc, cmd.params, filter))
|
||||||
std::string descLower(cmd.desc);
|
|
||||||
std::string paramsLower(cmd.params);
|
|
||||||
std::transform(nameLower.begin(), nameLower.end(), nameLower.begin(), ::tolower);
|
|
||||||
std::transform(descLower.begin(), descLower.end(), descLower.begin(), ::tolower);
|
|
||||||
std::transform(paramsLower.begin(), paramsLower.end(), paramsLower.begin(), ::tolower);
|
|
||||||
|
|
||||||
if (!filter.empty() &&
|
|
||||||
nameLower.find(filter) == std::string::npos &&
|
|
||||||
descLower.find(filter) == std::string::npos &&
|
|
||||||
paramsLower.find(filter) == std::string::npos) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,
|
ImGui::PushStyleColor(ImGuiCol_Text,
|
||||||
@@ -1275,48 +1337,7 @@ void ConsoleTab::renderCommandsPopup()
|
|||||||
ImGui::PopStyleColor(3);
|
ImGui::PopStyleColor(3);
|
||||||
if (showParams) {
|
if (showParams) {
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
// Style optional params [param] in dimmed text
|
drawConsoleCommandParams(cmd.params);
|
||||||
const char* p = cmd.params;
|
|
||||||
bool first = true;
|
|
||||||
while (*p) {
|
|
||||||
const char* bracketStart = strchr(p, '[');
|
|
||||||
if (bracketStart) {
|
|
||||||
// Draw required part before bracket
|
|
||||||
if (bracketStart > p) {
|
|
||||||
if (!first) ImGui::SameLine(0, 0);
|
|
||||||
std::string req(p, bracketStart);
|
|
||||||
ImGui::TextColored(
|
|
||||||
ImGui::ColorConvertU32ToFloat4(OnSurfaceDisabled()),
|
|
||||||
"%s", req.c_str());
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
// Find matching ]
|
|
||||||
const char* bracketEnd = strchr(bracketStart, ']');
|
|
||||||
if (bracketEnd) {
|
|
||||||
if (!first) ImGui::SameLine(0, 0);
|
|
||||||
std::string opt(bracketStart, bracketEnd + 1);
|
|
||||||
ImGui::TextColored(
|
|
||||||
ImGui::ColorConvertU32ToFloat4(OnSurfaceMedium()),
|
|
||||||
"%s", opt.c_str());
|
|
||||||
first = false;
|
|
||||||
p = bracketEnd + 1;
|
|
||||||
} else {
|
|
||||||
if (!first) ImGui::SameLine(0, 0);
|
|
||||||
ImGui::TextColored(
|
|
||||||
ImGui::ColorConvertU32ToFloat4(OnSurfaceDisabled()),
|
|
||||||
"%s", bracketStart);
|
|
||||||
first = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!first) ImGui::SameLine(0, 0);
|
|
||||||
ImGui::TextColored(
|
|
||||||
ImGui::ColorConvertU32ToFloat4(OnSurfaceDisabled()),
|
|
||||||
"%s", p);
|
|
||||||
first = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::TextColored(
|
ImGui::TextColored(
|
||||||
|
|||||||
@@ -100,10 +100,20 @@ private:
|
|||||||
// Format a completed command result (JSON role -> channel) into console lines.
|
// Format a completed command result (JSON role -> channel) into console lines.
|
||||||
void addFormattedResult(const std::string& result, bool is_error);
|
void addFormattedResult(const std::string& result, bool is_error);
|
||||||
void renderStatusHeader(ConsoleCommandExecutor& exec);
|
void renderStatusHeader(ConsoleCommandExecutor& exec);
|
||||||
void renderToolbar(ConsoleCommandExecutor& exec);
|
|
||||||
void renderInput(ConsoleCommandExecutor& exec);
|
|
||||||
void renderCommandsPopup();
|
void renderCommandsPopup();
|
||||||
|
|
||||||
|
// renderToolbar() draws the top bar; these are its sub-steps:
|
||||||
|
void renderToolbar(ConsoleCommandExecutor& exec);
|
||||||
|
void drawToolbarStatus(ConsoleCommandExecutor& exec); // backend status dot + label
|
||||||
|
void drawLogFilterToggles(); // daemon/errors/rpc/app checkboxes
|
||||||
|
void drawFilterInput(); // text filter + match count
|
||||||
|
void drawZoomControls(); // zoom -/+ buttons
|
||||||
|
|
||||||
|
// renderInput() draws the command line; dispatch is factored out:
|
||||||
|
void renderInput(ConsoleCommandExecutor& exec);
|
||||||
|
// Echo + handle a submitted command line (built-ins + submit). True if non-empty/handled.
|
||||||
|
bool submitConsoleCommand(ConsoleCommandExecutor& exec, const std::string& cmd);
|
||||||
|
|
||||||
// renderOutput() orchestrates the scrollable output area; these are its sub-steps:
|
// renderOutput() orchestrates the scrollable output area; these are its sub-steps:
|
||||||
void renderOutput();
|
void renderOutput();
|
||||||
void computeVisibleLines(bool& hasTextFilter, std::string& filterLower); // -> visible_indices_
|
void computeVisibleLines(bool& hasTextFilter, std::string& filterLower); // -> visible_indices_
|
||||||
|
|||||||
Reference in New Issue
Block a user