Add ParseCommand implementation

This commit is contained in:
Lion Kortlepel 2022-02-15 15:34:33 +01:00
parent a44684f6e7
commit 8ff94a57d7
No known key found for this signature in database
GPG Key ID: 4322FF2B4C71259B
2 changed files with 60 additions and 0 deletions

View File

@ -4,6 +4,9 @@
#include "commandline.h"
#include <atomic>
#include <fstream>
#include <string>
#include <tuple>
#include <vector>
class TLuaEngine;
@ -29,6 +32,9 @@ private:
void Command_Say(const std::string& cmd);
void Command_List(const std::string& cmd);
void Command_Status(const std::string& cmd);
void Command_Settings(const std::string& cmd);
static std::tuple<std::string, std::vector<std::string>> ParseCommand(const std::string& cmd);
Commandline mCommandline;
std::vector<std::string> mCachedLuaHistory;

View File

@ -156,6 +156,7 @@ void TConsole::Command_Help(const std::string&) {
list lists all players and info about them
say <message> sends the message to all players in chat
lua [state id] switches to lua, optionally into a specific state id's lua
settings [command] sets or gets settings for the server, run `settings help` for more info
status how the server is doing and what it's up to)";
Application::Console().WriteRaw("BeamMP-Server Console: " + std::string(sHelpString));
}
@ -195,6 +196,59 @@ void TConsole::Command_Kick(const std::string& cmd) {
}
}
std::tuple<std::string, std::vector<std::string>> TConsole::ParseCommand(const std::string& CommandWithArgs) {
// Algorithm designed and implemented by Lion Kortlepel (c) 2022
// It correctly splits arguments, including respecting single and double quotes, as well as backticks
auto End_i = CommandWithArgs.find_first_of(' ');
std::string Command = CommandWithArgs.substr(0, End_i);
std::string ArgsStr = CommandWithArgs.substr(End_i);
std::vector<std::string> Args;
char* PrevPtr = ArgsStr.data();
char* Ptr = ArgsStr.data();
const char* End = ArgsStr.data() + ArgsStr.size();
while (Ptr != End) {
std::string Arg = "";
// advance while space
while (Ptr != End && std::isspace(*Ptr))
++Ptr;
PrevPtr = Ptr;
// advance while NOT space, also handle quotes
while (Ptr != End && !std::isspace(*Ptr)) {
// TODO: backslash escaping quotes
for (char Quote : { '"', '\'', '`' }) {
if (*Ptr == Quote) {
// seek if there's a closing quote
// if there is, go there and continue, otherwise ignore
char* Seeker = Ptr + 1;
while (Seeker != End && *Seeker != Quote)
++Seeker;
if (Seeker != End) {
// found closing quote
Ptr = Seeker;
}
break; // exit for loop
}
}
++Ptr;
}
Arg = std::string(PrevPtr, Ptr - PrevPtr);
// remove quotes if enclosed in quotes
for (char Quote : { '"', '\'', '`' }) {
if (!Arg.empty() && Arg.at(0) == Quote && Arg.at(Arg.size() - 1) == Quote) {
Arg = Arg.substr(1, Arg.size() - 2);
break;
}
}
if (!Arg.empty()) {
Args.push_back(Arg);
}
}
return { Command, Args };
}
void TConsole::Command_Settings(const std::string& cmd) {
}
void TConsole::Command_Say(const std::string& cmd) {
if (cmd.size() > 3) {
auto Message = cmd.substr(4);