|
@ -19,14 +19,19 @@ |
|
|
#include "GenericCommand.h" |
|
|
#include "GenericCommand.h" |
|
|
#include "Plugin.h" |
|
|
#include "Plugin.h" |
|
|
|
|
|
|
|
|
Jupiter::ArrayList<Jupiter::GenericCommand> o_genericCommands; |
|
|
using namespace Jupiter::literals; |
|
|
Jupiter::ArrayList<Jupiter::GenericCommand> *Jupiter::g_generic_commands = &o_genericCommands; |
|
|
|
|
|
|
|
|
constexpr const char GENERIC_COMMAND_WORD_DELIMITER = ' '; |
|
|
|
|
|
constexpr const char *GENERIC_COMMAND_WORD_DELIMITER_CS = " "; |
|
|
|
|
|
|
|
|
|
|
|
Jupiter::GenericCommandNamespace o_generic_commands; |
|
|
|
|
|
Jupiter::GenericCommandNamespace &Jupiter::g_generic_commands = o_generic_commands; |
|
|
|
|
|
|
|
|
/** GenericCommand */ |
|
|
/** GenericCommand */ |
|
|
|
|
|
|
|
|
Jupiter::GenericCommand::GenericCommand() |
|
|
Jupiter::GenericCommand::GenericCommand() |
|
|
{ |
|
|
{ |
|
|
o_genericCommands.add(this); |
|
|
Jupiter::GenericCommand::setNamespace(o_generic_commands); |
|
|
|
|
|
|
|
|
for (size_t index = 0; index != Jupiter::plugins->size(); ++index) |
|
|
for (size_t index = 0; index != Jupiter::plugins->size(); ++index) |
|
|
Jupiter::plugins->get(index)->OnGenericCommandAdd(*this); |
|
|
Jupiter::plugins->get(index)->OnGenericCommandAdd(*this); |
|
@ -34,18 +39,48 @@ Jupiter::GenericCommand::GenericCommand() |
|
|
|
|
|
|
|
|
Jupiter::GenericCommand::~GenericCommand() |
|
|
Jupiter::GenericCommand::~GenericCommand() |
|
|
{ |
|
|
{ |
|
|
size_t count = o_genericCommands.size(); |
|
|
// Inform the parent
|
|
|
while (count != 0) |
|
|
if (GenericCommand::m_parent == nullptr) |
|
|
if (o_genericCommands.get(--count) == this) |
|
|
GenericCommand::m_parent->removeCommand(*this); |
|
|
{ |
|
|
|
|
|
o_genericCommands.remove(count); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Notify plugins
|
|
|
for (size_t index = 0; index != Jupiter::plugins->size(); ++index) |
|
|
for (size_t index = 0; index != Jupiter::plugins->size(); ++index) |
|
|
Jupiter::plugins->get(index)->OnGenericCommandRemove(*this); |
|
|
Jupiter::plugins->get(index)->OnGenericCommandRemove(*this); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool Jupiter::GenericCommand::isNamespace() const |
|
|
|
|
|
{ |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Jupiter::GenericCommand::setNamespace(const Jupiter::ReadableString &in_namespace) |
|
|
|
|
|
{ |
|
|
|
|
|
if (in_namespace.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0) |
|
|
|
|
|
return; // We're already here
|
|
|
|
|
|
|
|
|
|
|
|
if (Jupiter::GenericCommand::m_parent == nullptr) |
|
|
|
|
|
return; // We have no parent to start from
|
|
|
|
|
|
|
|
|
|
|
|
Jupiter::GenericCommand *command = Jupiter::GenericCommand::m_parent->getCommand(in_namespace); |
|
|
|
|
|
if (command != nullptr && command->isNamespace()) |
|
|
|
|
|
Jupiter::GenericCommand::setNamespace(*reinterpret_cast<Jupiter::GenericCommandNamespace *>(command)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Jupiter::GenericCommand::setNamespace(Jupiter::GenericCommandNamespace &in_namespace) |
|
|
|
|
|
{ |
|
|
|
|
|
if (Jupiter::GenericCommand::m_parent != nullptr) // Remove from previous parent
|
|
|
|
|
|
Jupiter::GenericCommand::m_parent->removeCommand(*this); |
|
|
|
|
|
|
|
|
|
|
|
// Add to new parent
|
|
|
|
|
|
Jupiter::GenericCommand::m_parent = &in_namespace; |
|
|
|
|
|
in_namespace.addCommand(*this); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Jupiter::GenericCommandNamespace *Jupiter::GenericCommand::getNamespace() const |
|
|
|
|
|
{ |
|
|
|
|
|
return Jupiter::GenericCommand::m_parent; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** GenericCommand::ResponseLine */ |
|
|
/** GenericCommand::ResponseLine */ |
|
|
|
|
|
|
|
|
Jupiter::GenericCommand::ResponseLine::ResponseLine(const Jupiter::ReadableString &response_, GenericCommand::DisplayType type_) |
|
|
Jupiter::GenericCommand::ResponseLine::ResponseLine(const Jupiter::ReadableString &response_, GenericCommand::DisplayType type_) |
|
@ -61,14 +96,169 @@ Jupiter::GenericCommand::ResponseLine *Jupiter::GenericCommand::ResponseLine::se |
|
|
return this; |
|
|
return this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::GenericCommand *Jupiter::getGenericCommand(const Jupiter::ReadableString &trigger) |
|
|
/** GenericCommandNamespace */ |
|
|
|
|
|
|
|
|
|
|
|
Jupiter::GenericCommandNamespace::~GenericCommandNamespace() |
|
|
|
|
|
{ |
|
|
|
|
|
// Murder the children
|
|
|
|
|
|
Jupiter::GenericCommandNamespace::m_commands.emptyAndDelete(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Jupiter::GenericCommand::ResponseLine *Jupiter::GenericCommandNamespace::trigger(const Jupiter::ReadableString &in_input) |
|
|
|
|
|
{ |
|
|
|
|
|
GenericCommand *command; |
|
|
|
|
|
Jupiter::ReferenceString input(in_input); |
|
|
|
|
|
|
|
|
|
|
|
if (input.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0) // No parameters; list commands
|
|
|
|
|
|
return new Jupiter::GenericCommand::ResponseLine(Jupiter::GenericCommandNamespace::m_help, Jupiter::GenericCommand::DisplayType::PrivateSuccess); |
|
|
|
|
|
|
|
|
|
|
|
command = Jupiter::GenericCommandNamespace::getCommand(input.getWord(0, GENERIC_COMMAND_WORD_DELIMITER_CS)); |
|
|
|
|
|
if (command != nullptr) |
|
|
|
|
|
return command->trigger(input.gotoWord(1, GENERIC_COMMAND_WORD_DELIMITER_CS)); |
|
|
|
|
|
|
|
|
|
|
|
return new Jupiter::GenericCommand::ResponseLine(Jupiter::ReferenceString::empty, Jupiter::GenericCommand::DisplayType::PrivateError); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const Jupiter::ReadableString &Jupiter::GenericCommandNamespace::getHelp(const Jupiter::ReadableString ¶meters) |
|
|
|
|
|
{ |
|
|
|
|
|
static Jupiter::ReferenceString not_found = "Error: Command not found"_jrs; |
|
|
|
|
|
|
|
|
|
|
|
if (parameters.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0) // No parameters; list commands
|
|
|
|
|
|
return Jupiter::GenericCommandNamespace::m_help; |
|
|
|
|
|
|
|
|
|
|
|
Jupiter::ReferenceString input(parameters); |
|
|
|
|
|
GenericCommand *command; |
|
|
|
|
|
|
|
|
|
|
|
// Search for command
|
|
|
|
|
|
command = Jupiter::GenericCommandNamespace::getCommand(input.getWord(0, GENERIC_COMMAND_WORD_DELIMITER_CS)); |
|
|
|
|
|
if (command != nullptr) |
|
|
|
|
|
return command->getHelp(input.gotoWord(1, GENERIC_COMMAND_WORD_DELIMITER_CS)); |
|
|
|
|
|
|
|
|
|
|
|
// Command not found
|
|
|
|
|
|
return not_found; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool Jupiter::GenericCommandNamespace::isNamespace() const |
|
|
|
|
|
{ |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool Jupiter::GenericCommandNamespace::isUsing() const |
|
|
|
|
|
{ |
|
|
|
|
|
return m_using; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Jupiter::GenericCommandNamespace::setUsing(bool in_value) |
|
|
|
|
|
{ |
|
|
|
|
|
m_using = in_value; |
|
|
|
|
|
|
|
|
|
|
|
if (Jupiter::GenericCommand::m_parent != nullptr) |
|
|
|
|
|
Jupiter::GenericCommand::m_parent->updateHelp(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Jupiter::ArrayList<Jupiter::GenericCommand> Jupiter::GenericCommandNamespace::getCommands() const |
|
|
{ |
|
|
{ |
|
|
size_t count = o_genericCommands.size(); |
|
|
Jupiter::ArrayList<Jupiter::GenericCommand> result(Jupiter::GenericCommandNamespace::m_commands.size()); |
|
|
while (count != 0) |
|
|
Jupiter::GenericCommand *command; |
|
|
|
|
|
size_t tmp_index; |
|
|
|
|
|
|
|
|
|
|
|
for (size_t command_index = 0; command_index != Jupiter::GenericCommandNamespace::m_commands.size(); ++command_index) |
|
|
{ |
|
|
{ |
|
|
Jupiter::GenericCommand *cmd = o_genericCommands.get(--count); |
|
|
command = Jupiter::GenericCommandNamespace::m_commands.get(command_index); |
|
|
if (cmd->matches(trigger)) |
|
|
result.add(command); |
|
|
return cmd; |
|
|
|
|
|
|
|
|
if (command->isNamespace() && reinterpret_cast<GenericCommandNamespace *>(command)->isUsing()) |
|
|
|
|
|
{ |
|
|
|
|
|
// Add commands from namespace
|
|
|
|
|
|
Jupiter::ArrayList<Jupiter::GenericCommand> tmp = reinterpret_cast<GenericCommandNamespace *>(command)->getCommands(); |
|
|
|
|
|
|
|
|
|
|
|
for (tmp_index = 0; tmp_index != tmp.size(); ++tmp_index) |
|
|
|
|
|
result.add(tmp.get(tmp_index)); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Jupiter::GenericCommand *Jupiter::GenericCommandNamespace::getCommand(const Jupiter::ReadableString &in_command) const |
|
|
|
|
|
{ |
|
|
|
|
|
Jupiter::GenericCommand *command; |
|
|
|
|
|
size_t command_index, namespaces = 0; |
|
|
|
|
|
|
|
|
|
|
|
/** This is broken into 2 loops in order to insure that exact matches are ALWAYS prioritized over inexact matches */ |
|
|
|
|
|
|
|
|
|
|
|
// Search commands
|
|
|
|
|
|
for (command_index = 0; command_index != Jupiter::GenericCommandNamespace::m_commands.size(); ++command_index) |
|
|
|
|
|
{ |
|
|
|
|
|
command = Jupiter::GenericCommandNamespace::m_commands.get(command_index); |
|
|
|
|
|
|
|
|
|
|
|
if (command->matches(in_command)) // Command found
|
|
|
|
|
|
return command; |
|
|
|
|
|
else if (command->isNamespace() && reinterpret_cast<GenericCommandNamespace *>(command)->isUsing()) // Search namespace for matches
|
|
|
|
|
|
++namespaces; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// None found; check namespaces
|
|
|
|
|
|
for (command_index = 0; namespaces != 0; ++command_index) |
|
|
|
|
|
{ |
|
|
|
|
|
command = Jupiter::GenericCommandNamespace::m_commands.get(command_index); |
|
|
|
|
|
|
|
|
|
|
|
if (command->isNamespace() && reinterpret_cast<GenericCommandNamespace *>(command)->isUsing()) |
|
|
|
|
|
{ |
|
|
|
|
|
command = reinterpret_cast<GenericCommandNamespace *>(command)->getCommand(in_command); |
|
|
|
|
|
if (command != nullptr) // match found
|
|
|
|
|
|
return command; |
|
|
|
|
|
|
|
|
|
|
|
--namespaces; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return nullptr; |
|
|
return nullptr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Jupiter::GenericCommandNamespace::addCommand(Jupiter::GenericCommand &in_command) |
|
|
|
|
|
{ |
|
|
|
|
|
if (in_command.getNamespace() != this) |
|
|
|
|
|
in_command.setNamespace(*this); |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
Jupiter::GenericCommandNamespace::m_commands.add(&in_command); |
|
|
|
|
|
Jupiter::GenericCommandNamespace::updateHelp(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Jupiter::GenericCommandNamespace::removeCommand(Jupiter::GenericCommand &in_command) |
|
|
|
|
|
{ |
|
|
|
|
|
for (size_t index = 0; index != Jupiter::GenericCommandNamespace::m_commands.size(); ++index) |
|
|
|
|
|
if (Jupiter::GenericCommandNamespace::m_commands.get(index) == &in_command) |
|
|
|
|
|
{ |
|
|
|
|
|
Jupiter::GenericCommandNamespace::m_commands.remove(index); |
|
|
|
|
|
Jupiter::GenericCommandNamespace::updateHelp(); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Jupiter::GenericCommandNamespace::removeCommand(const Jupiter::ReadableString &in_command) |
|
|
|
|
|
{ |
|
|
|
|
|
for (size_t index = 0; index != Jupiter::GenericCommandNamespace::m_commands.size(); ++index) |
|
|
|
|
|
if (Jupiter::GenericCommandNamespace::m_commands.get(index)->matches(in_command)) |
|
|
|
|
|
{ |
|
|
|
|
|
Jupiter::GenericCommandNamespace::m_commands.remove(index); |
|
|
|
|
|
Jupiter::GenericCommandNamespace::updateHelp(); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Jupiter::GenericCommandNamespace::updateHelp() |
|
|
|
|
|
{ |
|
|
|
|
|
Jupiter::ArrayList<Jupiter::GenericCommand> commands = Jupiter::GenericCommandNamespace::getCommands(); |
|
|
|
|
|
Jupiter::StringL tmp_help(commands.size() * 8); |
|
|
|
|
|
|
|
|
|
|
|
for (size_t index = 0; index != commands.size(); ++index) |
|
|
|
|
|
{ |
|
|
|
|
|
tmp_help += commands.get(index)->getTrigger(); |
|
|
|
|
|
tmp_help += ' '; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Jupiter::GenericCommandNamespace::m_help = tmp_help; |
|
|
|
|
|
} |
|
|