#include "Flag.h" #include "StringPiece.h" #include #include #include #include #include namespace aapt { namespace flag { struct Flag { std::string name; std::string description; std::function action; bool required; bool* flagResult; bool flagValueWhenSet; bool parsed; }; static std::vector sFlags; static std::vector sArgs; static std::function wrap( const std::function& action) { return [action](const StringPiece& arg, std::string*) -> bool { action(arg); return true; }; } void optionalFlag(const StringPiece& name, const StringPiece& description, std::function action) { sFlags.push_back(Flag{ name.toString(), description.toString(), wrap(action), false, nullptr, false, false }); } void requiredFlag(const StringPiece& name, const StringPiece& description, std::function action) { sFlags.push_back(Flag{ name.toString(), description.toString(), wrap(action), true, nullptr, false, false }); } void requiredFlag(const StringPiece& name, const StringPiece& description, std::function action) { sFlags.push_back(Flag{ name.toString(), description.toString(), action, true, nullptr, false, false }); } void optionalSwitch(const StringPiece& name, const StringPiece& description, bool resultWhenSet, bool* result) { sFlags.push_back(Flag{ name.toString(), description.toString(), {}, false, result, resultWhenSet, false }); } void usageAndDie(const StringPiece& command) { std::cerr << command << " [options]"; for (const Flag& flag : sFlags) { if (flag.required) { std::cerr << " " << flag.name << " arg"; } } std::cerr << " files..." << std::endl << std::endl << "Options:" << std::endl; for (const Flag& flag : sFlags) { std::string command = flag.name; if (!flag.flagResult) { command += " arg "; } std::cerr << " " << std::setw(30) << std::left << command << flag.description << std::endl; } exit(1); } void parse(int argc, char** argv, const StringPiece& command) { std::string errorStr; for (int i = 0; i < argc; i++) { const StringPiece arg(argv[i]); if (*arg.data() != '-') { sArgs.push_back(arg.toString()); continue; } bool match = false; for (Flag& flag : sFlags) { if (arg == flag.name) { match = true; flag.parsed = true; if (flag.flagResult) { *flag.flagResult = flag.flagValueWhenSet; } else { i++; if (i >= argc) { std::cerr << flag.name << " missing argument." << std::endl << std::endl; usageAndDie(command); } if (!flag.action(argv[i], &errorStr)) { std::cerr << errorStr << "." << std::endl << std::endl; usageAndDie(command); } } break; } } if (!match) { std::cerr << "unknown option '" << arg << "'." << std::endl << std::endl; usageAndDie(command); } } for (const Flag& flag : sFlags) { if (flag.required && !flag.parsed) { std::cerr << "missing required flag " << flag.name << std::endl << std::endl; usageAndDie(command); } } } const std::vector& getArgs() { return sArgs; } } // namespace flag } // namespace aapt