1 #ifndef HLWM_ARGPARSE_H 2 #define HLWM_ARGPARSE_H 3 4 #include <functional> 5 6 #include "commandio.h" 7 #include "ipc-protocol.h" 8 #include "types.h" 9 10 /** 11 * @brief The InputConvert class is a convenience wrapper around Input::operator>> and 12 * Converter<X>::parse(). If an argument cannot be parsed, a meaningful error message 13 * is printed to the output stream. 14 */ 15 class ArgParse 16 { 17 public: ArgParse()18 ArgParse() { 19 } 20 21 bool parsingFails(Input& input, Output& output); 22 bool parsingAllFails(Input& input, Output& output); 23 24 class Argument { 25 public: 26 /** try to parse the argument from the given string or 27 * throw an exception 28 */ 29 std::function<void(std::string)> tryParse_; 30 //! whether the present argument is only optional 31 bool optional_; 32 }; 33 34 /** 35 * @brief A flag is a command line flag (prefixed with one or two dashes) 36 * and without a parameter. If a flag is given, the callback 37 * function is called. 38 */ 39 class Flag { 40 public: Flag(std::string name,std::function<void ()> callback)41 Flag(std::string name, std::function<void()> callback) 42 : name_(name) 43 , callback_(callback) 44 {} 45 //! directly activate a boolean variable Flag(std::string name,bool * target)46 Flag(std::string name, bool* target) 47 : name_(name) 48 { 49 callback_ = [target] () { 50 if (target) { 51 *target = true; 52 } 53 }; 54 } 55 56 std::string name_; 57 std::function<void()> callback_; 58 }; 59 60 /** 61 * Defines a mandatory argument of type X 62 */ 63 template<typename X> mandatory(X & value)64 ArgParse& mandatory(X& value) { 65 Argument arg { 66 [&value] (std::string source) { 67 value = Converter<X>::parse(source); 68 }, 69 false}; 70 arguments_.push_back(arg); 71 return *this; 72 } 73 74 /** 75 * Defines an optional argument of type X. 76 * If there are more arguments in the input than there are 77 * mandatory arguments, then the optional arguments are filled with 78 * input (earlier optional arguments are preferred). 79 * The target of the whetherArgumentSupplied pointer is set to 'true' 80 * if the present optional argument was supplied in the input. 81 */ 82 template<typename X> 83 ArgParse& optional(X& value, bool* whetherArgumentSupplied = nullptr) { 84 if (whetherArgumentSupplied) { 85 *whetherArgumentSupplied = false; 86 } 87 Argument arg { 88 [&value, whetherArgumentSupplied] (std::string source) { 89 value = Converter<X>::parse(source); 90 if (whetherArgumentSupplied) { 91 *whetherArgumentSupplied = true; 92 } 93 }, 94 true}; 95 arguments_.push_back(arg); 96 return *this; 97 } 98 99 ArgParse& flags(std::initializer_list<Flag> flagTable); 100 exitCode()101 int exitCode() const { return errorCode_; } 102 103 private: 104 bool unparsedTokens(Input& input, Output& output); 105 bool tryParseFlag(std::string inputToken); 106 std::vector<Argument> arguments_; 107 std::map<std::string, Flag> flags_; 108 int errorCode_ = 0; 109 }; 110 111 #endif // HLWM_ARGPARSE_H 112