// OptionParser // Author: Nick Porcino // Purpose: Sample code that implements a simple to use // Command Line parsing class, based loosely on Python's OptionParser. // Also included are simple versions of Join and Split // This code is public domain, no warranty expressed or implied, // Functionality is thought to be correct, but it's up to you to make // sure it does what you want. #ifndef OPTIONPARSER_H #define OPTIONPARSER_H #include #include class OptionParser { public: class Option { public: Option() { } virtual ~Option() { } bool HasShortName() const { return shortName.length() > 0; } bool HasLongName() const { return longName.length() > 0; } std::string ShortName() const { return shortName; } std::string LongName() const { return longName; } std::string Help() const { return help; } virtual bool HasArgument() const = 0; virtual std::string ArgumentType() const = 0; virtual bool Action(const std::string& s) = 0; std::string shortName; std::string longName; std::string help; }; // Ascending date sorting function struct AscendingOptionSort { bool operator()(Option*& start, Option*& end) { if (start->HasShortName() && end->HasShortName()) { return start->ShortName() < end->ShortName(); } else if (start->HasShortName() && end->HasLongName()) { return start->ShortName() < end->LongName(); } else if (start->HasLongName() && end->HasShortName()) { return start->LongName() < end->ShortName(); } else // (start->HasLongName() && end->HasLongName()) { return start->LongName() < end->LongName(); } } }; public: OptionParser(const std::string& appName); ~OptionParser(); void AddTrueOption( const std::string& shortOption, // eg "-f" const std::string& longOption, // eg "--file" bool& modMe, const std::string& help); void AddFalseOption( const std::string& shortOption, // eg "-f" const std::string& longOption, // eg "--file" bool& modMe, const std::string& help); void AddStringOption( const std::string& shortOption, // eg "-f" const std::string& longOption, // eg "--file" std::string& modMe, const std::string& help); void AddIntOption( const std::string& shortOption, // eg "-f" const std::string& longOption, // eg "--file" int& modMe, const std::string& help); void AddFloatOption( const std::string& shortOption, // eg "-f" const std::string& longOption, // eg "--file" float& modMe, const std::string& help); //void AddFloat3Option( // const std::string& shortOption, // eg "-f" // const std::string& longOption, // eg "--file" // float* modMe, // const std::string& help); //void AddFloat4Option( // const std::string& shortOption, // eg "-f" // const std::string& longOption, // eg "--file" // float* modMe, // const std::string& help); void AddCallbackOption( const std::string& shortOption, // eg "-f" const std::string& longOption, // eg "--file" void (*callback)(), const std::string& help); void StringCallback( void (*callback)(const std::string&), const std::string& help); // default is to start parsing just beyond 0, which is the executable name bool Parse(const std::string& commandLine, int firstOption = 1); // send all the Options' help strings to the output // uses argument 0 to know what the executable name is void Usage(); std::string Canonicalize(const std::string& commandLine); static bool Verbose(); static void Verbose(bool); protected: void (*stringCallback)(const std::string&); std::string stringCallbackHelp; std::vector options; std::string name; }; // utility functions for OptionParser // these are generally useful and so are exposed here // takes a string, and separates out according to embedded quoted strings // examples // abc > abc // abc "def" > abc, "def" // a "def" ghi > a, "def", ghi // a\"bc > a\"bc // as you can see, the quotes are preserved. // and quotes are escaped std::vector Separate(const std::string& input); // given a string, split it into components, at the splitter character. // if escapes are allowed, an escaped splitter won't split // if empties are allowed, empty strings will get pushed, otherwise not // ";" yields two empties if empties are allowed, zero otherwise. std::vector Split(const std::string& input, char splitter, bool escapes=false, bool empties=false); // given a vector of strings, join them all together with the join string // in between each one std::string Join(const std::vector& input, const std::string& join); std::string Join(int argc, char* argv[], const std::string& join); #ifdef _WIN32 std::string Join(int argc, wchar_t* argv[], const std::string& join); #endif // given a joined command line, this re-splits it, respecting quoted // contained strings. This way, no matter WHAT the OS thinks a good // grouping of quoted strings is in an agrv list, the end result // will be completely consistent; a list of strings that are not // quoted, with a list of strings that are quoted. std::vector SplitCommandLine(const std::string& input); #endif