Commit 653d8b70fd2f102eff0f1620e4cc83c350b857e4
1 parent
e0ca21f4
Clean up, move more to detail
Showing
3 changed files
with
296 additions
and
327 deletions
include/CLI.hpp
| @@ -18,6 +18,7 @@ | @@ -18,6 +18,7 @@ | ||
| 18 | #include <iomanip> | 18 | #include <iomanip> |
| 19 | #include <numeric> | 19 | #include <numeric> |
| 20 | #include <vector> | 20 | #include <vector> |
| 21 | +#include <locale> | ||
| 21 | 22 | ||
| 22 | // C standard library | 23 | // C standard library |
| 23 | // Only needed for existence checking | 24 | // Only needed for existence checking |
| @@ -25,118 +26,11 @@ | @@ -25,118 +26,11 @@ | ||
| 25 | #include <sys/types.h> | 26 | #include <sys/types.h> |
| 26 | #include <sys/stat.h> | 27 | #include <sys/stat.h> |
| 27 | 28 | ||
| 28 | -#include <locale> | ||
| 29 | - | ||
| 30 | - | ||
| 31 | -//#define CLI_LOG 1 | ||
| 32 | 29 | ||
| 33 | namespace CLI { | 30 | namespace CLI { |
| 34 | 31 | ||
| 35 | -/// Log a message, can be enabled with CLI_LOG | ||
| 36 | -void logit(std::string) { | ||
| 37 | -#ifdef CLI_LOG | ||
| 38 | - std::cout << "\033[1;31m" << output << "\033[0m" << std::endl; | ||
| 39 | -#endif | ||
| 40 | -} | ||
| 41 | - | ||
| 42 | -/// Simple fucntion to join a string | ||
| 43 | -template <typename T> | ||
| 44 | -std::string join(const T& v, std::string delim = ",") { | ||
| 45 | - std::ostringstream s; | ||
| 46 | - for (const auto& i : v) { | ||
| 47 | - if (&i != &v[0]) { | ||
| 48 | - s << delim; | ||
| 49 | - } | ||
| 50 | - s << i; | ||
| 51 | - } | ||
| 52 | - return s.str(); | ||
| 53 | -} | ||
| 54 | - | ||
| 55 | -// Based generally on https://rmf.io/cxx11/almost-static-if | ||
| 56 | -namespace detail { | ||
| 57 | - /// Simple empty scoped class | ||
| 58 | - enum class enabler {}; | ||
| 59 | -} | ||
| 60 | - | ||
| 61 | -/// An instance to use in EnableIf | ||
| 62 | -constexpr detail::enabler dummy = {}; | ||
| 63 | - | ||
| 64 | -// Copied from C++14 | ||
| 65 | -#if __cplusplus < 201402L | ||
| 66 | -template< bool B, class T = void > | ||
| 67 | -using enable_if_t = typename std::enable_if<B,T>::type; | ||
| 68 | -#else | ||
| 69 | -using std::enable_if_t; | ||
| 70 | -#endif | ||
| 71 | -// If your compiler supports C++14, you can use that definition instead | ||
| 72 | - | ||
| 73 | -template <typename T> | ||
| 74 | -struct is_vector { | ||
| 75 | - static const bool value = false; | ||
| 76 | -}; | ||
| 77 | - | ||
| 78 | - | ||
| 79 | -template<class T, class A> | ||
| 80 | -struct is_vector<std::vector<T, A> > { | ||
| 81 | - static bool const value = true; | ||
| 82 | -}; | ||
| 83 | - | ||
| 84 | -struct Combiner { | ||
| 85 | - int num; | ||
| 86 | - bool positional; | ||
| 87 | - bool required; | ||
| 88 | - bool defaulted; | ||
| 89 | - std::vector<std::function<bool(std::string)>> validators; | ||
| 90 | - | ||
| 91 | - /// Can be or-ed together | ||
| 92 | - Combiner operator | (Combiner b) const { | ||
| 93 | - Combiner self; | ||
| 94 | - self.num = std::min(num, b.num) == -1 ? -1 : std::max(num, b.num); | ||
| 95 | - self.positional = positional || b.positional; | ||
| 96 | - self.required = required || b.required; | ||
| 97 | - self.defaulted = defaulted || b.defaulted; | ||
| 98 | - self.validators.reserve(validators.size() + b.validators.size()); | ||
| 99 | - self.validators.insert(self.validators.end(), validators.begin(), validators.end()); | ||
| 100 | - self.validators.insert(self.validators.end(), b.validators.begin(), b.validators.end()); | ||
| 101 | - return self; | ||
| 102 | - } | ||
| 103 | - | ||
| 104 | - /// Call to give the number of arguments expected on cli | ||
| 105 | - Combiner operator() (int n) const { | ||
| 106 | - Combiner self = *this; | ||
| 107 | - self.num = n; | ||
| 108 | - return self; | ||
| 109 | - } | ||
| 110 | - /// Call to give a validator | ||
| 111 | - Combiner operator() (std::function<bool(std::string)> func) const { | ||
| 112 | - Combiner self = *this; | ||
| 113 | - self.validators.push_back(func); | ||
| 114 | - return self; | ||
| 115 | - } | ||
| 116 | - Combiner operator, (Combiner b) const { | ||
| 117 | - return *this | b; | ||
| 118 | - } | ||
| 119 | -}; | ||
| 120 | - | ||
| 121 | -bool _ExistingFile(std::string filename) { | ||
| 122 | -// std::fstream f(name.c_str()); | ||
| 123 | -// return f.good(); | ||
| 124 | -// Fastest way according to http://stackoverflow.com/questions/12774207/fastest-way-to-check-if-a-file-exist-using-standard-c-c11-c | ||
| 125 | - struct stat buffer; | ||
| 126 | - return (stat(filename.c_str(), &buffer) == 0); | ||
| 127 | -} | ||
| 128 | 32 | ||
| 129 | -bool _ExistingDirectory(std::string filename) { | ||
| 130 | - struct stat buffer; | ||
| 131 | - if(stat(filename.c_str(), &buffer) == 0 && (buffer.st_mode & S_IFDIR) ) | ||
| 132 | - return true; | ||
| 133 | - return false; | ||
| 134 | -} | ||
| 135 | - | ||
| 136 | -bool _NonexistentPath(std::string filename) { | ||
| 137 | - struct stat buffer; | ||
| 138 | - return stat(filename.c_str(), &buffer) != 0; | ||
| 139 | -} | 33 | +// Error definitions |
| 140 | 34 | ||
| 141 | struct Error : public std::runtime_error { | 35 | struct Error : public std::runtime_error { |
| 142 | int exit_code; | 36 | int exit_code; |
| @@ -183,125 +77,262 @@ struct EmptyError : public Error { | @@ -183,125 +77,262 @@ struct EmptyError : public Error { | ||
| 183 | }; | 77 | }; |
| 184 | 78 | ||
| 185 | 79 | ||
| 186 | -template<typename T> | ||
| 187 | -bool valid_first_char(T c) { | ||
| 188 | - return std::isalpha(c) || c=='_'; | ||
| 189 | -} | 80 | +// Type tools |
| 81 | +// | ||
| 82 | +// Copied from C++14 | ||
| 83 | +#if __cplusplus < 201402L | ||
| 84 | +template< bool B, class T = void > | ||
| 85 | +using enable_if_t = typename std::enable_if<B,T>::type; | ||
| 86 | +#else | ||
| 87 | +using std::enable_if_t; | ||
| 88 | +#endif | ||
| 89 | +// If your compiler supports C++14, you can use that definition instead | ||
| 190 | 90 | ||
| 191 | -template<typename T> | ||
| 192 | -bool valid_later_char(T c) { | ||
| 193 | - return std::isalnum(c) || c=='_' || c=='.' || c=='-'; | ||
| 194 | -} | 91 | +template <typename T> |
| 92 | +struct is_vector { | ||
| 93 | + static const bool value = false; | ||
| 94 | +}; | ||
| 195 | 95 | ||
| 196 | -inline bool valid_name_string(const std::string &str) { | ||
| 197 | - if(str.size()<1 || !valid_first_char(str[0])) | ||
| 198 | - return false; | ||
| 199 | - for(auto c : str.substr(1)) | ||
| 200 | - if(!valid_later_char(c)) | ||
| 201 | - return false; | ||
| 202 | - return true; | ||
| 203 | -} | ||
| 204 | 96 | ||
| 205 | -// Returns false if not a short option. Otherwise, sets opt name and rest and returns true | ||
| 206 | -inline bool split_short(const std::string ¤t, std::string &name, std::string &rest) { | ||
| 207 | - if(current.size()>1 && current[0] == '-' && valid_first_char(current[1])) { | ||
| 208 | - name = current.substr(1,1); | ||
| 209 | - rest = current.substr(2); | ||
| 210 | - return true; | ||
| 211 | - } else | ||
| 212 | - return false; | ||
| 213 | -} | 97 | +template<class T, class A> |
| 98 | +struct is_vector<std::vector<T, A> > { | ||
| 99 | + static bool const value = true; | ||
| 100 | +}; | ||
| 214 | 101 | ||
| 215 | -// Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true | ||
| 216 | -inline bool split_long(const std::string ¤t, std::string &name, std::string &value) { | ||
| 217 | - if(current.size()>2 && current.substr(0,2) == "--" && valid_first_char(current[2])) { | ||
| 218 | - auto loc = current.find("="); | ||
| 219 | - if(loc != std::string::npos) { | ||
| 220 | - name = current.substr(2,loc-2); | ||
| 221 | - value = current.substr(loc+1); | ||
| 222 | - } else { | ||
| 223 | - name = current.substr(2); | ||
| 224 | - value = ""; | 102 | +namespace detail { |
| 103 | + // Based generally on https://rmf.io/cxx11/almost-static-if | ||
| 104 | + /// Simple empty scoped class | ||
| 105 | + enum class enabler {}; | ||
| 106 | + | ||
| 107 | + /// An instance to use in EnableIf | ||
| 108 | + constexpr enabler dummy = {}; | ||
| 109 | + | ||
| 110 | + /// Simple function to join a string | ||
| 111 | + template <typename T> | ||
| 112 | + std::string join(const T& v, std::string delim = ",") { | ||
| 113 | + std::ostringstream s; | ||
| 114 | + for (const auto& i : v) { | ||
| 115 | + if (&i != &v[0]) { | ||
| 116 | + s << delim; | ||
| 117 | + } | ||
| 118 | + s << i; | ||
| 225 | } | 119 | } |
| 226 | - return true; | ||
| 227 | - } else | 120 | + return s.str(); |
| 121 | + } | ||
| 122 | + | ||
| 123 | + struct Combiner { | ||
| 124 | + int num; | ||
| 125 | + bool positional; | ||
| 126 | + bool required; | ||
| 127 | + bool defaulted; | ||
| 128 | + std::vector<std::function<bool(std::string)>> validators; | ||
| 129 | + | ||
| 130 | + /// Can be or-ed together | ||
| 131 | + Combiner operator | (Combiner b) const { | ||
| 132 | + Combiner self; | ||
| 133 | + self.num = std::min(num, b.num) == -1 ? -1 : std::max(num, b.num); | ||
| 134 | + self.positional = positional || b.positional; | ||
| 135 | + self.required = required || b.required; | ||
| 136 | + self.defaulted = defaulted || b.defaulted; | ||
| 137 | + self.validators.reserve(validators.size() + b.validators.size()); | ||
| 138 | + self.validators.insert(self.validators.end(), validators.begin(), validators.end()); | ||
| 139 | + self.validators.insert(self.validators.end(), b.validators.begin(), b.validators.end()); | ||
| 140 | + return self; | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + /// Call to give the number of arguments expected on cli | ||
| 144 | + Combiner operator() (int n) const { | ||
| 145 | + Combiner self = *this; | ||
| 146 | + self.num = n; | ||
| 147 | + return self; | ||
| 148 | + } | ||
| 149 | + /// Call to give a validator | ||
| 150 | + Combiner operator() (std::function<bool(std::string)> func) const { | ||
| 151 | + Combiner self = *this; | ||
| 152 | + self.validators.push_back(func); | ||
| 153 | + return self; | ||
| 154 | + } | ||
| 155 | + Combiner operator, (Combiner b) const { | ||
| 156 | + return *this | b; | ||
| 157 | + } | ||
| 158 | + }; | ||
| 159 | + | ||
| 160 | + bool _ExistingFile(std::string filename) { | ||
| 161 | + // std::fstream f(name.c_str()); | ||
| 162 | + // return f.good(); | ||
| 163 | + // Fastest way according to http://stackoverflow.com/questions/12774207/fastest-way-to-check-if-a-file-exist-using-standard-c-c11-c | ||
| 164 | + struct stat buffer; | ||
| 165 | + return (stat(filename.c_str(), &buffer) == 0); | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + bool _ExistingDirectory(std::string filename) { | ||
| 169 | + struct stat buffer; | ||
| 170 | + if(stat(filename.c_str(), &buffer) == 0 && (buffer.st_mode & S_IFDIR) ) | ||
| 171 | + return true; | ||
| 228 | return false; | 172 | return false; |
| 229 | -} | 173 | + } |
| 230 | 174 | ||
| 231 | -// Splits a string into multiple long and short names | ||
| 232 | -inline std::vector<std::string> split_names(std::string current) { | ||
| 233 | - std::vector<std::string> output; | ||
| 234 | - size_t val; | ||
| 235 | - while((val = current.find(",")) != std::string::npos) { | ||
| 236 | - output.push_back(current.substr(0,val)); | ||
| 237 | - current = current.substr(val+1); | 175 | + bool _NonexistentPath(std::string filename) { |
| 176 | + struct stat buffer; | ||
| 177 | + return stat(filename.c_str(), &buffer) != 0; | ||
| 238 | } | 178 | } |
| 239 | - output.push_back(current); | ||
| 240 | - return output; | ||
| 241 | 179 | ||
| 242 | -} | ||
| 243 | 180 | ||
| 181 | + template<typename T> | ||
| 182 | + bool valid_first_char(T c) { | ||
| 183 | + return std::isalpha(c) || c=='_'; | ||
| 184 | + } | ||
| 244 | 185 | ||
| 245 | -inline std::tuple<std::vector<std::string>,std::vector<std::string>> get_names(const std::vector<std::string> &input) { | ||
| 246 | - std::vector<std::string> short_names; | ||
| 247 | - std::vector<std::string> long_names; | ||
| 248 | - | ||
| 249 | - for(std::string name : input) { | ||
| 250 | - if(name.length() == 0) | ||
| 251 | - continue; | ||
| 252 | - else if(name.length() == 1) | ||
| 253 | - if(valid_first_char(name[0])) | ||
| 254 | - short_names.push_back(name); | ||
| 255 | - else | ||
| 256 | - throw BadNameString("Invalid one char name: "+name); | ||
| 257 | - else if(name.length() == 2 && name[0] == '-' && name[1] != '-') { | ||
| 258 | - if(valid_first_char(name[1])) | ||
| 259 | - short_names.push_back(std::string(1,name[1])); | ||
| 260 | - else | ||
| 261 | - throw BadNameString("Invalid one char name: "+name); | ||
| 262 | - } else { | 186 | + template<typename T> |
| 187 | + bool valid_later_char(T c) { | ||
| 188 | + return std::isalnum(c) || c=='_' || c=='.' || c=='-'; | ||
| 189 | + } | ||
| 263 | 190 | ||
| 264 | - if(name.substr(0,2) == "--") | ||
| 265 | - name = name.substr(2); | ||
| 266 | - if(valid_name_string(name)) | ||
| 267 | - long_names.push_back(name); | ||
| 268 | - else | ||
| 269 | - throw BadNameString("Bad long name"+name); | 191 | + inline bool valid_name_string(const std::string &str) { |
| 192 | + if(str.size()<1 || !valid_first_char(str[0])) | ||
| 193 | + return false; | ||
| 194 | + for(auto c : str.substr(1)) | ||
| 195 | + if(!valid_later_char(c)) | ||
| 196 | + return false; | ||
| 197 | + return true; | ||
| 198 | + } | ||
| 199 | + | ||
| 200 | + // Returns false if not a short option. Otherwise, sets opt name and rest and returns true | ||
| 201 | + inline bool split_short(const std::string ¤t, std::string &name, std::string &rest) { | ||
| 202 | + if(current.size()>1 && current[0] == '-' && valid_first_char(current[1])) { | ||
| 203 | + name = current.substr(1,1); | ||
| 204 | + rest = current.substr(2); | ||
| 205 | + return true; | ||
| 206 | + } else | ||
| 207 | + return false; | ||
| 208 | + } | ||
| 209 | + | ||
| 210 | + // Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true | ||
| 211 | + inline bool split_long(const std::string ¤t, std::string &name, std::string &value) { | ||
| 212 | + if(current.size()>2 && current.substr(0,2) == "--" && valid_first_char(current[2])) { | ||
| 213 | + auto loc = current.find("="); | ||
| 214 | + if(loc != std::string::npos) { | ||
| 215 | + name = current.substr(2,loc-2); | ||
| 216 | + value = current.substr(loc+1); | ||
| 217 | + } else { | ||
| 218 | + name = current.substr(2); | ||
| 219 | + value = ""; | ||
| 220 | + } | ||
| 221 | + return true; | ||
| 222 | + } else | ||
| 223 | + return false; | ||
| 224 | + } | ||
| 270 | 225 | ||
| 226 | + // Splits a string into multiple long and short names | ||
| 227 | + inline std::vector<std::string> split_names(std::string current) { | ||
| 228 | + std::vector<std::string> output; | ||
| 229 | + size_t val; | ||
| 230 | + while((val = current.find(",")) != std::string::npos) { | ||
| 231 | + output.push_back(current.substr(0,val)); | ||
| 232 | + current = current.substr(val+1); | ||
| 271 | } | 233 | } |
| 234 | + output.push_back(current); | ||
| 235 | + return output; | ||
| 236 | + | ||
| 272 | } | 237 | } |
| 273 | - | ||
| 274 | - return std::tuple<std::vector<std::string>,std::vector<std::string>>(short_names, long_names); | ||
| 275 | 238 | ||
| 276 | -} | ||
| 277 | 239 | ||
| 278 | -// Currently just throws an error if name is incorrect. May clean later. | ||
| 279 | -inline void cleanup_names(const std::vector<std::string> &input) { | 240 | + inline std::tuple<std::vector<std::string>,std::vector<std::string>> get_names(const std::vector<std::string> &input) { |
| 241 | + std::vector<std::string> short_names; | ||
| 242 | + std::vector<std::string> long_names; | ||
| 243 | + | ||
| 244 | + for(std::string name : input) { | ||
| 245 | + if(name.length() == 0) | ||
| 246 | + continue; | ||
| 247 | + else if(name.length() == 1) | ||
| 248 | + if(valid_first_char(name[0])) | ||
| 249 | + short_names.push_back(name); | ||
| 250 | + else | ||
| 251 | + throw BadNameString("Invalid one char name: "+name); | ||
| 252 | + else if(name.length() == 2 && name[0] == '-' && name[1] != '-') { | ||
| 253 | + if(valid_first_char(name[1])) | ||
| 254 | + short_names.push_back(std::string(1,name[1])); | ||
| 255 | + else | ||
| 256 | + throw BadNameString("Invalid one char name: "+name); | ||
| 257 | + } else { | ||
| 258 | + | ||
| 259 | + if(name.substr(0,2) == "--") | ||
| 260 | + name = name.substr(2); | ||
| 261 | + if(valid_name_string(name)) | ||
| 262 | + long_names.push_back(name); | ||
| 263 | + else | ||
| 264 | + throw BadNameString("Bad long name"+name); | ||
| 265 | + | ||
| 266 | + } | ||
| 267 | + } | ||
| 268 | + | ||
| 269 | + return std::tuple<std::vector<std::string>,std::vector<std::string>>(short_names, long_names); | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + | ||
| 273 | + template<typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = detail::dummy> | ||
| 274 | + bool lexical_cast(std::string input, T& output) { | ||
| 275 | + try{ | ||
| 276 | + output = (T) std::stoll(input); | ||
| 277 | + return true; | ||
| 278 | + } catch (std::invalid_argument) { | ||
| 279 | + return false; | ||
| 280 | + } catch (std::out_of_range) { | ||
| 281 | + return false; | ||
| 282 | + } | ||
| 283 | + } | ||
| 284 | + | ||
| 285 | + template<typename T, enable_if_t<std::is_floating_point<T>::value, detail::enabler> = detail::dummy> | ||
| 286 | + bool lexical_cast(std::string input, T& output) { | ||
| 287 | + try{ | ||
| 288 | + output = (T) std::stold(input); | ||
| 289 | + return true; | ||
| 290 | + } catch (std::invalid_argument) { | ||
| 291 | + return false; | ||
| 292 | + } catch (std::out_of_range) { | ||
| 293 | + return false; | ||
| 294 | + } | ||
| 295 | + } | ||
| 296 | + | ||
| 297 | + // String and similar | ||
| 298 | + template<typename T, | ||
| 299 | + enable_if_t<is_vector<T>::value, detail::enabler> = detail::dummy> | ||
| 300 | + bool lexical_cast(std::string input, T& output) { | ||
| 301 | + if(output.size() == input.size()) | ||
| 302 | + output.resize(input.size()); | ||
| 303 | + for(size_t i=0; i<input.size(); i++) | ||
| 304 | + output[i] = input[i]; | ||
| 305 | + return true; | ||
| 306 | + } | ||
| 280 | 307 | ||
| 281 | - for(const std::string &name : input) { | ||
| 282 | - if(name.compare(0, 2, "--") == 0) | ||
| 283 | - //output = output.substring(2); | ||
| 284 | - throw BadNameString(name); | ||
| 285 | - else if(name.compare(0, 1, std::string("-")) == 0) | ||
| 286 | - throw BadNameString(name); | ||
| 287 | - //output = output.substring(1); | 308 | + // String and similar |
| 309 | + template<typename T, | ||
| 310 | + enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value && !is_vector<T>::value | ||
| 311 | + , detail::enabler> = detail::dummy> | ||
| 312 | + bool lexical_cast(std::string input, T& output) { | ||
| 313 | + output = input; | ||
| 314 | + return true; | ||
| 288 | } | 315 | } |
| 289 | } | 316 | } |
| 290 | 317 | ||
| 291 | 318 | ||
| 292 | -const Combiner NOTHING {0, false,false,false, {}}; | ||
| 293 | -const Combiner REQUIRED {1, false,true, false, {}}; | ||
| 294 | -const Combiner DEFAULT {1, false,false,true, {}}; | ||
| 295 | -const Combiner POSITIONAL {1, true, false,false, {}}; | ||
| 296 | -const Combiner ARGS {-1, false,false,false, {}}; | ||
| 297 | -const Combiner VALIDATORS {1, false, false, false, {}}; | 319 | + |
| 320 | +// Defines for common Combiners (don't use combiners directly) | ||
| 321 | + | ||
| 322 | + | ||
| 323 | +const detail::Combiner NOTHING {0, false,false,false, {}}; | ||
| 324 | +const detail::Combiner REQUIRED {1, false,true, false, {}}; | ||
| 325 | +const detail::Combiner DEFAULT {1, false,false,true, {}}; | ||
| 326 | +const detail::Combiner POSITIONAL {1, true, false,false, {}}; | ||
| 327 | +const detail::Combiner ARGS {-1, false,false,false, {}}; | ||
| 328 | +const detail::Combiner VALIDATORS {1, false, false, false, {}}; | ||
| 298 | 329 | ||
| 299 | // Warning about using these validators: | 330 | // Warning about using these validators: |
| 300 | // The files could be added/deleted after the validation. This is not common, | 331 | // The files could be added/deleted after the validation. This is not common, |
| 301 | // but if this is a possibility, check the file you open afterwards | 332 | // but if this is a possibility, check the file you open afterwards |
| 302 | -const Combiner ExistingFile {1, false, false, false, {_ExistingFile}}; | ||
| 303 | -const Combiner ExistingDirectory {1, false, false, false, {_ExistingDirectory}}; | ||
| 304 | -const Combiner NonexistentPath {1, false, false, false, {_NonexistentPath}}; | 333 | +const detail::Combiner ExistingFile {1, false, false, false, {detail::_ExistingFile}}; |
| 334 | +const detail::Combiner ExistingDirectory {1, false, false, false, {detail::_ExistingDirectory}}; | ||
| 335 | +const detail::Combiner NonexistentPath {1, false, false, false, {detail::_NonexistentPath}}; | ||
| 305 | 336 | ||
| 306 | typedef std::vector<std::vector<std::string>> results_t; | 337 | typedef std::vector<std::vector<std::string>> results_t; |
| 307 | typedef std::function<bool(results_t)> callback_t; | 338 | typedef std::function<bool(results_t)> callback_t; |
| @@ -314,7 +345,7 @@ protected: | @@ -314,7 +345,7 @@ protected: | ||
| 314 | // Config | 345 | // Config |
| 315 | std::vector<std::string> snames; | 346 | std::vector<std::string> snames; |
| 316 | std::vector<std::string> lnames; | 347 | std::vector<std::string> lnames; |
| 317 | - Combiner opts; | 348 | + detail::Combiner opts; |
| 318 | std::string discription; | 349 | std::string discription; |
| 319 | callback_t callback; | 350 | callback_t callback; |
| 320 | 351 | ||
| @@ -323,9 +354,9 @@ protected: | @@ -323,9 +354,9 @@ protected: | ||
| 323 | 354 | ||
| 324 | 355 | ||
| 325 | public: | 356 | public: |
| 326 | - Option(std::string name, std::string discription = "", Combiner opts=NOTHING, std::function<bool(results_t)> callback=[](results_t){return true;}) : | 357 | + Option(std::string name, std::string discription = "", detail::Combiner opts=NOTHING, std::function<bool(results_t)> callback=[](results_t){return true;}) : |
| 327 | opts(opts), discription(discription), callback(callback){ | 358 | opts(opts), discription(discription), callback(callback){ |
| 328 | - std::tie(snames, lnames) = get_names(split_names(name)); | 359 | + std::tie(snames, lnames) = detail::get_names(detail::split_names(name)); |
| 329 | } | 360 | } |
| 330 | 361 | ||
| 331 | void clear() { | 362 | void clear() { |
| @@ -378,7 +409,7 @@ public: | @@ -378,7 +409,7 @@ public: | ||
| 378 | name_list.push_back("-"+sname); | 409 | name_list.push_back("-"+sname); |
| 379 | for(const std::string& lname : lnames) | 410 | for(const std::string& lname : lnames) |
| 380 | name_list.push_back("--"+lname); | 411 | name_list.push_back("--"+lname); |
| 381 | - return join(name_list); | 412 | + return detail::join(name_list); |
| 382 | } | 413 | } |
| 383 | 414 | ||
| 384 | bool check_name(std::string name) const { | 415 | bool check_name(std::string name) const { |
| @@ -399,7 +430,6 @@ public: | @@ -399,7 +430,6 @@ public: | ||
| 399 | 430 | ||
| 400 | 431 | ||
| 401 | void add_result(int r, std::string s) { | 432 | void add_result(int r, std::string s) { |
| 402 | - logit("Adding result: " + s); | ||
| 403 | results.at(r).push_back(s); | 433 | results.at(r).push_back(s); |
| 404 | } | 434 | } |
| 405 | int get_new() { | 435 | int get_new() { |
| @@ -420,7 +450,7 @@ public: | @@ -420,7 +450,7 @@ public: | ||
| 420 | for(const auto& item : results) { | 450 | for(const auto& item : results) { |
| 421 | if(&item!=&results[0]) | 451 | if(&item!=&results[0]) |
| 422 | val+="],["; | 452 | val+="],["; |
| 423 | - val += join(item); | 453 | + val += detail::join(item); |
| 424 | } | 454 | } |
| 425 | val += "]"; | 455 | val += "]"; |
| 426 | return val; | 456 | return val; |
| @@ -446,57 +476,9 @@ public: | @@ -446,57 +476,9 @@ public: | ||
| 446 | }; | 476 | }; |
| 447 | 477 | ||
| 448 | 478 | ||
| 449 | -template<typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = dummy> | ||
| 450 | -bool lexical_cast(std::string input, T& output) { | ||
| 451 | - logit("Int lexical cast " + input); | ||
| 452 | - try{ | ||
| 453 | - output = (T) std::stoll(input); | ||
| 454 | - return true; | ||
| 455 | - } catch (std::invalid_argument) { | ||
| 456 | - return false; | ||
| 457 | - } catch (std::out_of_range) { | ||
| 458 | - return false; | ||
| 459 | - } | ||
| 460 | -} | ||
| 461 | - | ||
| 462 | -template<typename T, enable_if_t<std::is_floating_point<T>::value, detail::enabler> = dummy> | ||
| 463 | -bool lexical_cast(std::string input, T& output) { | ||
| 464 | - logit("Floating lexical cast " + input); | ||
| 465 | - try{ | ||
| 466 | - output = (T) std::stold(input); | ||
| 467 | - return true; | ||
| 468 | - } catch (std::invalid_argument) { | ||
| 469 | - return false; | ||
| 470 | - } catch (std::out_of_range) { | ||
| 471 | - return false; | ||
| 472 | - } | ||
| 473 | -} | ||
| 474 | - | ||
| 475 | -// String and similar | ||
| 476 | -template<typename T, | ||
| 477 | -enable_if_t<is_vector<T>::value, detail::enabler> = dummy> | ||
| 478 | -bool lexical_cast(std::string input, T& output) { | ||
| 479 | - logit("vector lexical cast: " + input); | ||
| 480 | - if(output.size() == input.size()) | ||
| 481 | - output.resize(input.size()); | ||
| 482 | - for(size_t i=0; i<input.size(); i++) | ||
| 483 | - output[i] = input[i]; | ||
| 484 | - return true; | ||
| 485 | -} | ||
| 486 | - | ||
| 487 | -// String and similar | ||
| 488 | -template<typename T, | ||
| 489 | -enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value && !is_vector<T>::value | ||
| 490 | -, detail::enabler> = dummy> | ||
| 491 | -bool lexical_cast(std::string input, T& output) { | ||
| 492 | - logit("Direct lexical cast: " + input); | ||
| 493 | - output = input; | ||
| 494 | - return true; | ||
| 495 | -} | ||
| 496 | 479 | ||
| 497 | enum class Classifer {NONE, POSITIONAL_MARK, SHORT, LONG, SUBCOMMAND}; | 480 | enum class Classifer {NONE, POSITIONAL_MARK, SHORT, LONG, SUBCOMMAND}; |
| 498 | 481 | ||
| 499 | - | ||
| 500 | class App; | 482 | class App; |
| 501 | 483 | ||
| 502 | // Prototype return value test | 484 | // Prototype return value test |
| @@ -514,18 +496,16 @@ public: | @@ -514,18 +496,16 @@ public: | ||
| 514 | /// explicit * notation. | 496 | /// explicit * notation. |
| 515 | T& operator *() const { | 497 | T& operator *() const { |
| 516 | if(*value) { | 498 | if(*value) { |
| 517 | - //std::cout << "Succ" << std::endl; | ||
| 518 | return **value; | 499 | return **value; |
| 519 | } | 500 | } |
| 520 | else { | 501 | else { |
| 521 | - //std::cout << "Throwing!!!" << std::endl; | ||
| 522 | throw EmptyError(name); | 502 | throw EmptyError(name); |
| 523 | } | 503 | } |
| 524 | } | 504 | } |
| 525 | }; | 505 | }; |
| 526 | 506 | ||
| 527 | /// Creates a command line program, with very few defaults. | 507 | /// Creates a command line program, with very few defaults. |
| 528 | -/** To use, create a new Program() instance with argc, argv, and a help discription. The templated | 508 | +/** To use, create a new Program() instance with argc, argv, and a help description. The templated |
| 529 | * add_option methods make it easy to prepare options. Remember to call `.start` before starting your | 509 | * add_option methods make it easy to prepare options. Remember to call `.start` before starting your |
| 530 | * program, so that the options can be evaluated and the help option doesn't accidentally run your program. */ | 510 | * program, so that the options can be evaluated and the help option doesn't accidentally run your program. */ |
| 531 | class App { | 511 | class App { |
| @@ -568,7 +548,6 @@ public: | @@ -568,7 +548,6 @@ public: | ||
| 568 | App* add_subcommand(std::string name, std::string discription="") { | 548 | App* add_subcommand(std::string name, std::string discription="") { |
| 569 | subcommands.emplace_back(new App(discription)); | 549 | subcommands.emplace_back(new App(discription)); |
| 570 | subcommands.back()->name = name; | 550 | subcommands.back()->name = name; |
| 571 | - logit(subcommands.back()->name); | ||
| 572 | return subcommands.back().get(); | 551 | return subcommands.back().get(); |
| 573 | } | 552 | } |
| 574 | 553 | ||
| @@ -592,7 +571,7 @@ public: | @@ -592,7 +571,7 @@ public: | ||
| 592 | std::string name, ///< The name, long,short | 571 | std::string name, ///< The name, long,short |
| 593 | callback_t callback, ///< The callback | 572 | callback_t callback, ///< The callback |
| 594 | std::string discription="", ///< Discription string | 573 | std::string discription="", ///< Discription string |
| 595 | - Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) | 574 | + detail::Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) |
| 596 | ) { | 575 | ) { |
| 597 | Option myopt{name, discription, opts, callback}; | 576 | Option myopt{name, discription, opts, callback}; |
| 598 | if(std::find(std::begin(options), std::end(options), myopt) == std::end(options)) | 577 | if(std::find(std::begin(options), std::end(options), myopt) == std::end(options)) |
| @@ -604,12 +583,12 @@ public: | @@ -604,12 +583,12 @@ public: | ||
| 604 | } | 583 | } |
| 605 | 584 | ||
| 606 | /// Add option for string | 585 | /// Add option for string |
| 607 | - template<typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = dummy> | 586 | + template<typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> |
| 608 | Option* add_option( | 587 | Option* add_option( |
| 609 | std::string name, ///< The name, long,short | 588 | std::string name, ///< The name, long,short |
| 610 | T &variable, ///< The variable to set | 589 | T &variable, ///< The variable to set |
| 611 | std::string discription="", ///< Discription string | 590 | std::string discription="", ///< Discription string |
| 612 | - Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) | 591 | + detail::Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) |
| 613 | ) { | 592 | ) { |
| 614 | 593 | ||
| 615 | 594 | ||
| @@ -622,7 +601,7 @@ public: | @@ -622,7 +601,7 @@ public: | ||
| 622 | if(res[0].size()!=1) { | 601 | if(res[0].size()!=1) { |
| 623 | return false; | 602 | return false; |
| 624 | } | 603 | } |
| 625 | - return lexical_cast(res[0][0], variable); | 604 | + return detail::lexical_cast(res[0][0], variable); |
| 626 | }; | 605 | }; |
| 627 | 606 | ||
| 628 | return add_option(name, fun, discription, opts); | 607 | return add_option(name, fun, discription, opts); |
| @@ -634,7 +613,7 @@ public: | @@ -634,7 +613,7 @@ public: | ||
| 634 | std::string name, ///< The name, long,short | 613 | std::string name, ///< The name, long,short |
| 635 | std::vector<T> &variable, ///< The variable to set | 614 | std::vector<T> &variable, ///< The variable to set |
| 636 | std::string discription="", ///< Discription string | 615 | std::string discription="", ///< Discription string |
| 637 | - Combiner opts=ARGS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) | 616 | + detail::Combiner opts=ARGS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) |
| 638 | ) { | 617 | ) { |
| 639 | 618 | ||
| 640 | if(opts.num==0) | 619 | if(opts.num==0) |
| @@ -645,7 +624,7 @@ public: | @@ -645,7 +624,7 @@ public: | ||
| 645 | for(const auto &a : res) | 624 | for(const auto &a : res) |
| 646 | for(const auto &b : a) { | 625 | for(const auto &b : a) { |
| 647 | variable.emplace_back(); | 626 | variable.emplace_back(); |
| 648 | - retval &= lexical_cast(b, variable.back()); | 627 | + retval &= detail::lexical_cast(b, variable.back()); |
| 649 | } | 628 | } |
| 650 | return variable.size() > 0 && retval; | 629 | return variable.size() > 0 && retval; |
| 651 | }; | 630 | }; |
| @@ -667,7 +646,7 @@ public: | @@ -667,7 +646,7 @@ public: | ||
| 667 | } | 646 | } |
| 668 | 647 | ||
| 669 | /// Add option for flag | 648 | /// Add option for flag |
| 670 | - template<typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = dummy> | 649 | + template<typename T, enable_if_t<std::is_integral<T>::value, detail::enabler> = detail::dummy> |
| 671 | Option* add_flag( | 650 | Option* add_flag( |
| 672 | std::string name, ///< The name, short,long | 651 | std::string name, ///< The name, short,long |
| 673 | T &count, ///< A varaible holding the count | 652 | T &count, ///< A varaible holding the count |
| @@ -690,7 +669,7 @@ public: | @@ -690,7 +669,7 @@ public: | ||
| 690 | T &member, ///< The selected member of the set | 669 | T &member, ///< The selected member of the set |
| 691 | std::set<T> options, ///< The set of posibilities | 670 | std::set<T> options, ///< The set of posibilities |
| 692 | std::string discription="", ///< Discription string | 671 | std::string discription="", ///< Discription string |
| 693 | - Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) | 672 | + detail::Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) |
| 694 | ) { | 673 | ) { |
| 695 | 674 | ||
| 696 | if(opts.num!=1) | 675 | if(opts.num!=1) |
| @@ -703,7 +682,7 @@ public: | @@ -703,7 +682,7 @@ public: | ||
| 703 | if(res[0].size()!=1) { | 682 | if(res[0].size()!=1) { |
| 704 | return false; | 683 | return false; |
| 705 | } | 684 | } |
| 706 | - bool retval = lexical_cast(res[0][0], member); | 685 | + bool retval = detail::lexical_cast(res[0][0], member); |
| 707 | if(!retval) | 686 | if(!retval) |
| 708 | return false; | 687 | return false; |
| 709 | return std::find(std::begin(options), std::end(options), member) != std::end(options); | 688 | return std::find(std::begin(options), std::end(options), member) != std::end(options); |
| @@ -719,11 +698,11 @@ public: | @@ -719,11 +698,11 @@ public: | ||
| 719 | 698 | ||
| 720 | /// Prototype for new output style | 699 | /// Prototype for new output style |
| 721 | template<typename T = std::string, | 700 | template<typename T = std::string, |
| 722 | - enable_if_t<!is_vector<T>::value, detail::enabler> = dummy> | 701 | + enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> |
| 723 | Value<T> make_option( | 702 | Value<T> make_option( |
| 724 | std::string name, ///< The name, short,long | 703 | std::string name, ///< The name, short,long |
| 725 | std::string discription="", | 704 | std::string discription="", |
| 726 | - Combiner opts=VALIDATORS | 705 | + detail::Combiner opts=VALIDATORS |
| 727 | ) { | 706 | ) { |
| 728 | 707 | ||
| 729 | if(opts.num!=1) | 708 | if(opts.num!=1) |
| @@ -740,7 +719,7 @@ public: | @@ -740,7 +719,7 @@ public: | ||
| 740 | return false; | 719 | return false; |
| 741 | } | 720 | } |
| 742 | ptr->reset(new T()); // resets the internal ptr | 721 | ptr->reset(new T()); // resets the internal ptr |
| 743 | - return lexical_cast(res[0][0], **ptr); | 722 | + return detail::lexical_cast(res[0][0], **ptr); |
| 744 | }; | 723 | }; |
| 745 | add_option(name, fun, discription, opts); | 724 | add_option(name, fun, discription, opts); |
| 746 | return out; | 725 | return out; |
| @@ -748,12 +727,12 @@ public: | @@ -748,12 +727,12 @@ public: | ||
| 748 | 727 | ||
| 749 | /// Prototype for new output style with default | 728 | /// Prototype for new output style with default |
| 750 | template<typename T, | 729 | template<typename T, |
| 751 | - enable_if_t<!is_vector<T>::value, detail::enabler> = dummy> | 730 | + enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy> |
| 752 | Value<T> make_option( | 731 | Value<T> make_option( |
| 753 | std::string name, ///< The name, short,long | 732 | std::string name, ///< The name, short,long |
| 754 | const T& default_value, | 733 | const T& default_value, |
| 755 | std::string discription="", | 734 | std::string discription="", |
| 756 | - Combiner opts=VALIDATORS | 735 | + detail::Combiner opts=VALIDATORS |
| 757 | ) { | 736 | ) { |
| 758 | 737 | ||
| 759 | if(opts.num!=1) | 738 | if(opts.num!=1) |
| @@ -771,7 +750,7 @@ public: | @@ -771,7 +750,7 @@ public: | ||
| 771 | return false; | 750 | return false; |
| 772 | } | 751 | } |
| 773 | ptr->reset(new T()); // resets the internal ptr | 752 | ptr->reset(new T()); // resets the internal ptr |
| 774 | - return lexical_cast(res[0][0], **ptr); | 753 | + return detail::lexical_cast(res[0][0], **ptr); |
| 775 | }; | 754 | }; |
| 776 | add_option(name, fun, discription, opts); | 755 | add_option(name, fun, discription, opts); |
| 777 | return out; | 756 | return out; |
| @@ -779,11 +758,11 @@ public: | @@ -779,11 +758,11 @@ public: | ||
| 779 | 758 | ||
| 780 | /// Prototype for new output style, vector | 759 | /// Prototype for new output style, vector |
| 781 | template<typename T, | 760 | template<typename T, |
| 782 | - enable_if_t<is_vector<T>::value, detail::enabler> = dummy> | 761 | + enable_if_t<is_vector<T>::value, detail::enabler> = detail::dummy> |
| 783 | Value<T> make_option( | 762 | Value<T> make_option( |
| 784 | std::string name, ///< The name, short,long | 763 | std::string name, ///< The name, short,long |
| 785 | std::string discription="", | 764 | std::string discription="", |
| 786 | - Combiner opts=VALIDATORS | 765 | + detail::Combiner opts=VALIDATORS |
| 787 | ) { | 766 | ) { |
| 788 | 767 | ||
| 789 | if(opts.num==0) | 768 | if(opts.num==0) |
| @@ -798,7 +777,7 @@ public: | @@ -798,7 +777,7 @@ public: | ||
| 798 | for(const auto &a : res) | 777 | for(const auto &a : res) |
| 799 | for(const auto &b : a) { | 778 | for(const auto &b : a) { |
| 800 | (*ptr)->emplace_back(); | 779 | (*ptr)->emplace_back(); |
| 801 | - retval &= lexical_cast(b, (*ptr)->back()); | 780 | + retval &= detail::lexical_cast(b, (*ptr)->back()); |
| 802 | } | 781 | } |
| 803 | return (*ptr)->size() > 0 && retval; | 782 | return (*ptr)->size() > 0 && retval; |
| 804 | }; | 783 | }; |
| @@ -832,7 +811,7 @@ public: | @@ -832,7 +811,7 @@ public: | ||
| 832 | std::string name, ///< The name, short,long | 811 | std::string name, ///< The name, short,long |
| 833 | std::set<T> options, ///< The set of posibilities | 812 | std::set<T> options, ///< The set of posibilities |
| 834 | std::string discription="", ///< Discription string | 813 | std::string discription="", ///< Discription string |
| 835 | - Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) | 814 | + detail::Combiner opts=VALIDATORS ///< The options (REQUIRED, DEFAULT, POSITIONAL, ARGS()) |
| 836 | ) { | 815 | ) { |
| 837 | 816 | ||
| 838 | Value<T> out(name); | 817 | Value<T> out(name); |
| @@ -849,7 +828,7 @@ public: | @@ -849,7 +828,7 @@ public: | ||
| 849 | return false; | 828 | return false; |
| 850 | } | 829 | } |
| 851 | ptr->reset(new T()); | 830 | ptr->reset(new T()); |
| 852 | - bool retval = lexical_cast(res[0][0], **ptr); | 831 | + bool retval = detail::lexical_cast(res[0][0], **ptr); |
| 853 | if(!retval) | 832 | if(!retval) |
| 854 | return false; | 833 | return false; |
| 855 | return std::find(std::begin(options), std::end(options), **ptr) != std::end(options); | 834 | return std::find(std::begin(options), std::end(options), **ptr) != std::end(options); |
| @@ -876,7 +855,6 @@ public: | @@ -876,7 +855,6 @@ public: | ||
| 876 | 855 | ||
| 877 | while(args.size()>0) { | 856 | while(args.size()>0) { |
| 878 | 857 | ||
| 879 | - logit("Parse: ["+join(args)+"]"); | ||
| 880 | 858 | ||
| 881 | Classifer classifer = positional_only ? Classifer::NONE : _recognize(args.back()); | 859 | Classifer classifer = positional_only ? Classifer::NONE : _recognize(args.back()); |
| 882 | switch(classifer) { | 860 | switch(classifer) { |
| @@ -894,7 +872,6 @@ public: | @@ -894,7 +872,6 @@ public: | ||
| 894 | _parse_short(args); | 872 | _parse_short(args); |
| 895 | break; | 873 | break; |
| 896 | case Classifer::NONE: | 874 | case Classifer::NONE: |
| 897 | - logit("Positional: "+args.back()); | ||
| 898 | positionals.push_back(args.back()); | 875 | positionals.push_back(args.back()); |
| 899 | args.pop_back(); | 876 | args.pop_back(); |
| 900 | } | 877 | } |
| @@ -920,7 +897,7 @@ public: | @@ -920,7 +897,7 @@ public: | ||
| 920 | 897 | ||
| 921 | } | 898 | } |
| 922 | if(positionals.size()>0) | 899 | if(positionals.size()>0) |
| 923 | - throw PositionalError("[" + join(positionals) + "]"); | 900 | + throw PositionalError("[" + detail::join(positionals) + "]"); |
| 924 | } | 901 | } |
| 925 | 902 | ||
| 926 | void _parse_subcommand(std::vector<std::string> &args) { | 903 | void _parse_subcommand(std::vector<std::string> &args) { |
| @@ -940,12 +917,10 @@ public: | @@ -940,12 +917,10 @@ public: | ||
| 940 | 917 | ||
| 941 | std::string name; | 918 | std::string name; |
| 942 | std::string rest; | 919 | std::string rest; |
| 943 | - if(!split_short(current, name, rest)) | 920 | + if(!detail::split_short(current, name, rest)) |
| 944 | throw HorribleError("Short"); | 921 | throw HorribleError("Short"); |
| 945 | args.pop_back(); | 922 | args.pop_back(); |
| 946 | 923 | ||
| 947 | - logit("Working on short: " + name + " (" + rest + ")"); | ||
| 948 | - | ||
| 949 | auto op = std::find_if(std::begin(options), std::end(options), [name](const Option &v){return v.check_sname(name);}); | 924 | auto op = std::find_if(std::begin(options), std::end(options), [name](const Option &v){return v.check_sname(name);}); |
| 950 | 925 | ||
| 951 | if(op == std::end(options)) { | 926 | if(op == std::end(options)) { |
| @@ -975,7 +950,6 @@ public: | @@ -975,7 +950,6 @@ public: | ||
| 975 | } else while(num>0 && args.size() > 0) { | 950 | } else while(num>0 && args.size() > 0) { |
| 976 | num--; | 951 | num--; |
| 977 | std::string current = args.back(); | 952 | std::string current = args.back(); |
| 978 | - logit("Adding: "+current); | ||
| 979 | args.pop_back(); | 953 | args.pop_back(); |
| 980 | op->add_result(vnum,current); | 954 | op->add_result(vnum,current); |
| 981 | } | 955 | } |
| @@ -995,9 +969,9 @@ public: | @@ -995,9 +969,9 @@ public: | ||
| 995 | if(com->name == current) | 969 | if(com->name == current) |
| 996 | return Classifer::SUBCOMMAND; | 970 | return Classifer::SUBCOMMAND; |
| 997 | } | 971 | } |
| 998 | - if(split_long(current, dummy1, dummy2)) | 972 | + if(detail::split_long(current, dummy1, dummy2)) |
| 999 | return Classifer::LONG; | 973 | return Classifer::LONG; |
| 1000 | - if(split_short(current, dummy1, dummy2)) | 974 | + if(detail::split_short(current, dummy1, dummy2)) |
| 1001 | return Classifer::SHORT; | 975 | return Classifer::SHORT; |
| 1002 | return Classifer::NONE; | 976 | return Classifer::NONE; |
| 1003 | } | 977 | } |
| @@ -1007,13 +981,10 @@ public: | @@ -1007,13 +981,10 @@ public: | ||
| 1007 | 981 | ||
| 1008 | std::string name; | 982 | std::string name; |
| 1009 | std::string value; | 983 | std::string value; |
| 1010 | - if(!split_long(current, name, value)) | 984 | + if(!detail::split_long(current, name, value)) |
| 1011 | throw HorribleError("Long"); | 985 | throw HorribleError("Long"); |
| 1012 | args.pop_back(); | 986 | args.pop_back(); |
| 1013 | 987 | ||
| 1014 | - | ||
| 1015 | - logit("Working on long: " + name + " (" + value + ")"); | ||
| 1016 | - | ||
| 1017 | auto op = std::find_if(std::begin(options), std::end(options), [name](const Option &v){return v.check_lname(name);}); | 988 | auto op = std::find_if(std::begin(options), std::end(options), [name](const Option &v){return v.check_lname(name);}); |
| 1018 | 989 | ||
| 1019 | if(op == std::end(options)) { | 990 | if(op == std::end(options)) { |
| @@ -1067,9 +1038,7 @@ public: | @@ -1067,9 +1038,7 @@ public: | ||
| 1067 | /// Counts the number of times the given option was passed. | 1038 | /// Counts the number of times the given option was passed. |
| 1068 | int count(std::string name) const { | 1039 | int count(std::string name) const { |
| 1069 | for(const Option &opt : options) { | 1040 | for(const Option &opt : options) { |
| 1070 | - logit("Computing: " + opt.get_name()); | ||
| 1071 | if(opt.check_name(name)) { | 1041 | if(opt.check_name(name)) { |
| 1072 | - logit("Counting: " + opt.get_name() + std::to_string(opt.count())); | ||
| 1073 | return opt.count(); | 1042 | return opt.count(); |
| 1074 | } | 1043 | } |
| 1075 | } | 1044 | } |
tests/CLITest.cpp
| @@ -222,7 +222,7 @@ TEST_F(TApp, Reset) { | @@ -222,7 +222,7 @@ TEST_F(TApp, Reset) { | ||
| 222 | 222 | ||
| 223 | TEST_F(TApp, FileNotExists) { | 223 | TEST_F(TApp, FileNotExists) { |
| 224 | std::string myfile{"TestNonFileNotUsed.txt"}; | 224 | std::string myfile{"TestNonFileNotUsed.txt"}; |
| 225 | - EXPECT_TRUE(CLI::_NonexistentPath(myfile)); | 225 | + EXPECT_TRUE(CLI::detail::_NonexistentPath(myfile)); |
| 226 | 226 | ||
| 227 | std::string filename; | 227 | std::string filename; |
| 228 | app.add_option("file", filename, "", CLI::NonexistentPath); | 228 | app.add_option("file", filename, "", CLI::NonexistentPath); |
| @@ -239,12 +239,12 @@ TEST_F(TApp, FileNotExists) { | @@ -239,12 +239,12 @@ TEST_F(TApp, FileNotExists) { | ||
| 239 | EXPECT_THROW(run(), CLI::ParseError); | 239 | EXPECT_THROW(run(), CLI::ParseError); |
| 240 | 240 | ||
| 241 | std::remove(myfile.c_str()); | 241 | std::remove(myfile.c_str()); |
| 242 | - EXPECT_FALSE(CLI::_ExistingFile(myfile)); | 242 | + EXPECT_FALSE(CLI::detail::_ExistingFile(myfile)); |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | TEST_F(TApp, FileExists) { | 245 | TEST_F(TApp, FileExists) { |
| 246 | std::string myfile{"TestNonFileNotUsed.txt"}; | 246 | std::string myfile{"TestNonFileNotUsed.txt"}; |
| 247 | - EXPECT_FALSE(CLI::_ExistingFile(myfile)); | 247 | + EXPECT_FALSE(CLI::detail::_ExistingFile(myfile)); |
| 248 | 248 | ||
| 249 | std::string filename = "Failed"; | 249 | std::string filename = "Failed"; |
| 250 | app.add_option("file", filename, "", CLI::ExistingFile); | 250 | app.add_option("file", filename, "", CLI::ExistingFile); |
| @@ -261,7 +261,7 @@ TEST_F(TApp, FileExists) { | @@ -261,7 +261,7 @@ TEST_F(TApp, FileExists) { | ||
| 261 | EXPECT_EQ(myfile, filename); | 261 | EXPECT_EQ(myfile, filename); |
| 262 | 262 | ||
| 263 | std::remove(myfile.c_str()); | 263 | std::remove(myfile.c_str()); |
| 264 | - EXPECT_FALSE(CLI::_ExistingFile(myfile)); | 264 | + EXPECT_FALSE(CLI::detail::_ExistingFile(myfile)); |
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | TEST_F(TApp, InSet) { | 267 | TEST_F(TApp, InSet) { |
tests/SmallTest.cpp
| @@ -7,79 +7,79 @@ | @@ -7,79 +7,79 @@ | ||
| 7 | 7 | ||
| 8 | TEST(Validators, FileExists) { | 8 | TEST(Validators, FileExists) { |
| 9 | std::string myfile{"TestFileNotUsed.txt"}; | 9 | std::string myfile{"TestFileNotUsed.txt"}; |
| 10 | - EXPECT_FALSE(CLI::_ExistingFile(myfile)); | 10 | + EXPECT_FALSE(CLI::detail::_ExistingFile(myfile)); |
| 11 | bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file | 11 | bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file |
| 12 | EXPECT_TRUE(ok); | 12 | EXPECT_TRUE(ok); |
| 13 | - EXPECT_TRUE(CLI::_ExistingFile(myfile)); | 13 | + EXPECT_TRUE(CLI::detail::_ExistingFile(myfile)); |
| 14 | 14 | ||
| 15 | std::remove(myfile.c_str()); | 15 | std::remove(myfile.c_str()); |
| 16 | - EXPECT_FALSE(CLI::_ExistingFile(myfile)); | 16 | + EXPECT_FALSE(CLI::detail::_ExistingFile(myfile)); |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | TEST(Validators, FileNotExists) { | 19 | TEST(Validators, FileNotExists) { |
| 20 | std::string myfile{"TestFileNotUsed.txt"}; | 20 | std::string myfile{"TestFileNotUsed.txt"}; |
| 21 | - EXPECT_TRUE(CLI::_NonexistentPath(myfile)); | 21 | + EXPECT_TRUE(CLI::detail::_NonexistentPath(myfile)); |
| 22 | bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file | 22 | bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file |
| 23 | EXPECT_TRUE(ok); | 23 | EXPECT_TRUE(ok); |
| 24 | - EXPECT_FALSE(CLI::_NonexistentPath(myfile)); | 24 | + EXPECT_FALSE(CLI::detail::_NonexistentPath(myfile)); |
| 25 | 25 | ||
| 26 | std::remove(myfile.c_str()); | 26 | std::remove(myfile.c_str()); |
| 27 | - EXPECT_TRUE(CLI::_NonexistentPath(myfile)); | 27 | + EXPECT_TRUE(CLI::detail::_NonexistentPath(myfile)); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | TEST(Split, StringList) { | 30 | TEST(Split, StringList) { |
| 31 | 31 | ||
| 32 | std::vector<std::string> results {"a", "long", "--lone", "-q"}; | 32 | std::vector<std::string> results {"a", "long", "--lone", "-q"}; |
| 33 | - EXPECT_EQ(results, CLI::split_names("a,long,--lone,-q")); | 33 | + EXPECT_EQ(results, CLI::detail::split_names("a,long,--lone,-q")); |
| 34 | 34 | ||
| 35 | - EXPECT_EQ(std::vector<std::string>({"one"}), CLI::split_names("one")); | 35 | + EXPECT_EQ(std::vector<std::string>({"one"}), CLI::detail::split_names("one")); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | TEST(RegEx, Shorts) { | 38 | TEST(RegEx, Shorts) { |
| 39 | std::string name, value; | 39 | std::string name, value; |
| 40 | 40 | ||
| 41 | - EXPECT_TRUE(CLI::split_short("-a", name, value)); | 41 | + EXPECT_TRUE(CLI::detail::split_short("-a", name, value)); |
| 42 | EXPECT_EQ("a", name); | 42 | EXPECT_EQ("a", name); |
| 43 | EXPECT_EQ("", value); | 43 | EXPECT_EQ("", value); |
| 44 | 44 | ||
| 45 | - EXPECT_TRUE(CLI::split_short("-B", name, value)); | 45 | + EXPECT_TRUE(CLI::detail::split_short("-B", name, value)); |
| 46 | EXPECT_EQ("B", name); | 46 | EXPECT_EQ("B", name); |
| 47 | EXPECT_EQ("", value); | 47 | EXPECT_EQ("", value); |
| 48 | 48 | ||
| 49 | - EXPECT_TRUE(CLI::split_short("-cc", name, value)); | 49 | + EXPECT_TRUE(CLI::detail::split_short("-cc", name, value)); |
| 50 | EXPECT_EQ("c", name); | 50 | EXPECT_EQ("c", name); |
| 51 | EXPECT_EQ("c", value); | 51 | EXPECT_EQ("c", value); |
| 52 | 52 | ||
| 53 | - EXPECT_TRUE(CLI::split_short("-simple", name, value)); | 53 | + EXPECT_TRUE(CLI::detail::split_short("-simple", name, value)); |
| 54 | EXPECT_EQ("s", name); | 54 | EXPECT_EQ("s", name); |
| 55 | EXPECT_EQ("imple", value); | 55 | EXPECT_EQ("imple", value); |
| 56 | 56 | ||
| 57 | - EXPECT_FALSE(CLI::split_short("--a", name, value)); | ||
| 58 | - EXPECT_FALSE(CLI::split_short("--thing", name, value)); | ||
| 59 | - EXPECT_FALSE(CLI::split_short("--", name, value)); | ||
| 60 | - EXPECT_FALSE(CLI::split_short("something", name, value)); | ||
| 61 | - EXPECT_FALSE(CLI::split_short("s", name, value)); | 57 | + EXPECT_FALSE(CLI::detail::split_short("--a", name, value)); |
| 58 | + EXPECT_FALSE(CLI::detail::split_short("--thing", name, value)); | ||
| 59 | + EXPECT_FALSE(CLI::detail::split_short("--", name, value)); | ||
| 60 | + EXPECT_FALSE(CLI::detail::split_short("something", name, value)); | ||
| 61 | + EXPECT_FALSE(CLI::detail::split_short("s", name, value)); | ||
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | TEST(RegEx, Longs) { | 64 | TEST(RegEx, Longs) { |
| 65 | std::string name, value; | 65 | std::string name, value; |
| 66 | 66 | ||
| 67 | - EXPECT_TRUE(CLI::split_long("--a", name, value)); | 67 | + EXPECT_TRUE(CLI::detail::split_long("--a", name, value)); |
| 68 | EXPECT_EQ("a", name); | 68 | EXPECT_EQ("a", name); |
| 69 | EXPECT_EQ("", value); | 69 | EXPECT_EQ("", value); |
| 70 | 70 | ||
| 71 | - EXPECT_TRUE(CLI::split_long("--thing", name, value)); | 71 | + EXPECT_TRUE(CLI::detail::split_long("--thing", name, value)); |
| 72 | EXPECT_EQ("thing", name); | 72 | EXPECT_EQ("thing", name); |
| 73 | EXPECT_EQ("", value); | 73 | EXPECT_EQ("", value); |
| 74 | 74 | ||
| 75 | - EXPECT_TRUE(CLI::split_long("--some=thing", name, value)); | 75 | + EXPECT_TRUE(CLI::detail::split_long("--some=thing", name, value)); |
| 76 | EXPECT_EQ("some", name); | 76 | EXPECT_EQ("some", name); |
| 77 | EXPECT_EQ("thing", value); | 77 | EXPECT_EQ("thing", value); |
| 78 | 78 | ||
| 79 | - EXPECT_FALSE(CLI::split_long("-a", name, value)); | ||
| 80 | - EXPECT_FALSE(CLI::split_long("-things", name, value)); | ||
| 81 | - EXPECT_FALSE(CLI::split_long("Q", name, value)); | ||
| 82 | - EXPECT_FALSE(CLI::split_long("--", name, value)); | 79 | + EXPECT_FALSE(CLI::detail::split_long("-a", name, value)); |
| 80 | + EXPECT_FALSE(CLI::detail::split_long("-things", name, value)); | ||
| 81 | + EXPECT_FALSE(CLI::detail::split_long("Q", name, value)); | ||
| 82 | + EXPECT_FALSE(CLI::detail::split_long("--", name, value)); | ||
| 83 | 83 | ||
| 84 | } | 84 | } |
| 85 | 85 | ||
| @@ -88,16 +88,16 @@ TEST(Regex, SplittingNew) { | @@ -88,16 +88,16 @@ TEST(Regex, SplittingNew) { | ||
| 88 | std::vector<std::string> shorts; | 88 | std::vector<std::string> shorts; |
| 89 | std::vector<std::string> longs; | 89 | std::vector<std::string> longs; |
| 90 | 90 | ||
| 91 | - EXPECT_NO_THROW(std::tie(shorts, longs) = CLI::get_names({"--long", "s", "-q", "also-long"})); | 91 | + EXPECT_NO_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"--long", "s", "-q", "also-long"})); |
| 92 | EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs); | 92 | EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs); |
| 93 | EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts); | 93 | EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts); |
| 94 | 94 | ||
| 95 | - EXPECT_NO_THROW(std::tie(shorts, longs) = CLI::get_names({"--long", "", "s", "-q", "", "also-long"})); | 95 | + EXPECT_NO_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"--long", "", "s", "-q", "", "also-long"})); |
| 96 | EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs); | 96 | EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs); |
| 97 | EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts); | 97 | EXPECT_EQ(std::vector<std::string>({"s", "q"}), shorts); |
| 98 | 98 | ||
| 99 | - EXPECT_THROW(std::tie(shorts, longs) = CLI::get_names({"-"}), CLI::BadNameString); | ||
| 100 | - EXPECT_THROW(std::tie(shorts, longs) = CLI::get_names({"--"}), CLI::BadNameString); | ||
| 101 | - EXPECT_THROW(std::tie(shorts, longs) = CLI::get_names({"-hi"}), CLI::BadNameString); | 99 | + EXPECT_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"-"}), CLI::BadNameString); |
| 100 | + EXPECT_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"--"}), CLI::BadNameString); | ||
| 101 | + EXPECT_THROW(std::tie(shorts, longs) = CLI::detail::get_names({"-hi"}), CLI::BadNameString); | ||
| 102 | 102 | ||
| 103 | } | 103 | } |