Add support for string literals in Console::executeString, add implicit get/set for CVars

This commit is contained in:
Phillip Stephens 2018-06-12 19:03:29 -07:00
parent eff677ca20
commit 801214d9a8
4 changed files with 68 additions and 10 deletions

View File

@ -22,6 +22,7 @@ enum class EType : atUint8
enum EFlags
{
None = -1,
System = (1 << 0),
Game = (1 << 1),
Editor = (1 << 2),
@ -113,7 +114,7 @@ public:
void setModified();
EType type() const { return m_type; }
EFlags flags() const { return m_flags; }
EFlags flags() const { return (m_unlocked ? m_oldFlags : m_flags); }
/*!
* \brief Unlocks the CVar for writing if it is ReadOnly.

View File

@ -63,7 +63,7 @@ public:
}
std::vector<CVar*> archivedCVars() const;
std::vector<CVar*> cvars() const;
std::vector<CVar*> cvars(CVar::EFlags filter = CVar::EFlags::None) const;
void deserialize(CVar* cvar);
void serialize();

View File

@ -14,7 +14,7 @@ CVar* com_developer = nullptr;
CVar* com_configfile = nullptr;
CVar* com_enableCheats = nullptr;
static const std::regex cmdLineRegex("\\+(\\w+)=([\\w\\.\\-]+)");
static const std::regex cmdLineRegex("\\+([\\w\\.]+)=([\\w\\.\\-]+)");
CVarManager* CVarManager::m_instance = nullptr;
static logvisor::Module CVarLog("CVarManager");
@ -65,11 +65,12 @@ std::vector<CVar*> CVarManager::archivedCVars() const
return ret;
}
std::vector<CVar*> CVarManager::cvars() const
std::vector<CVar*> CVarManager::cvars(CVar::EFlags filter) const
{
std::vector<CVar*> ret;
for (const auto& pair : m_cvars)
ret.push_back(pair.second.get());
if (filter == CVar::EFlags::None || (pair.second->flags() & filter) != 0)
ret.push_back(pair.second.get());
return ret;
}
@ -201,7 +202,7 @@ void CVarManager::list(Console* con, const std::vector<std::string>& /*args*/)
for (const auto& cvar : m_cvars)
{
if (!cvar.second->isHidden())
con->report(Console::Level::Info, "%s: %s", cvar.first.c_str(), cvar.second->help().c_str());
con->report(Console::Level::Info, "%s: %s", cvar.second->name().data(), cvar.second->help().c_str());
}
}
@ -222,13 +223,20 @@ void CVarManager::setCVar(Console* con, const std::vector<std::string> &args)
}
const auto& cv = m_cvars[cvName];
std::string oldVal = cv->value();
std::string value = args[1];
auto it = args.begin() + 2;
for (; it != args.end(); ++it)
value += " " + *it;
/* Check to make sure we're not redundantly assigning the value */
if (cv->value() == value)
return;
if (!cv->fromLiteralToType(value))
con->report(Console::Level::Warning, "Unable to set cvar '%s' to value '%s'", args[0].c_str(), value.c_str());
con->report(Console::Level::Warning, "Unable to set cvar '%s' to value '%s'", cv->name().data(), value.c_str());
else
con->report(Console::Level::Info, "Set '%s' from '%s' to '%s'", cv->name().data(), oldVal.c_str(), value.c_str());
}
void CVarManager::getCVar(Console* con, const std::vector<std::string> &args)

View File

@ -1,6 +1,7 @@
#include "hecl/Console.hpp"
#include "hecl/CVarManager.hpp"
#include "hecl/CVar.hpp"
#include "hecl/hecl.hpp"
#include "athena/Utility.hpp"
namespace hecl
@ -54,10 +55,50 @@ void Console::executeString(const std::string& str)
for (std::string command : commands)
{
command = athena::utility::trim(command);
std::vector<std::string> args = athena::utility::split(command, ' ');
if (args.empty())
std::vector<std::string> tmpArgs = athena::utility::split(command, ' ');
if (tmpArgs.empty())
continue;
std::vector<std::string> args;
args.reserve(tmpArgs.size());
/* detect string literals */
bool isInLiteral = false;
std::string curLiteral;
int depth = 0;
for (std::string arg : tmpArgs)
{
if ((arg.front() == '\'' || arg.front() == '"'))
{
++depth;
isInLiteral = true;
curLiteral += arg;
}
else if ((arg.back() == '\'' || arg.back() == '"') && isInLiteral)
{
--depth;
curLiteral += arg;
args.push_back(curLiteral);
if (depth <= 0)
{
depth = 0;
isInLiteral = false;
curLiteral.clear();
}
}
else if (isInLiteral)
curLiteral += arg;
else
args.push_back(arg);
}
if (isInLiteral)
{
if ((curLiteral.back() != '\'' && curLiteral.back() != '"') || depth > 1)
{
report(Level::Warning, "Unterminated string literal");
return;
}
args.push_back(curLiteral);
}
std::string commandName = args[0];
args.erase(args.begin());
@ -80,6 +121,14 @@ void Console::executeString(const std::string& str)
}
m_commands[lowComName].m_func(this, args);
}
else if (const CVar* cv = m_cvarMgr->findCVar(commandName))
{
args.insert(args.begin(), commandName);
if (args.size() > 1)
m_cvarMgr->setCVar(this, args);
else
m_cvarMgr->getCVar(this, args);
}
else
report(Level::Error, "Command '%s' is not valid!", commandName.c_str());
}