How did I get here?
This commit is contained in:
146
src/console/Console.cpp
Normal file
146
src/console/Console.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
// Copyright (c) 2025 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "Console.hpp"
|
||||
#include "assert/Assert.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
Console::Console(void) :
|
||||
commands(),
|
||||
variables(),
|
||||
buffer()
|
||||
{
|
||||
}
|
||||
|
||||
void Console::registerCommand(
|
||||
const std::string &cmd,
|
||||
const std::function<void(std::vector<std::string>&)> &callback
|
||||
) {
|
||||
assertTrue(cmd.length() > 0, "cmd length must be > 0");
|
||||
assertTrue(callback != nullptr, "callback must not be null");
|
||||
|
||||
this->commands[cmd] = callback;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Console::registerVariable(
|
||||
const std::string &var,
|
||||
const std::function<T()> &getter,
|
||||
const std::function<void(const T &)> &setter
|
||||
) {
|
||||
assertTrue(var.length() > 0, "var length must be > 0");
|
||||
assertTrue(getter != nullptr, "getter must not be null");
|
||||
assertTrue(setter != nullptr, "setter must not be null");
|
||||
|
||||
this->variables[var] = std::make_pair(getter, setter);
|
||||
}
|
||||
|
||||
void Console::update() {
|
||||
enum class ParseState { FIND_CMD, FIND_ARG, COMMAND, ARG, ARG_QUOTED };
|
||||
|
||||
for (const auto &cmd : buffer) {
|
||||
std::string cmdName;
|
||||
std::vector<std::string> args;
|
||||
ParseState state = ParseState::FIND_CMD;
|
||||
|
||||
std::string buff;
|
||||
for(size_t i = 0; i < cmd.length(); i++) {
|
||||
char_t c = cmd[i];
|
||||
|
||||
switch(state) {
|
||||
case ParseState::FIND_CMD:
|
||||
if(isspace(c)) continue;
|
||||
state = ParseState::COMMAND;
|
||||
buff += c;
|
||||
break;
|
||||
|
||||
case ParseState::FIND_ARG:
|
||||
if(isspace(c)) continue;
|
||||
if(c == '\"') {
|
||||
state = ParseState::ARG_QUOTED;
|
||||
break;
|
||||
}
|
||||
state = ParseState::ARG;
|
||||
buff += c;
|
||||
break;
|
||||
|
||||
case ParseState::COMMAND:
|
||||
if(isspace(c)) {
|
||||
cmdName = buff;
|
||||
buff.clear();
|
||||
state = ParseState::FIND_ARG;
|
||||
break;
|
||||
}
|
||||
buff += c;
|
||||
break;
|
||||
|
||||
case ParseState::ARG:
|
||||
if(isspace(c)) {
|
||||
args.push_back(buff);
|
||||
buff.clear();
|
||||
state = ParseState::FIND_ARG;
|
||||
break;
|
||||
}
|
||||
buff += c;
|
||||
break;
|
||||
|
||||
case ParseState::ARG_QUOTED:
|
||||
if(c == '\"') {
|
||||
args.push_back(buff);
|
||||
buff.clear();
|
||||
state = ParseState::FIND_ARG;
|
||||
break;
|
||||
}
|
||||
buff += c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(buff.length() > 0) {
|
||||
if(state == ParseState::COMMAND) {
|
||||
cmdName = buff;
|
||||
} else {
|
||||
args.push_back(buff);
|
||||
}
|
||||
}
|
||||
|
||||
// Find command
|
||||
auto itCmd = commands.find(cmdName);
|
||||
if(itCmd == commands.end()) {
|
||||
// Find variable
|
||||
auto itVar = variables.find(cmdName);
|
||||
if(itVar == variables.end()) {
|
||||
std::cout << "Console: Unknown command or variable '" << cmdName << "'" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Variable get/set
|
||||
printf("Console: Variable '%s' ", cmdName.c_str());
|
||||
continue;
|
||||
}
|
||||
itCmd->second(args);
|
||||
}
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
void Console::exec(const std::string &str) {
|
||||
// Split strings by command seperator
|
||||
std::istringstream iss(str);
|
||||
std::string token;
|
||||
while(std::getline(iss, token, COMMAND_SEPARATOR)) {
|
||||
// Seperate by newlines too
|
||||
std::istringstream lineIss(token);
|
||||
std::string lineToken;
|
||||
while(std::getline(lineIss, lineToken)) {
|
||||
if(lineToken.length() == 0) continue;
|
||||
buffer.push_back(lineToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console::~Console(void) {
|
||||
|
||||
}
|
Reference in New Issue
Block a user