Commit 653d8b70fd2f102eff0f1620e4cc83c350b857e4

Authored by Henry Fredrick Schreiner
1 parent e0ca21f4

Clean up, move more to detail

include/CLI.hpp
... ... @@ -18,6 +18,7 @@
18 18 #include <iomanip>
19 19 #include <numeric>
20 20 #include <vector>
  21 +#include <locale>
21 22  
22 23 // C standard library
23 24 // Only needed for existence checking
... ... @@ -25,118 +26,11 @@
25 26 #include <sys/types.h>
26 27 #include <sys/stat.h>
27 28  
28   -#include <locale>
29   -
30   -
31   -//#define CLI_LOG 1
32 29  
33 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 35 struct Error : public std::runtime_error {
142 36 int exit_code;
... ... @@ -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 &current, 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 &current, 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 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 &current, 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 &current, 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 330 // Warning about using these validators:
300 331 // The files could be added/deleted after the validation. This is not common,
301 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 337 typedef std::vector<std::vector<std::string>> results_t;
307 338 typedef std::function<bool(results_t)> callback_t;
... ... @@ -314,7 +345,7 @@ protected:
314 345 // Config
315 346 std::vector<std::string> snames;
316 347 std::vector<std::string> lnames;
317   - Combiner opts;
  348 + detail::Combiner opts;
318 349 std::string discription;
319 350 callback_t callback;
320 351  
... ... @@ -323,9 +354,9 @@ protected:
323 354  
324 355  
325 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 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 362 void clear() {
... ... @@ -378,7 +409,7 @@ public:
378 409 name_list.push_back("-"+sname);
379 410 for(const std::string& lname : lnames)
380 411 name_list.push_back("--"+lname);
381   - return join(name_list);
  412 + return detail::join(name_list);
382 413 }
383 414  
384 415 bool check_name(std::string name) const {
... ... @@ -399,7 +430,6 @@ public:
399 430  
400 431  
401 432 void add_result(int r, std::string s) {
402   - logit("Adding result: " + s);
403 433 results.at(r).push_back(s);
404 434 }
405 435 int get_new() {
... ... @@ -420,7 +450,7 @@ public:
420 450 for(const auto& item : results) {
421 451 if(&item!=&results[0])
422 452 val+="],[";
423   - val += join(item);
  453 + val += detail::join(item);
424 454 }
425 455 val += "]";
426 456 return val;
... ... @@ -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 480 enum class Classifer {NONE, POSITIONAL_MARK, SHORT, LONG, SUBCOMMAND};
498 481  
499   -
500 482 class App;
501 483  
502 484 // Prototype return value test
... ... @@ -514,18 +496,16 @@ public:
514 496 /// explicit * notation.
515 497 T& operator *() const {
516 498 if(*value) {
517   - //std::cout << "Succ" << std::endl;
518 499 return **value;
519 500 }
520 501 else {
521   - //std::cout << "Throwing!!!" << std::endl;
522 502 throw EmptyError(name);
523 503 }
524 504 }
525 505 };
526 506  
527 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 509 * add_option methods make it easy to prepare options. Remember to call `.start` before starting your
530 510 * program, so that the options can be evaluated and the help option doesn't accidentally run your program. */
531 511 class App {
... ... @@ -568,7 +548,6 @@ public:
568 548 App* add_subcommand(std::string name, std::string discription="") {
569 549 subcommands.emplace_back(new App(discription));
570 550 subcommands.back()->name = name;
571   - logit(subcommands.back()->name);
572 551 return subcommands.back().get();
573 552 }
574 553  
... ... @@ -592,7 +571,7 @@ public:
592 571 std::string name, ///< The name, long,short
593 572 callback_t callback, ///< The callback
594 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 576 Option myopt{name, discription, opts, callback};
598 577 if(std::find(std::begin(options), std::end(options), myopt) == std::end(options))
... ... @@ -604,12 +583,12 @@ public:
604 583 }
605 584  
606 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 587 Option* add_option(
609 588 std::string name, ///< The name, long,short
610 589 T &variable, ///< The variable to set
611 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 601 if(res[0].size()!=1) {
623 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 607 return add_option(name, fun, discription, opts);
... ... @@ -634,7 +613,7 @@ public:
634 613 std::string name, ///< The name, long,short
635 614 std::vector<T> &variable, ///< The variable to set
636 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 619 if(opts.num==0)
... ... @@ -645,7 +624,7 @@ public:
645 624 for(const auto &a : res)
646 625 for(const auto &b : a) {
647 626 variable.emplace_back();
648   - retval &= lexical_cast(b, variable.back());
  627 + retval &= detail::lexical_cast(b, variable.back());
649 628 }
650 629 return variable.size() > 0 && retval;
651 630 };
... ... @@ -667,7 +646,7 @@ public:
667 646 }
668 647  
669 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 650 Option* add_flag(
672 651 std::string name, ///< The name, short,long
673 652 T &count, ///< A varaible holding the count
... ... @@ -690,7 +669,7 @@ public:
690 669 T &member, ///< The selected member of the set
691 670 std::set<T> options, ///< The set of posibilities
692 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 675 if(opts.num!=1)
... ... @@ -703,7 +682,7 @@ public:
703 682 if(res[0].size()!=1) {
704 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 686 if(!retval)
708 687 return false;
709 688 return std::find(std::begin(options), std::end(options), member) != std::end(options);
... ... @@ -719,11 +698,11 @@ public:
719 698  
720 699 /// Prototype for new output style
721 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 702 Value<T> make_option(
724 703 std::string name, ///< The name, short,long
725 704 std::string discription="",
726   - Combiner opts=VALIDATORS
  705 + detail::Combiner opts=VALIDATORS
727 706 ) {
728 707  
729 708 if(opts.num!=1)
... ... @@ -740,7 +719,7 @@ public:
740 719 return false;
741 720 }
742 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 724 add_option(name, fun, discription, opts);
746 725 return out;
... ... @@ -748,12 +727,12 @@ public:
748 727  
749 728 /// Prototype for new output style with default
750 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 731 Value<T> make_option(
753 732 std::string name, ///< The name, short,long
754 733 const T& default_value,
755 734 std::string discription="",
756   - Combiner opts=VALIDATORS
  735 + detail::Combiner opts=VALIDATORS
757 736 ) {
758 737  
759 738 if(opts.num!=1)
... ... @@ -771,7 +750,7 @@ public:
771 750 return false;
772 751 }
773 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 755 add_option(name, fun, discription, opts);
777 756 return out;
... ... @@ -779,11 +758,11 @@ public:
779 758  
780 759 /// Prototype for new output style, vector
781 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 762 Value<T> make_option(
784 763 std::string name, ///< The name, short,long
785 764 std::string discription="",
786   - Combiner opts=VALIDATORS
  765 + detail::Combiner opts=VALIDATORS
787 766 ) {
788 767  
789 768 if(opts.num==0)
... ... @@ -798,7 +777,7 @@ public:
798 777 for(const auto &a : res)
799 778 for(const auto &b : a) {
800 779 (*ptr)->emplace_back();
801   - retval &= lexical_cast(b, (*ptr)->back());
  780 + retval &= detail::lexical_cast(b, (*ptr)->back());
802 781 }
803 782 return (*ptr)->size() > 0 && retval;
804 783 };
... ... @@ -832,7 +811,7 @@ public:
832 811 std::string name, ///< The name, short,long
833 812 std::set<T> options, ///< The set of posibilities
834 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 817 Value<T> out(name);
... ... @@ -849,7 +828,7 @@ public:
849 828 return false;
850 829 }
851 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 832 if(!retval)
854 833 return false;
855 834 return std::find(std::begin(options), std::end(options), **ptr) != std::end(options);
... ... @@ -876,7 +855,6 @@ public:
876 855  
877 856 while(args.size()>0) {
878 857  
879   - logit("Parse: ["+join(args)+"]");
880 858  
881 859 Classifer classifer = positional_only ? Classifer::NONE : _recognize(args.back());
882 860 switch(classifer) {
... ... @@ -894,7 +872,6 @@ public:
894 872 _parse_short(args);
895 873 break;
896 874 case Classifer::NONE:
897   - logit("Positional: "+args.back());
898 875 positionals.push_back(args.back());
899 876 args.pop_back();
900 877 }
... ... @@ -920,7 +897,7 @@ public:
920 897  
921 898 }
922 899 if(positionals.size()>0)
923   - throw PositionalError("[" + join(positionals) + "]");
  900 + throw PositionalError("[" + detail::join(positionals) + "]");
924 901 }
925 902  
926 903 void _parse_subcommand(std::vector<std::string> &args) {
... ... @@ -940,12 +917,10 @@ public:
940 917  
941 918 std::string name;
942 919 std::string rest;
943   - if(!split_short(current, name, rest))
  920 + if(!detail::split_short(current, name, rest))
944 921 throw HorribleError("Short");
945 922 args.pop_back();
946 923  
947   - logit("Working on short: " + name + " (" + rest + ")");
948   -
949 924 auto op = std::find_if(std::begin(options), std::end(options), [name](const Option &v){return v.check_sname(name);});
950 925  
951 926 if(op == std::end(options)) {
... ... @@ -975,7 +950,6 @@ public:
975 950 } else while(num>0 && args.size() > 0) {
976 951 num--;
977 952 std::string current = args.back();
978   - logit("Adding: "+current);
979 953 args.pop_back();
980 954 op->add_result(vnum,current);
981 955 }
... ... @@ -995,9 +969,9 @@ public:
995 969 if(com->name == current)
996 970 return Classifer::SUBCOMMAND;
997 971 }
998   - if(split_long(current, dummy1, dummy2))
  972 + if(detail::split_long(current, dummy1, dummy2))
999 973 return Classifer::LONG;
1000   - if(split_short(current, dummy1, dummy2))
  974 + if(detail::split_short(current, dummy1, dummy2))
1001 975 return Classifer::SHORT;
1002 976 return Classifer::NONE;
1003 977 }
... ... @@ -1007,13 +981,10 @@ public:
1007 981  
1008 982 std::string name;
1009 983 std::string value;
1010   - if(!split_long(current, name, value))
  984 + if(!detail::split_long(current, name, value))
1011 985 throw HorribleError("Long");
1012 986 args.pop_back();
1013 987  
1014   -
1015   - logit("Working on long: " + name + " (" + value + ")");
1016   -
1017 988 auto op = std::find_if(std::begin(options), std::end(options), [name](const Option &v){return v.check_lname(name);});
1018 989  
1019 990 if(op == std::end(options)) {
... ... @@ -1067,9 +1038,7 @@ public:
1067 1038 /// Counts the number of times the given option was passed.
1068 1039 int count(std::string name) const {
1069 1040 for(const Option &opt : options) {
1070   - logit("Computing: " + opt.get_name());
1071 1041 if(opt.check_name(name)) {
1072   - logit("Counting: " + opt.get_name() + std::to_string(opt.count()));
1073 1042 return opt.count();
1074 1043 }
1075 1044 }
... ...
tests/CLITest.cpp
... ... @@ -222,7 +222,7 @@ TEST_F(TApp, Reset) {
222 222  
223 223 TEST_F(TApp, FileNotExists) {
224 224 std::string myfile{"TestNonFileNotUsed.txt"};
225   - EXPECT_TRUE(CLI::_NonexistentPath(myfile));
  225 + EXPECT_TRUE(CLI::detail::_NonexistentPath(myfile));
226 226  
227 227 std::string filename;
228 228 app.add_option("file", filename, "", CLI::NonexistentPath);
... ... @@ -239,12 +239,12 @@ TEST_F(TApp, FileNotExists) {
239 239 EXPECT_THROW(run(), CLI::ParseError);
240 240  
241 241 std::remove(myfile.c_str());
242   - EXPECT_FALSE(CLI::_ExistingFile(myfile));
  242 + EXPECT_FALSE(CLI::detail::_ExistingFile(myfile));
243 243 }
244 244  
245 245 TEST_F(TApp, FileExists) {
246 246 std::string myfile{"TestNonFileNotUsed.txt"};
247   - EXPECT_FALSE(CLI::_ExistingFile(myfile));
  247 + EXPECT_FALSE(CLI::detail::_ExistingFile(myfile));
248 248  
249 249 std::string filename = "Failed";
250 250 app.add_option("file", filename, "", CLI::ExistingFile);
... ... @@ -261,7 +261,7 @@ TEST_F(TApp, FileExists) {
261 261 EXPECT_EQ(myfile, filename);
262 262  
263 263 std::remove(myfile.c_str());
264   - EXPECT_FALSE(CLI::_ExistingFile(myfile));
  264 + EXPECT_FALSE(CLI::detail::_ExistingFile(myfile));
265 265 }
266 266  
267 267 TEST_F(TApp, InSet) {
... ...
tests/SmallTest.cpp
... ... @@ -7,79 +7,79 @@
7 7  
8 8 TEST(Validators, FileExists) {
9 9 std::string myfile{"TestFileNotUsed.txt"};
10   - EXPECT_FALSE(CLI::_ExistingFile(myfile));
  10 + EXPECT_FALSE(CLI::detail::_ExistingFile(myfile));
11 11 bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
12 12 EXPECT_TRUE(ok);
13   - EXPECT_TRUE(CLI::_ExistingFile(myfile));
  13 + EXPECT_TRUE(CLI::detail::_ExistingFile(myfile));
14 14  
15 15 std::remove(myfile.c_str());
16   - EXPECT_FALSE(CLI::_ExistingFile(myfile));
  16 + EXPECT_FALSE(CLI::detail::_ExistingFile(myfile));
17 17 }
18 18  
19 19 TEST(Validators, FileNotExists) {
20 20 std::string myfile{"TestFileNotUsed.txt"};
21   - EXPECT_TRUE(CLI::_NonexistentPath(myfile));
  21 + EXPECT_TRUE(CLI::detail::_NonexistentPath(myfile));
22 22 bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
23 23 EXPECT_TRUE(ok);
24   - EXPECT_FALSE(CLI::_NonexistentPath(myfile));
  24 + EXPECT_FALSE(CLI::detail::_NonexistentPath(myfile));
25 25  
26 26 std::remove(myfile.c_str());
27   - EXPECT_TRUE(CLI::_NonexistentPath(myfile));
  27 + EXPECT_TRUE(CLI::detail::_NonexistentPath(myfile));
28 28 }
29 29  
30 30 TEST(Split, StringList) {
31 31  
32 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 38 TEST(RegEx, Shorts) {
39 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 42 EXPECT_EQ("a", name);
43 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 46 EXPECT_EQ("B", name);
47 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 50 EXPECT_EQ("c", name);
51 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 54 EXPECT_EQ("s", name);
55 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 64 TEST(RegEx, Longs) {
65 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 68 EXPECT_EQ("a", name);
69 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 72 EXPECT_EQ("thing", name);
73 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 76 EXPECT_EQ("some", name);
77 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 88 std::vector<std::string> shorts;
89 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 92 EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs);
93 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 96 EXPECT_EQ(std::vector<std::string>({"long", "also-long"}), longs);
97 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 }
... ...