diff --git a/cmake/MMseqsSetupDerivedTarget.cmake b/cmake/MMseqsSetupDerivedTarget.cmake index a5a85fa90..f5248d8d8 100644 --- a/cmake/MMseqsSetupDerivedTarget.cmake +++ b/cmake/MMseqsSetupDerivedTarget.cmake @@ -1,12 +1,16 @@ include(AppendTargetProperty) function (mmseqs_setup_derived_target TARGET) - get_target_property(COMPILE_TMP mmseqs-framework COMPILE_FLAGS) - get_target_property(LINK_TMP mmseqs-framework LINK_FLAGS) - get_target_property(DEF_TMP mmseqs-framework COMPILE_DEFINITIONS) - get_target_property(INCL_TMP mmseqs-framework INCLUDE_DIRECTORIES) + set(SOURCE "${ARGN}") + if(NOT SOURCE) + set(SOURCE "mmseqs-framework") + endif() + get_target_property(COMPILE_TMP ${SOURCE} COMPILE_FLAGS) + get_target_property(LINK_TMP ${SOURCE} LINK_FLAGS) + get_target_property(DEF_TMP ${SOURCE} COMPILE_DEFINITIONS) + get_target_property(INCL_TMP ${SOURCE} INCLUDE_DIRECTORIES) - target_link_libraries(${TARGET} mmseqs-framework) + target_link_libraries(${TARGET} ${SOURCE}) append_target_property(${TARGET} COMPILE_FLAGS ${COMPILE_TMP}) append_target_property(${TARGET} LINK_FLAGS ${LINK_TMP}) set_property(TARGET ${TARGET} APPEND PROPERTY COMPILE_DEFINITIONS ${DEF_TMP}) diff --git a/src/commons/Application.cpp b/src/commons/Application.cpp index c99da844e..aa29c9c54 100644 --- a/src/commons/Application.cpp +++ b/src/commons/Application.cpp @@ -16,31 +16,30 @@ extern const char *show_extended_help; extern const char *show_bash_info; extern bool hide_base_commands; -extern std::vector commands; -extern std::vector baseCommands; +extern std::vector*> commands; extern std::vector categories; extern void (*validatorUpdate)(void); +extern void (*initCommands)(void); -Command *getCommandByName(const char *s) { - for (size_t i = 0; i < commands.size(); i++) { - Command &p = commands[i]; - if (!strcmp(s, p.cmd)) - return &p; - } - +const Command* getCommandByName(const char *s) { // allow base commands also to be called with a prefix, e.g. "mmseqs base:createdb" // this allows inheriting programs to find shadowed base modules const char *prefix = "base:"; const char *check = strncmp(s, prefix, strlen(prefix)) == 0 ? s + strlen(prefix) : s; - for (size_t i = 0; i < baseCommands.size(); i++) { - Command &p = baseCommands[i]; - if (!strcmp(check, p.cmd)) - return &p; + + for (size_t i = 0; i < commands.size(); i++) { + for (size_t j = 0; j < commands[i]->size(); j++) { + const Command &p = (*commands[i])[j]; + if (!strcmp(s, p.cmd)) + return &p; + if (i == 0 && !strcmp(check, p.cmd)) + return &p; + } } return NULL; } -int runCommand(Command *p, int argc, const char **argv) { +int runCommand(const Command *p, int argc, const char **argv) { Timer timer; int status = p->commandFunction(argc, argv, *p); Debug(Debug::INFO) << "Time for processing: " << timer.lap() << "\n"; @@ -57,21 +56,17 @@ void printUsage(bool showExtended) { std::vector showCategoryHeader(categories.size(), 0); for (size_t i = 0; i < categories.size(); ++i) { - for (size_t j = 0; j < commands.size(); j++) { - Command &p = commands[j]; - if (p.mode & categories[i].mode) { - showCategoryHeader[i] = 1; - break; - } - } + size_t start = 0; if (hide_base_commands) { - continue; - } - for (size_t j = 0; j < baseCommands.size(); j++) { - Command &p = baseCommands[j]; - if (p.mode & categories[i].mode) { - showCategoryHeader[i] = 1; - break; + start = commands.size() - 1; + } + for (size_t j = start; j < commands.size(); j++) { + for (size_t k = 0; k < commands[j]->size(); k++) { + const Command &p = (*commands[j])[k]; + if (p.mode & categories[i].mode) { + showCategoryHeader[i] = 1; + break; + } } } } @@ -93,24 +88,18 @@ void printUsage(bool showExtended) { usage << "\n" << std::setw(20) << categories[i].title << "\n"; for (size_t j = 0; j < commands.size(); j++) { - struct Command &p = commands[j]; - if (showExtended == false && (p.mode & COMMAND_EXPERT) != 0) { - continue; - } - if (p.mode & categories[i].mode) { - usage << std::left << std::setw(20) << " " + std::string(p.cmd) << "\t" << p.description << "\n"; + size_t start = 0; + if (hide_base_commands) { + start = commands.size() - 1; } - } - if (hide_base_commands) { - continue; - } - for (size_t j = 0; j < baseCommands.size(); j++) { - struct Command &p = baseCommands[j]; - if (showExtended == false && (p.mode & COMMAND_EXPERT) != 0) { - continue; - } - if (p.mode & categories[i].mode) { - usage << std::left << std::setw(20) << " " + std::string(p.cmd) << "\t" << p.description << "\n"; + for (size_t k = start; k < commands[j]->size(); k++) { + const Command &p = (*commands[j])[k]; + if (showExtended == false && (p.mode & COMMAND_EXPERT) != 0) { + continue; + } + if (p.mode & categories[i].mode) { + usage << std::left << std::setw(20) << " " + std::string(p.cmd) << "\t" << p.description << "\n"; + } } } } @@ -130,14 +119,12 @@ int shellcompletion(int argc, const char **argv) { // mmseqs programs if (argc == 0) { for (size_t i = 0; i < commands.size(); i++) { - struct Command &p = commands[i]; - if (p.mode & COMMAND_HIDDEN) - continue; - Debug(Debug::INFO) << p.cmd << " "; - } - if (hide_base_commands == false) { - for (size_t i = 0; i < baseCommands.size(); i++) { - struct Command &p = baseCommands[i]; + size_t start = 0; + if (hide_base_commands) { + start = commands.size() - 1; + } + for (size_t j = start; j < commands[i]->size(); j++) { + const Command &p = (*commands[i])[j]; if (p.mode & COMMAND_HIDDEN) continue; Debug(Debug::INFO) << p.cmd << " "; @@ -149,30 +136,19 @@ int shellcompletion(int argc, const char **argv) { // mmseqs parameters for given program if (argc == 1) { for (size_t i = 0; i < commands.size(); i++) { - struct Command &p = commands[i]; - if (strcmp(p.cmd, argv[0]) != 0) { - continue; - } - if (p.params == NULL) { - continue; + size_t start = 0; + if (hide_base_commands) { + start = commands.size() - 1; } - for (std::vector::const_iterator it = p.params->begin(); it != p.params->end(); ++it) { - Debug(Debug::INFO) << (*it)->name << " "; - } - Debug(Debug::INFO) << "\n"; - break; - } - if (hide_base_commands == false) { - for (size_t i = 0; i < baseCommands.size(); i++) { - struct Command &p = baseCommands[i]; + for (size_t j = start; j < commands[i]->size(); j++) { + const Command &p = (*commands[i])[j]; if (strcmp(p.cmd, argv[0]) != 0) { continue; } if (p.params == NULL) { continue; } - for (std::vector::const_iterator it = p.params->begin(); - it != p.params->end(); ++it) { + for (std::vector::const_iterator it = p.params->begin(); it != p.params->end(); ++it) { Debug(Debug::INFO) << (*it)->name << " "; } Debug(Debug::INFO) << "\n"; @@ -185,6 +161,10 @@ int shellcompletion(int argc, const char **argv) { } int main(int argc, const char **argv) { + if (initCommands != NULL) { + initCommands(); + } + if (argc < 2) { printUsage(false); return EXIT_SUCCESS; @@ -201,7 +181,7 @@ int main(int argc, const char **argv) { FileUtil::fixRlimitNoFile(); setenv("MMSEQS", argv[0], true); - Command *c = NULL; + const Command *c = NULL; if (strncmp(argv[1], "shellcompletion", strlen("shellcompletion")) == 0) { return shellcompletion(argc - 2, argv + 2); } else if ((c = getCommandByName(argv[1])) != NULL) { @@ -211,37 +191,31 @@ int main(int argc, const char **argv) { Debug(Debug::INFO) << "\nInvalid Command: " << argv[1] << "\n"; // Suggest some command that the user might have meant - size_t index = SIZE_MAX; + size_t indexI = SIZE_MAX; + size_t indexJ = SIZE_MAX; int maxDistance = 0; - for (size_t i = 0; i < commands.size(); ++i) { - struct Command &p = commands[i]; - if (p.mode & COMMAND_HIDDEN) { - continue; - } - - int distance = DistanceCalculator::localLevenshteinDistance(argv[1], p.cmd); - if (distance > maxDistance) { - maxDistance = distance; - index = i; + for (size_t i = 0; i < commands.size(); i++) { + size_t start = 0; + if (hide_base_commands) { + start = commands.size() - 1; } - } - - if (hide_base_commands == false) { - for (size_t i = 0; i < baseCommands.size(); ++i) { - struct Command &p = baseCommands[i]; - if (p.mode & COMMAND_HIDDEN) + for (size_t j = start; j < commands[i]->size(); j++) { + const Command &p = (*commands[i])[j]; + if (p.mode & COMMAND_HIDDEN) { continue; + } int distance = DistanceCalculator::localLevenshteinDistance(argv[1], p.cmd); if (distance > maxDistance) { maxDistance = distance; - index = i; + indexI = i; + indexJ = j; } } } - if (index != SIZE_MAX) { - Debug(Debug::WARNING) << "Did you mean \"" << argv[0] << " " << baseCommands[index].cmd << "\"?\n"; + if (indexI != SIZE_MAX && indexJ != SIZE_MAX) { + Debug(Debug::WARNING) << "Did you mean \"" << argv[0] << " " << (*commands[indexI])[indexJ].cmd << "\"?\n"; } return EXIT_FAILURE; diff --git a/src/commons/Command.cpp b/src/commons/Command.cpp index 677f46a03..ac6a8b14f 100644 --- a/src/commons/Command.cpp +++ b/src/commons/Command.cpp @@ -1,6 +1,11 @@ #include "Command.h" #include "Parameters.h" +std::vector*> commands; +void registerCommands(std::vector* cmd) { + commands.emplace_back(cmd); +} + std::vector categories = { {"Easy workflows for plain text input/output", COMMAND_EASY}, {"Main workflows for database input/output", COMMAND_MAIN}, diff --git a/src/commons/Command.h b/src/commons/Command.h index 5c5fd1ae4..308309e5a 100644 --- a/src/commons/Command.h +++ b/src/commons/Command.h @@ -108,4 +108,6 @@ struct Categories { CommandMode mode; }; +void registerCommands(std::vector* cmd); + #endif diff --git a/src/mmseqs.cpp b/src/mmseqs.cpp index cdbb3134e..f0a5be091 100644 --- a/src/mmseqs.cpp +++ b/src/mmseqs.cpp @@ -12,7 +12,13 @@ extern const char* MMSEQS_CURRENT_INDEX_VERSION; const char* index_version_compatible = MMSEQS_CURRENT_INDEX_VERSION; bool hide_base_commands = false; void (*validatorUpdate)(void) = 0; -std::vector commands = {}; + +extern std::vector baseCommands; +void init() { + registerCommands(&baseCommands); +} +void (*initCommands)(void) = init; + std::vector externalDownloads = {}; std::vector externalThreshold = {};