diff --git a/src/ui/windows/console_tab.cpp b/src/ui/windows/console_tab.cpp index 27f34bd..4d67e8b 100644 --- a/src/ui/windows/console_tab.cpp +++ b/src/ui/windows/console_tab.cpp @@ -1635,13 +1635,20 @@ void ConsoleTab::renderCommandDetail(const ConsoleCommandEntry& cmd, const char* if (a == std::string::npos) return std::string(); return s.substr(a, s.find_last_not_of(" \t") - a + 1); }; + // Include fields up to the last one that is filled OR required; trailing empty optionals are + // dropped. An empty field that must still be included (a blank required field, or a gap before a + // later filled field — positional args can't skip a middle slot) keeps its placeholder and marks + // the command incomplete, so Insert & run stays disabled and no typed value is silently lost. + int lastNeeded = -1; + for (size_t k = 0; k < specs.size() && k < 6; k++) + if (!trimStr(cmd_param_bufs_[k]).empty() || !specs[k].optional) lastNeeded = (int)k; bool complete = specs.size() <= 6; std::string built = cmd.name; - for (size_t k = 0, stop = 0; k < specs.size() && k < 6 && !stop; k++) { + for (int k = 0; k <= lastNeeded; k++) { std::string val = trimStr(cmd_param_bufs_[k]); if (val.empty()) { - if (specs[k].optional) stop = 1; // omit this + trailing optionals - else { built += " " + specs[k].raw; complete = false; } // required placeholder + built += " " + specs[k].raw; + complete = false; } else { if (specs[k].type == "string" && val.front() != '"' && val.front() != '\'' && val.front() != '[' && val.front() != '{')