#include #include #include #include "hex/subcommands/subcommands.hpp" #include #include #include #include #include namespace hex::subcommands { std::optional findSubCommand(const std::string &arg) { for (auto &plugin : PluginManager::getPlugins()) { for (auto &subCommand : plugin.getSubCommands()) { if (hex::format("--{}", subCommand.commandKey) == arg) { return subCommand; } } } return std::nullopt; } void processArguments(const std::vector &args) { // If no arguments, do not even try to process arguments // (important because this function will exit ImHex if an instance is already opened, // and we don't want that if no arguments were provided) if (args.empty()) return; std::vector>> subCommands; auto argsIter = args.begin(); // Get subcommand associated with the first argument std::optional currentSubCommand = findSubCommand(*argsIter); if (currentSubCommand) { argsIter += 1; // If it is a valid subcommand, remove it from the argument list } else { // If no (valid) subcommand was provided, the default one is --open currentSubCommand = findSubCommand("--open"); } // Arguments of the current subcommand std::vector currentSubCommandArgs; // Compute all subcommands to run while (argsIter != args.end()) { const std::string &arg = *argsIter; if (arg == "--othercmd") { // Save command to run if (currentSubCommand) { subCommands.emplace_back(*currentSubCommand, currentSubCommandArgs); } currentSubCommand = std::nullopt; currentSubCommandArgs = { }; } else if (currentSubCommand) { // Add current argument to the current command currentSubCommandArgs.push_back(arg); } else { // Get next subcommand from current argument currentSubCommand = findSubCommand(arg); if (!currentSubCommand) { log::error("No subcommand named '{}' found", arg); exit(EXIT_FAILURE); } } argsIter += 1; } // Save last command to run if (currentSubCommand) { subCommands.emplace_back(*currentSubCommand, currentSubCommandArgs); } // Run the subcommands for (auto& subCommandPair : subCommands) { subCommandPair.first.callback(subCommandPair.second); } // Exit the process if its not the main instance (the commands have been forwarded to another instance) if (!ImHexApi::System::isMainInstance()) { exit(0); } } void forwardSubCommand(const std::string &cmdName, const std::vector &args) { log::debug("Forwarding subcommand {} (maybe to us)", cmdName); std::vector data; for (const auto &arg: args) { data.insert(data.end(), arg.begin(), arg.end()); data.push_back('\0'); } data.erase(data.end()-1); EventManager::post(hex::format("command/{}", cmdName), data); } void registerSubCommand(const std::string &cmdName, const ForwardCommandHandler &handler) { log::debug("Registered new forward command handler: {}", cmdName); ImHexApi::Messaging::impl::getHandlers().insert({ hex::format("command/{}", cmdName), [handler](const std::vector &eventData){ std::string str(reinterpret_cast(eventData.data()), eventData.size()); std::vector args; for (const auto &arg_view : std::views::split(str, '\0')) { std::string arg(arg_view.data(), arg_view.size()); args.push_back(arg); } handler(args); }}); } }