diff options
Diffstat (limited to 'src/crsm.cpp')
| -rw-r--r-- | src/crsm.cpp | 108 |
1 files changed, 96 insertions, 12 deletions
diff --git a/src/crsm.cpp b/src/crsm.cpp index aa1ef13..e187123 100644 --- a/src/crsm.cpp +++ b/src/crsm.cpp @@ -245,6 +245,21 @@ bool CRSM::watchdog(const QString& id) return false; } +QString CRSM::cmdErrorText(const QString& command, const ClientInfo& client, bool& ret) +{ + QString retText; + QStringList corrections; + if(!(ret = cmd(command, client, corrections))) + { + retText = "Unbekannter Befehl: \"" + command + "\"!\n"; + if(!corrections.isEmpty()) + { + retText += "Meintest du: " + corrections.join(", ") + "?\n"; + } + } + return retText; +} + bool CRSM::clientMessage(ClientInfo& client, const QString& message, ClonkOutputInterface::MessageType type, const QTime& time) { bool isMeMessage = (type == Action); @@ -281,11 +296,16 @@ bool CRSM::clientMessage(ClientInfo& client, const QString& message, ClonkOutput QString command = getCommand(message); if(!command.isEmpty()) { - if(!cmd(command, client)) + bool ret; + const QString& txt = cmdErrorText(command, client, ret); + if(ret) + { + return true; + } + else { - respond(client, "Unbekannter Befehl: \"" + command + "\"!\n"); + respond(client, txt); } - return true; } } } @@ -699,7 +719,8 @@ void CRSM::newManagementData() if(data.at(0) == '/') { QString command = data.mid(1).trimmed(); - if(cmd(command, ClientInfo::managementClient(conn))) + QStringList corrections; + if(cmd(command, ClientInfo::managementClient(conn), corrections)) { continue; } @@ -1431,12 +1452,58 @@ bool CRSM::cmdExists(const QString &name, ClientInterface interface) return cmds.contains(name) && cmds.value(name).interfaces & interface; } -CmdFunctionRef* CRSM::findCommand(const QString &cmd, ClientInterface interface, QString &args) +QStringList CRSM::guessCmd(const QString& name, ClientInterface interface) +{ + int minDistance = -1; + QString minDistanceCmd; + QStringList minDistanceCmds; + + auto applyDistance = [&name, &minDistance, &minDistanceCmd, &minDistanceCmds](const QString& cmdName) + { + int distance = Util::damerauLevenshteinDistance(name, cmdName); + if(minDistance == -1 || distance < minDistance) + { + minDistance = distance; + minDistanceCmd = cmdName; + minDistanceCmds.clear(); + } + else if(minDistance == distance && !minDistanceCmds.contains(cmdName)) + { + minDistanceCmds.append(cmdName); + } + }; + + for(const auto& cmd : cmds) + { + if(cmd.interfaces & interface) + { + applyDistance(cmd.name); + } + } + + for(const auto& alias : Config.CRSM.CommandAlias.keys()) + { + applyDistance(alias); + } + + if(!minDistanceCmds.contains(minDistanceCmd)) + { + minDistanceCmds.append(minDistanceCmd); + } + + if(minDistanceCmds.length() == 1 && minDistance >= std::min(3, name.length() - 1)) + { + minDistanceCmds.clear(); + } + return minDistanceCmds; +} + +CmdFunctionRef* CRSM::findCommand(const QString &cmd, ClientInterface interface, QString &args, QStringList& corrections) { - return findCommand(cmd.split(QRegularExpression(R"(\s)"), QString::KeepEmptyParts), interface, args); + return findCommand(cmd.split(QRegularExpression(R"(\s)"), QString::KeepEmptyParts), interface, args, corrections); } -CmdFunctionRef* CRSM::findCommand(QStringList&& cmd, ClientInterface interface, QString &realCmd) +CmdFunctionRef* CRSM::findCommand(QStringList&& cmd, ClientInterface interface, QString &realCmd, QStringList& corrections) { if(cmd.length() > 0) { @@ -1457,8 +1524,23 @@ CmdFunctionRef* CRSM::findCommand(QStringList&& cmd, ClientInterface interface, } else { + const QStringList& guesses = guessCmd(cmdPart, interface); + if(guesses.length() == 1) + { + QString guess = guesses.first(); + substituteCommandAlias(guess); + if(cmdExists(guess, interface)) + { + return &cmds[guess]; + } + } + else if(guesses.length() > 1) + { + corrections.append(guesses); + } + cmd.removeLast(); - return findCommand(std::move(cmd), interface, realCmd); + return findCommand(std::move(cmd), interface, realCmd, corrections); } } } @@ -1468,12 +1550,12 @@ CmdFunctionRef* CRSM::findCommand(QStringList&& cmd, ClientInterface interface, } } -bool CRSM::cmd(const QString& cmd, const ClientInfo &client) +bool CRSM::cmd(const QString& cmd, const ClientInfo &client, QStringList& corrections) { Log.commandLog(cmd, client, false); CmdFunctionRef* cmdPtr; QString realCmd = cmd; - if((cmdPtr = findCommand(cmd, client.interface, realCmd)) != nullptr) + if((cmdPtr = findCommand(cmd, client.interface, realCmd, corrections)) != nullptr) { CmdFunctionRef cmdRef = *cmdPtr; QString args = cmd.mid(realCmd.length()).trimmed(); @@ -2327,9 +2409,11 @@ void CRSM::handleIrcMessage(const ClientInfo &client, QString message, const QSt if(!command.isEmpty()) { - if(!cmd(command, client)) + bool ret; + const QString& txt = cmdErrorText(command, client, ret); + if(!ret) { - respond(client, "Unbekannter Befehl: \"" + command + "\"!", (privateMessage ? RespondType::PrivateNotice : RespondType::Normal), true); + respond(client, txt, (privateMessage ? RespondType::PrivateNotice : RespondType::Normal), true); } } |
