fix(console): don't silently drop a filled param after an empty optional
The builder's "omit trailing optionals" loop stopped at the FIRST empty optional, which discarded any later field the user had filled — e.g. setban with bantime empty but absolute=true built `setban "ip" "add"`, dropping the typed `true`, and (worse) left Insert & run enabled so it ran a command that ignored the input. Include fields up to the last one that is filled or required; only genuinely trailing empty optionals are dropped. A gap (an empty field before a later filled one) keeps its placeholder and marks the command incomplete, so Insert & run disables and nothing typed is lost. Found by an adversarial pass over all 82 param templates. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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() != '{')
|
||||
|
||||
Reference in New Issue
Block a user