[Orxonox-commit 2533] r7238 - in code/branches/consolecommands3/src/libraries: core/command util
landauf at orxonox.net
landauf at orxonox.net
Sat Aug 28 16:48:48 CEST 2010
Author: landauf
Date: 2010-08-28 16:48:48 +0200 (Sat, 28 Aug 2010)
New Revision: 7238
Modified:
code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.cc
code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.h
code/branches/consolecommands3/src/libraries/core/command/TclBind.cc
code/branches/consolecommands3/src/libraries/util/StringUtils.cc
code/branches/consolecommands3/src/libraries/util/StringUtils.h
Log:
added a function to compute the Levenshtein distance between two strings to StringUtils.
used this in CommandEvaluation to correct misspelled commands (not automatically though, just to print a suggestion to the user)
Modified: code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.cc 2010-08-28 14:09:41 UTC (rev 7237)
+++ code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.cc 2010-08-28 14:48:48 UTC (rev 7238)
@@ -123,14 +123,11 @@
default: return (*this->execCommand_->getExecutor())(this->param_[0], this->param_[1], this->param_[2], this->param_[3], this->param_[4]);
}
}
- else
- {
- COUT(5) << "CE_execute: " << this->string_ << "\n";
- return this->execCommand_->getExecutor()->parse(this->tokens_.subSet(this->execArgumentsOffset_), error, " ");
- }
+ else if (error)
+ *error = CommandExecutor::Incomplete;
}
- else
- return MT_Type::Null;
+
+ return MT_Type::Null;
}
int CommandEvaluation::evaluateParams(bool bPrintError)
@@ -212,9 +209,8 @@
else
{
std::string groupLC = getLowercase(this->getToken(0));
- std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommands().begin();
- for ( ; it_group != ConsoleCommand::getCommands().end(); ++it_group)
- if (getLowercase(it_group->first) == groupLC)
+ for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandsLC().begin(); it_group != ConsoleCommand::getCommandsLC().end(); ++it_group)
+ if (it_group->first == groupLC)
return std::string("Error: There is no command in group \"") + this->getToken(0) + "\" starting with \"" + this->getToken(1) + "\".";
return std::string("Error: There is no command starting with \"") + this->getToken(0) + "\".";
@@ -222,6 +218,49 @@
}
}
+ std::string CommandEvaluation::getCommandSuggestion() const
+ {
+ std::string token0_LC = getLowercase(this->getToken(0));
+ std::string token1_LC = getLowercase(this->getToken(1));
+
+ std::string nearestCommand;
+ unsigned int nearestDistance = (unsigned int)-1;
+
+ for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandsLC().begin(); it_group != ConsoleCommand::getCommandsLC().end(); ++it_group)
+ {
+ if (it_group->first != "")
+ {
+ for (std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); ++it_name)
+ {
+ std::string command = it_group->first + " " + it_name->first;
+ unsigned int distance = getLevenshteinDistance(command, token0_LC + " " + token1_LC);
+ if (distance < nearestDistance)
+ {
+ nearestCommand = command;
+ nearestDistance = distance;
+ }
+ }
+ }
+ }
+
+ std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandsLC().find("");
+ if (it_group != ConsoleCommand::getCommandsLC().end())
+ {
+ for (std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); ++it_name)
+ {
+ std::string command = it_name->first;
+ unsigned int distance = getLevenshteinDistance(command, token0_LC);
+ if (distance < nearestDistance)
+ {
+ nearestCommand = command;
+ nearestDistance = distance;
+ }
+ }
+ }
+
+ return nearestCommand;
+ }
+
void CommandEvaluation::retrievePossibleArguments()
{
this->bPossibleArgumentsRetrieved_ = true;
Modified: code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.h
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.h 2010-08-28 14:09:41 UTC (rev 7237)
+++ code/branches/consolecommands3/src/libraries/core/command/CommandEvaluation.h 2010-08-28 14:48:48 UTC (rev 7238)
@@ -53,6 +53,8 @@
std::string complete();
std::string hint();
+ std::string getCommandSuggestion() const;
+
int evaluateParams(bool bPrintError = false);
inline bool isValid() const
Modified: code/branches/consolecommands3/src/libraries/core/command/TclBind.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/core/command/TclBind.cc 2010-08-28 14:09:41 UTC (rev 7237)
+++ code/branches/consolecommands3/src/libraries/core/command/TclBind.cc 2010-08-28 14:48:48 UTC (rev 7238)
@@ -134,7 +134,8 @@
const std::string& command = stripEnclosingBraces(args.get());
int error;
- const std::string& result = CommandExecutor::query(command, &error, false);
+ CommandEvaluation evaluation = CommandExecutor::evaluate(command);
+ const std::string& result = evaluation.query(&error);
switch (error)
{
case CommandExecutor::Error: COUT(1) << "Error: Can't execute command \"" << command << "\", command doesn't exist. (B)" << std::endl; break;
@@ -143,6 +144,9 @@
case CommandExecutor::Denied: COUT(1) << "Error: Can't execute command \"" << command << "\", access denied. (B)" << std::endl; break;
}
+ if (error == CommandExecutor::Error)
+ COUT(3) << "Did you mean \"" << evaluation.getCommandSuggestion() << "\"?" << std::endl;
+
return result;
}
Modified: code/branches/consolecommands3/src/libraries/util/StringUtils.cc
===================================================================
--- code/branches/consolecommands3/src/libraries/util/StringUtils.cc 2010-08-28 14:09:41 UTC (rev 7237)
+++ code/branches/consolecommands3/src/libraries/util/StringUtils.cc 2010-08-28 14:48:48 UTC (rev 7238)
@@ -513,7 +513,7 @@
@param replacement Replacement character
@return Number of replacements
*/
- _UtilExport size_t replaceCharacters(std::string& str, char target, char replacement)
+ size_t replaceCharacters(std::string& str, char target, char replacement)
{
size_t j = 0;
for (size_t i = 0; i < str.size(); ++i)
@@ -526,4 +526,36 @@
}
return j;
}
+
+ /**
+ @brief Calculates the Levenshtein distance between two strings.
+
+ The Levenshtein distance is defined by the number of transformations needed to convert str1
+ into str2. Possible transformations are substituted, added, or removed characters.
+ */
+ unsigned int getLevenshteinDistance(const std::string& str1, const std::string& str2)
+ {
+ size_t cols = str1.size() + 1;
+ size_t rows = str2.size() + 1;
+ int matrix[rows][cols];
+
+ for (size_t r = 0; r < rows; ++r)
+ for (size_t c = 0; c < cols; ++c)
+ matrix[r][c] = 0;
+
+ for (size_t i = 1; i < cols; ++i)
+ matrix[0][i] = i;
+ for (size_t i = 1; i < rows; ++i)
+ matrix[i][0] = i;
+
+ for (size_t r = 1; r < rows; ++r)
+ for (size_t c = 1; c < cols; ++c)
+ matrix[r][c] = (str1[c-1] != str2[r-1]);
+
+ for (size_t r = 1; r < rows; ++r)
+ for (size_t c = 1; c < cols; ++c)
+ matrix[r][c] = std::min(std::min(matrix[r-1][c] + 1, matrix[r][c-1] + 1), matrix[r-1][c-1] + (str1[c-1] != str2[r-1]));
+
+ return matrix[rows-1][cols-1];
+ }
}
Modified: code/branches/consolecommands3/src/libraries/util/StringUtils.h
===================================================================
--- code/branches/consolecommands3/src/libraries/util/StringUtils.h 2010-08-28 14:09:41 UTC (rev 7237)
+++ code/branches/consolecommands3/src/libraries/util/StringUtils.h 2010-08-28 14:48:48 UTC (rev 7238)
@@ -42,42 +42,44 @@
extern _UtilExport std::string BLANKSTRING;
_UtilExport std::string getUniqueNumberString();
- _UtilExport void strip(std::string* str);
- _UtilExport std::string getStripped(const std::string& str);
+ _UtilExport void strip(std::string* str);
+ _UtilExport std::string getStripped(const std::string& str);
- _UtilExport std::string removeTrailingWhitespaces(const std::string& str);
+ _UtilExport std::string removeTrailingWhitespaces(const std::string& str);
- _UtilExport size_t getNextQuote(const std::string& str, size_t start);
- _UtilExport bool isBetweenQuotes(const std::string& str, size_t pos);
+ _UtilExport size_t getNextQuote(const std::string& str, size_t start);
+ _UtilExport bool isBetweenQuotes(const std::string& str, size_t pos);
- _UtilExport bool hasStringBetweenQuotes(const std::string& str);
- _UtilExport std::string getStringBetweenQuotes(const std::string& str);
+ _UtilExport bool hasStringBetweenQuotes(const std::string& str);
+ _UtilExport std::string getStringBetweenQuotes(const std::string& str);
- _UtilExport std::string stripEnclosingQuotes(const std::string& str);
- _UtilExport std::string stripEnclosingBraces(const std::string& str);
+ _UtilExport std::string stripEnclosingQuotes(const std::string& str);
+ _UtilExport std::string stripEnclosingBraces(const std::string& str);
- _UtilExport bool isEmpty(const std::string& str);
- _UtilExport bool isComment(const std::string& str);
- _UtilExport bool isNumeric(const std::string& str);
+ _UtilExport bool isEmpty(const std::string& str);
+ _UtilExport bool isComment(const std::string& str);
+ _UtilExport bool isNumeric(const std::string& str);
- _UtilExport std::string addSlashes(const std::string& str);
- _UtilExport std::string removeSlashes(const std::string& str);
+ _UtilExport std::string addSlashes(const std::string& str);
+ _UtilExport std::string removeSlashes(const std::string& str);
- _UtilExport void lowercase(std::string* str);
- _UtilExport std::string getLowercase(const std::string& str);
+ _UtilExport void lowercase(std::string* str);
+ _UtilExport std::string getLowercase(const std::string& str);
- _UtilExport void uppercase(std::string* str);
- _UtilExport std::string getUppercase(const std::string& str);
+ _UtilExport void uppercase(std::string* str);
+ _UtilExport std::string getUppercase(const std::string& str);
- _UtilExport int nocaseCmp(const std::string& s1, const std::string& s2);
- _UtilExport int nocaseCmp(const std::string& s1, const std::string& s2, size_t len);
+ _UtilExport int nocaseCmp(const std::string& s1, const std::string& s2);
+ _UtilExport int nocaseCmp(const std::string& s1, const std::string& s2, size_t len);
- _UtilExport bool hasComment(const std::string& str);
- _UtilExport std::string getComment(const std::string& str);
- _UtilExport size_t getCommentPosition(const std::string& str);
- _UtilExport size_t getNextCommentPosition(const std::string& str, size_t start = 0);
+ _UtilExport bool hasComment(const std::string& str);
+ _UtilExport std::string getComment(const std::string& str);
+ _UtilExport size_t getCommentPosition(const std::string& str);
+ _UtilExport size_t getNextCommentPosition(const std::string& str, size_t start = 0);
- _UtilExport size_t replaceCharacters(std::string& str, char target, char replacement);
+ _UtilExport size_t replaceCharacters(std::string& str, char target, char replacement);
+
+ _UtilExport unsigned int getLevenshteinDistance(const std::string& str1, const std::string& str2);
}
#endif /* _StringUtils_H__ */
More information about the Orxonox-commit
mailing list