ROSE 0.11.145.317
Sawyer/CommandLine.h
1// WARNING: Changes to this file must be contributed back to Sawyer or else they will
2// be clobbered by the next update from Sawyer. The Sawyer repository is at
3// https://gitlab.com/charger7534/sawyer.git.
4
5
6
7
8/* Command-line switch parsing. */
9#ifndef Sawyer_CommandLine_H
10#define Sawyer_CommandLine_H
11
12#include <Sawyer/Assert.h>
13#include <Sawyer/BitFlags.h>
14#include <Sawyer/DocumentMarkup.h>
15#include <Sawyer/IntervalSet.h>
16#include <Sawyer/Map.h>
17#include <Sawyer/Message.h>
18#include <Sawyer/Optional.h>
19#include <Sawyer/Sawyer.h>
20#include <Sawyer/Set.h>
21#include <Sawyer/SharedPointer.h>
22
23#include <boost/algorithm/string/case_conv.hpp>
24#include <boost/any.hpp>
25#include <boost/cstdint.hpp>
26#include <boost/foreach.hpp>
27#include <boost/lexical_cast.hpp>
28#include <boost/numeric/conversion/cast.hpp>
29#include <cerrno>
30#include <ctype.h>
31#include <list>
32#include <regex>
33#include <set>
34#include <stdexcept>
35#include <string>
36#include <vector>
37
38namespace Sawyer { // documented in Sawyer.h
39
164namespace CommandLine {
165
166SAWYER_EXPORT extern const std::string STR_NONE;
167class Switch;
168class SwitchGroup;
169class Parser;
170class ParserResult;
171
184
192
200
207
209// Program argument cursor
211
216struct SAWYER_EXPORT Location {
217 size_t idx;
218 size_t offset;
220 ~Location();
221
225
227 Location(size_t idx, size_t offset);
228
231 bool operator==(const Location &other) const;
232
235 bool operator!=(const Location &other) const;
236
239 bool operator<(const Location &other) const;
240
243 bool operator<=(const Location &other) const;
244};
245
247SAWYER_EXPORT std::ostream& operator<<(std::ostream&, const Location&);
248
252SAWYER_EXPORT extern const Location NOWHERE;
253
257class SAWYER_EXPORT Cursor {
258#include <Sawyer/WarningsOff.h>
259 std::vector<std::string> strings_;
260 Location loc_;
261#include <Sawyer/WarningsRestore.h>
262public:
263 ~Cursor();
264
267 explicit Cursor(const std::vector<std::string> &strings);
268
271 Cursor(const std::string &string);
272
275
277 const std::vector<std::string>& strings() const;
278
296 const Location& location() const;
302 bool atArgBegin() const;
303
306 bool atArgEnd() const;
307
312 bool atEnd() const;
313 bool atEnd(const Location &location) const;
320 const std::string& arg() const;
321 const std::string& arg(const Location &location) const;
328 std::string rest() const;
329 std::string rest(const Location &location) const;
337 std::string substr(const Location &limit, const std::string &separator=" ") const;
338 std::string substr(const Location &limit1, const Location &limit2, const std::string &separator=" ") const;
343 void replace(const std::vector<std::string>&);
344
348 void consumeChars(size_t nchars);
349
354 void consumeArgs(size_t nargs);
363 size_t linearDistance() const;
364};
365
369 Cursor &cursor_;
370 Location loc_;
371 bool canceled_;
372public:
375 ExcursionGuard(Cursor&); // implicit
377
380 void cancel();
381
385};
386
387
389// Switch value savers
391
392// used internally
393class SAWYER_EXPORT ValueSaver: public SharedObject {
394public:
395 virtual ~ValueSaver();
396protected:
397 ValueSaver();
398public:
400public:
401 virtual void save(const boost::any&, const std::string &switchKey) = 0;
402};
403
404// used internally
405template<typename T>
406class TypedSaver: public ValueSaver {
407 T &storage_;
408protected:
409 TypedSaver(T &storage): storage_(storage) {}
410public:
412 static Ptr instance(T &storage) { return Ptr(new TypedSaver(storage)); }
413 virtual void save(const boost::any &value, const std::string &/*switchKey*/) /*override*/ {
414 storage_ = boost::any_cast<T>(value);
415 }
416};
417
418// Partial specialization of TypedSaver, saving a value of any type T into a container of type CONTAINER_TEMPLATE calling the
419// containers INSERT_METHOD with one argument: the value. The CONTAINER_TEMPLATE is the name of a class template that
420// takes one argument: type type of value stored by the container.
421#define SAWYER_COMMANDLINE_SEQUENCE_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
422 template<typename T> \
423 class TypedSaver<CONTAINER_TEMPLATE<T> >: public ValueSaver { \
424 CONTAINER_TEMPLATE<T> &storage_; \
425 protected: \
426 TypedSaver(CONTAINER_TEMPLATE<T> &storage): storage_(storage) {} \
427 public: \
428 static Ptr instance(CONTAINER_TEMPLATE<T> &storage) { return Ptr(new TypedSaver(storage)); } \
429 virtual void save(const boost::any &value, const std::string &/*switchKey*/) /*override*/ { \
430 T typed = boost::any_cast<T>(value); \
431 storage_.INSERT_METHOD(typed); \
432 } \
433 }
434
435// Partial specialization of TypedSaver for saving values into map-like containers. The CONTAINER_TEMPLATE should take two
436// parameters: the key type (always std::string) and the value type (not part of this specialization). The value is stored by
437// invoking the INSERT_METHOD with two arguments: the key string for the switch whose value is being saved, and the value to
438// save.
439#define SAWYER_COMMANDLINE_MAP_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
440 template<typename T> \
441 class TypedSaver<CONTAINER_TEMPLATE<std::string, T> >: public ValueSaver { \
442 CONTAINER_TEMPLATE<std::string, T> &storage_; \
443 protected: \
444 TypedSaver(CONTAINER_TEMPLATE<std::string, T> &storage): storage_(storage) {} \
445 public: \
446 static Ptr instance(CONTAINER_TEMPLATE<std::string, T> &storage) { return Ptr(new TypedSaver(storage)); } \
447 virtual void save(const boost::any &value, const std::string &switchKey) /*override*/ { \
448 T typed = boost::any_cast<T>(value); \
449 storage_.INSERT_METHOD(switchKey, typed); \
450 } \
451 }
452
453// Partial specialization of TypedSaver for saving values into set-like containers. The CONTAINER_TEMPLATE should take one
454// parameter: the value type (not part of this specialization). The value is stored by invoking the INSERT_METHOD with one
455// argument: the value to save. The value is always an interval.
456#define SAWYER_COMMANDLINE_INTERVALSET_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
457 template<typename Interval> \
458 class TypedSaver<CONTAINER_TEMPLATE<Interval> >: public ValueSaver { \
459 CONTAINER_TEMPLATE<Interval> &storage_; \
460 protected: \
461 TypedSaver(CONTAINER_TEMPLATE<Interval> &storage): storage_(storage) {} \
462 public: \
463 static Ptr instance(CONTAINER_TEMPLATE<Interval> &storage) { return Ptr(new TypedSaver(storage)); } \
464 virtual void save(const boost::any &value, const std::string &/*switchKey*/) /*override*/ { \
465 Interval typed = boost::any_cast<Interval>(value); \
466 storage_.INSERT_METHOD(typed); \
467 } \
468 }
469
470// Partial specialization of TypedSaver for saving values into map-like containers using the STL approach where the insert
471// operator takes an std::pair(key,value) rather than two arguments. The CONTAINER_TEMPLATE should take two parameters: the key
472// type (always std::string) and the value type (not part of this specialization). The value is stored by invoking the
473// INSERT_METHOD with two arguments: the key string for the switch whose value is being saved, and the value to save.
474#define SAWYER_COMMANDLINE_MAP_PAIR_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
475 template<typename T> \
476 class TypedSaver<CONTAINER_TEMPLATE<std::string, T> >: public ValueSaver { \
477 CONTAINER_TEMPLATE<std::string, T> &storage_; \
478 protected: \
479 TypedSaver(CONTAINER_TEMPLATE<std::string, T> &storage): storage_(storage) {} \
480 public: \
481 static Ptr instance(CONTAINER_TEMPLATE<std::string, T> &storage) { return Ptr(new TypedSaver(storage)); } \
482 virtual void save(const boost::any &value, const std::string &switchKey) /*override*/ { \
483 T typed = boost::any_cast<T>(value); \
484 storage_.INSERT_METHOD(std::make_pair(switchKey, typed)); \
485 } \
486 }
487
488SAWYER_COMMANDLINE_SEQUENCE_SAVER(std::vector, push_back);
489SAWYER_COMMANDLINE_SEQUENCE_SAVER(std::list, push_back);
490SAWYER_COMMANDLINE_SEQUENCE_SAVER(std::set, insert);
491SAWYER_COMMANDLINE_SEQUENCE_SAVER(Sawyer::Container::Set, insert);
492SAWYER_COMMANDLINE_SEQUENCE_SAVER(Optional, operator=);
493SAWYER_COMMANDLINE_SEQUENCE_SAVER(BitFlags, set);
494SAWYER_COMMANDLINE_MAP_PAIR_SAVER(std::map, insert);
495SAWYER_COMMANDLINE_MAP_SAVER(Sawyer::Container::Map, insert);
496SAWYER_COMMANDLINE_INTERVALSET_SAVER(Sawyer::Container::IntervalSet, insert);
497
499// Parsed value
501
508class SAWYER_EXPORT ParsedValue {
509#include <Sawyer/WarningsOff.h>
510 boost::any value_;
511 Location valueLocation_;
512 std::string valueString_;
513 std::string switchKey_;
514 Location switchLocation_;
515 std::string switchString_;
516 size_t keySequence_;
517 size_t switchSequence_;
518 ValueSaver::Ptr valueSaver_;
519#include <Sawyer/WarningsRestore.h>
520
521public:
522 ~ParsedValue();
523
526
536 ParsedValue(const boost::any value, const Location &loc, const std::string &str, const ValueSaver::Ptr &saver);
537
540 ParsedValue& switchInfo(const std::string &key, const Location &loc, const std::string &str);
541
542private:
543 friend class ParserResult;
544 void sequenceInfo(size_t keySequence, size_t switchSequence);
545
546public:
552 const boost::any& value() const;
553 void value(const boost::any &v);
564 const std::string& string() const;
565
571 int asInt() const;
572 unsigned asUnsigned() const;
573 long asLong() const;
574 unsigned long asUnsignedLong() const;
575 boost::int64_t asInt64() const;
576 boost::uint64_t asUnsigned64() const;
577 double asDouble() const;
578 float asFloat() const;
579 bool asBool() const;
580 std::string asString() const;
585 template<typename T> T as() const { return boost::any_cast<T>(value_); }
586
589 ParsedValue& switchKey(const std::string &s);
590 const std::string& switchKey() const;
600 const std::string& switchString() const;
601
606
609 size_t keySequence() const;
610
613 size_t switchSequence() const;
614
618
621 void save() const;
622
624 bool isEmpty() const;
625
627 void print(std::ostream&) const;
628};
629
631SAWYER_EXPORT std::ostream& operator<<(std::ostream&, const ParsedValue&);
632
634typedef std::vector<ParsedValue> ParsedValues;
635
636
637
638
640// Switch argument parsers
642
695class SAWYER_EXPORT ValueParser: public SharedObject, public SharedFromThis<ValueParser> {
696#include <Sawyer/WarningsOff.h>
697 ValueSaver::Ptr valueSaver_;
698#include <Sawyer/WarningsRestore.h>
699public:
700 virtual ~ValueParser();
701
702protected:
705
707 explicit ValueParser(const ValueSaver::Ptr &valueSaver);
708public:
711
715 ParsedValue matchString(const std::string&) /*final*/;
716
722
741private:
744 virtual ParsedValue operator()(Cursor&);
745 virtual ParsedValue operator()(const char *input, const char **endptr, const Location&);
747};
748
749// used internally to convert from one type to another via boost::lexical_cast or throw a runtime_error with a decent message.
750template<typename T>
752 static T convert(const std::string &src) {
753 try {
754 return boost::lexical_cast<T>(src);
755 } catch (const boost::bad_lexical_cast &e) {
756 throw std::runtime_error(e.what());
757 }
758 }
759};
760
761template<>
762struct LexicalCast<boost::regex> {
763 static boost::regex convert(const std::string &src) {
764 return boost::regex(src);
765 }
766};
767
768template<>
769struct LexicalCast<std::regex> {
770 static std::regex convert(const std::string &src) {
771 return std::regex(src);
772 }
773};
774
775template<>
776struct LexicalCast<boost::filesystem::path> {
777 static boost::filesystem::path convert(const std::string &src) {
778 return boost::filesystem::path(src);
779 }
780};
781
782template<>
783struct LexicalCast<boost::any> {
784 static boost::any convert(const std::string &src) {
785 return src;
786 }
787};
788
789template<typename T>
791 static T convert(const std::string &src) {
792 return LexicalCast<T>::convert(src);
793 }
794};
795
796template<typename T>
798 static T convert(const std::string &src) {
799 return LexicalCast<T>::convert(src);
800 }
801};
802
803template<typename T>
804struct LexicalCast<Sawyer::Container::Map<std::string, T> > {
805 static T convert(const std::string &src) {
806 return LexicalCast<T>::convert(src);
807 }
808};
809
810template<typename T>
811struct LexicalCast<std::vector<T> > {
812 static T convert(const std::string &src) {
813 return LexicalCast<T>::convert(src);
814 }
815};
816
817template<typename T>
818struct LexicalCast<std::set<T> > {
819 static T convert(const std::string &src) {
820 return LexicalCast<T>::convert(src);
821 }
822};
823
824template<typename T>
825struct LexicalCast<std::list<T> > {
826 static T convert(const std::string &src) {
827 return LexicalCast<T>::convert(src);
828 }
829};
830
831template<typename T>
832struct LexicalCast<std::map<std::string, T> > {
833 static T convert(const std::string &src) {
834 return LexicalCast<T>::convert(src);
835 }
836};
837
861template<typename T>
862class AnyParser: public ValueParser {
863protected:
866
869public:
872
876 static Ptr instance() { return Ptr(new AnyParser); }
877
882private:
883 virtual ParsedValue operator()(Cursor &cursor) /*override*/ {
884 if (cursor.atEnd())
885 throw std::runtime_error("string expected");
886 Location startLoc = cursor.location();
887 std::string s = cursor.rest();
888 cursor.consumeChars(s.size());
889 return ParsedValue(LexicalCast<T>::convert(s), startLoc, s, valueSaver());
890 }
891};
892
893// used internally to cast one numeric type to another and throw a range_error with a decent message.
894template<typename Target, typename Source>
896 static Target convert(Source from, const std::string &parsed) {
897 try {
898 return boost::numeric_cast<Target>(from);
899 } catch (const boost::numeric::positive_overflow&) {
900 std::string bound = boost::lexical_cast<std::string>(boost::numeric::bounds<Target>::highest());
901 throw std::range_error("parsed string \""+parsed+"\" is greater than "+bound);
902 } catch (const boost::numeric::negative_overflow&) {
903 std::string bound = boost::lexical_cast<std::string>(boost::numeric::bounds<Target>::lowest());
904 throw std::range_error("parsed string \""+parsed+"\" is less than "+bound);
905 } catch (const boost::numeric::bad_numeric_cast&) {
906 throw std::range_error("cannot cast \""+parsed+"\" to destination type");
907 }
908 }
909};
910
911// partial specialization for Sawyer::Optional<Target>
912template<typename Target, typename Source>
913struct NumericCast<Optional<Target>, Source> {
914 static Target convert(Source from, const std::string &parsed) {
915 return NumericCast<Target, Source>::convert(from, parsed);
916 }
917};
918
919// partial specialization for std::vector<Target>
920template<typename Target, typename Source>
921struct NumericCast<std::vector<Target>, Source> {
922 static Target convert(Source from, const std::string &parsed) {
923 return NumericCast<Target, Source>::convert(from, parsed);
924 }
925};
926
927// partial specialization for std::list<Target>
928template<typename Target, typename Source>
929struct NumericCast<std::list<Target>, Source> {
930 static Target convert(Source from, const std::string &parsed) {
931 return NumericCast<Target, Source>::convert(from, parsed);
932 }
933};
934
935// partial specialization for std::set<Target>
936template<typename Target, typename Source>
937struct NumericCast<std::set<Target>, Source> {
938 static Target convert(Source from, const std::string &parsed) {
939 return NumericCast<Target, Source>::convert(from, parsed);
940 }
941};
942
943// partial specialization for Sawyer::Container::Set<Target>
944template<typename Target, typename Source>
945struct NumericCast<Sawyer::Container::Set<Target>, Source> {
946 static Target convert(Source from, const std::string &parsed) {
947 return NumericCast<Target, Source>::convert(from, parsed);
948 }
949};
950
951// partial specialization for std::map<std::string, Target>
952template<typename Target, typename Source>
953struct NumericCast<std::map<std::string, Target>, Source> {
954 static Target convert(Source from, const std::string &parsed) {
955 return NumericCast<Target, Source>::convert(from, parsed);
956 }
957};
958
959// partial specialization for Sawyer::Container::Map<std::string, Target>
960template<typename Target, typename Source>
961struct NumericCast<Sawyer::Container::Map<std::string, Target>, Source> {
962 static Target convert(Source from, const std::string &parsed) {
963 return NumericCast<Target, Source>::convert(from, parsed);
964 }
965};
966
976template<typename T>
978protected:
981
984public:
987
994 static Ptr instance() { return Ptr(new IntegerParser); }
995
1003private:
1004 virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1005 errno = 0;
1006 boost::int64_t big = strtoll(input, (char**)rest, 0);
1007 if (*rest==input)
1008 throw std::runtime_error("integer expected");
1009 while (isspace(**rest)) ++*rest;
1010 std::string parsed(input, *rest-input);
1011 if (ERANGE==errno)
1012 throw std::range_error("integer overflow when parsing \""+parsed+"\"");
1013 return ParsedValue(NumericCast<T, boost::int64_t>::convert(big, parsed), loc, parsed, valueSaver());
1014 }
1015};
1016
1027template<typename T>
1029protected:
1032
1035public:
1038
1042 static Ptr instance() { return Ptr(new NonNegativeIntegerParser); }
1043
1048private:
1049 virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1050 errno = 0;
1051 while (isspace(*input)) ++input;
1052 if ('+'!=*input && !isdigit(*input))
1053 throw std::runtime_error("unsigned integer expected");
1054 boost::uint64_t big = strtoull(input, (char**)rest, 0);
1055 if (*rest==input)
1056 throw std::runtime_error("unsigned integer expected");
1057 while (isspace(**rest)) ++*rest;
1058 std::string parsed(input, *rest-input);
1059 if (ERANGE==errno)
1060 throw std::range_error("integer overflow when parsing \""+parsed+"\"");
1061 return ParsedValue(NumericCast<T, boost::uint64_t>::convert(big, parsed), loc, parsed, valueSaver());
1062 }
1063};
1064
1075template<typename T>
1077protected:
1080
1083public:
1086
1090 static Ptr instance() { return Ptr(new PositiveIntegerParser); }
1091
1096private:
1097 virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1098 errno = 0;
1099 while (isspace(*input)) ++input;
1100 if ('+'!=*input && !isdigit(*input))
1101 throw std::runtime_error("positive integer expected");
1102 boost::uint64_t big = strtoull(input, (char**)rest, 0);
1103 if (*rest==input || big==0)
1104 throw std::runtime_error("positive integer expected");
1105 while (isspace(**rest)) ++*rest;
1106 std::string parsed(input, *rest-input);
1107 if (ERANGE==errno)
1108 throw std::range_error("integer overflow when parsing \""+parsed+"\"");
1109 return ParsedValue(NumericCast<T, boost::uint64_t>::convert(big, parsed), loc, parsed, valueSaver());
1110 }
1111};
1112
1122template<typename T>
1124protected:
1127
1130public:
1133
1137 static Ptr instance() { return Ptr(new RealNumberParser); }
1138
1143private:
1144 virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1145 double big = strtod(input, (char**)rest);
1146 if (*rest==input)
1147 throw std::runtime_error("real number expected");
1148 while (isspace(**rest)) ++*rest;
1149 std::string parsed(input, *rest-input);
1150 return ParsedValue(NumericCast<T, double>::convert(big, parsed), loc, parsed, valueSaver());
1151 }
1152};
1153
1160template<typename T>
1162protected:
1165
1168public:
1171
1175 static Ptr instance() { return Ptr(new BooleanParser); }
1176
1181private:
1182 virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1183 static const char *neg[] = {"false", "off", "no", "0", "f", "n"}; // longest to shortest
1184 static const char *pos[] = {"true", "yes", "on", "1", "t", "y"};
1185 const char *start = input;
1186 while (isspace(*input)) ++input;
1187 for (int negpos=0; negpos<2; ++negpos) {
1188 const char **list = 0==negpos ? neg : pos;
1189 size_t listsz = 0==negpos ? sizeof(neg)/sizeof(*neg) : sizeof(pos)/sizeof(*pos);
1190 for (size_t i=0; i<listsz; ++i) {
1191 if (0==my_strncasecmp(list[i], input, strlen(list[i]))) {
1192 *rest = input + strlen(list[i]);
1193 while (isspace(**rest)) ++*rest;
1194 std::string parsed(start, *rest-start);
1195 return ParsedValue(NumericCast<T, bool>::convert(0!=negpos, parsed), loc, parsed, valueSaver());
1196 }
1197 }
1198 }
1199 throw std::runtime_error("Boolean expected");
1200 }
1201
1202 // Microsoft doesn't have the POSIX.1-2001 strncasecmp function
1203 int my_strncasecmp(const char *a, const char *b, size_t nchars) {
1204 ASSERT_not_null(a);
1205 ASSERT_not_null(b);
1206 for (size_t i=0; i<nchars; ++i) {
1207 if (!a[i] || !b[i])
1208 return a[i] ? 1 : (b[i] ? -1 : 0);
1209 char achar = (char)tolower(a[i]);
1210 char bchar = (char)tolower(b[i]);
1211 if (achar != bchar)
1212 return achar < bchar ? -1 : 1;
1213 }
1214 return 0;
1215 }
1216};
1217
1226class SAWYER_EXPORT StringSetParser: public ValueParser {
1227#include <Sawyer/WarningsOff.h>
1228 std::vector<std::string> strings_;
1229#include <Sawyer/WarningsRestore.h>
1230public:
1232
1233protected:
1236
1239public:
1242
1246 static Ptr instance();
1247
1252
1255 Ptr with(const std::string&);
1256 Ptr with(const std::vector<std::string>);
1257 template<class InputIterator>
1258 Ptr with(InputIterator begin, InputIterator end) {
1259 strings_.insert(strings_.end(), begin, end);
1260 return sharedFromThis().dynamicCast<StringSetParser>();
1261 }
1264private:
1265 virtual ParsedValue operator()(Cursor&) /*override*/;
1266};
1267
1275template<typename T>
1277 StringSetParser::Ptr strParser_;
1279protected:
1282
1285public:
1288
1292 static Ptr instance() { return Ptr(new EnumParser); }
1293
1298
1300 Ptr with(const std::string &name, T value) {
1301 strParser_->with(name);
1302 members_.insert(name, value);
1303 return sharedFromThis().template dynamicCast<EnumParser>();
1304 }
1305private:
1306 virtual ParsedValue operator()(Cursor &cursor) /*override*/ {
1307 ParsedValue strVal = strParser_->match(cursor);
1308 return ParsedValue(members_[strVal.string()], strVal.valueLocation(), strVal.string(), valueSaver());
1309 }
1310};
1311
1319class SAWYER_EXPORT ListParser: public ValueParser {
1320 typedef std::pair<ValueParser::Ptr, std::string> ParserSep;
1321#include <Sawyer/WarningsOff.h>
1322 std::vector<ParserSep> elements_;
1323 size_t minLength_, maxLength_; // limits on the number of values permitted
1324#include <Sawyer/WarningsRestore.h>
1325public:
1326 ~ListParser();
1327 ListParser() = delete;
1328protected:
1330 ListParser(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe);
1331
1332public:
1335
1337 typedef std::list<ParsedValue> ValueList;
1338
1346 static Ptr instance(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe="[,;:]\\s*");
1347
1354 Ptr nextMember(const ValueParser::Ptr &elmtType, const std::string &separatorRe="[,;:]\\s*");
1355
1362 Ptr limit(size_t minLength, size_t maxLength);
1363 Ptr limit(size_t maxLength);
1364 Ptr exactly(size_t length);
1366private:
1367 virtual ParsedValue operator()(Cursor&) /*override*/;
1368};
1369
1425template<typename T>
1426typename AnyParser<T>::Ptr anyParser(T &storage) {
1428}
1429template<typename T>
1431 return AnyParser<T>::instance();
1432}
1434
1435template<typename T>
1439template<typename T>
1444
1445template<typename T>
1449template<typename T>
1454
1455template<typename T>
1459template<typename T>
1464
1465template<typename T>
1469template<typename T>
1474
1475template<typename T>
1479template<typename T>
1484
1485template<typename T>
1486typename EnumParser<T>::Ptr enumParser(T &storage) {
1488}
1489template<typename T>
1490typename EnumParser<T>::Ptr enumParser(std::vector<T> &storage) {
1491 return EnumParser<T>::instance(TypedSaver<std::vector<T> >::instance(storage));
1492}
1493template<typename T>
1495 return EnumParser<T>::instance(TypedSaver<Optional<T> >::instance(storage));
1496}
1497template<typename T>
1499 return EnumParser<T>::instance(TypedSaver<BitFlags<T> >::instance(storage));
1500}
1501template<typename T>
1505
1506SAWYER_EXPORT StringSetParser::Ptr stringSetParser(std::string &storage);
1508
1509SAWYER_EXPORT ListParser::Ptr listParser(const ValueParser::Ptr&, const std::string &sepRe="[,;:]\\s*");
1514// Switch argument descriptors
1516
1531class SAWYER_EXPORT SwitchArgument {
1532#include <Sawyer/WarningsOff.h>
1533 std::string name_; // argument name for synopsis
1534 ValueParser::Ptr parser_; // how to match and parse this argument
1535 ParsedValue defaultValue_; // default value if the argument is optional
1536#include <Sawyer/WarningsRestore.h>
1537public:
1539
1542 explicit SwitchArgument(const std::string &name, const ValueParser::Ptr &parser = anyParser());
1543
1547 SwitchArgument(const std::string &name, const ValueParser::Ptr &parser, const std::string &defaultValueString);
1548
1550 bool isRequired() const;
1551
1554 bool isOptional() const;
1555
1561 const std::string& name() const;
1562
1564 std::string nameAsText() const;
1565
1568
1572 const std::string& defaultValueString() const;
1573
1575 const ValueParser::Ptr& parser() const;
1576};
1577
1578
1580// Switch actions
1582
1598class SAWYER_EXPORT SwitchAction: public SharedObject {
1599public:
1602 virtual ~SwitchAction();
1603 SwitchAction();
1604
1606 void run(const ParserResult &parserResult); // final
1607protected:
1608 virtual void operator()(const ParserResult&) = 0;
1609};
1610
1614class SAWYER_EXPORT ShowVersion: public SwitchAction {
1615#include <Sawyer/WarningsOff.h>
1616 std::string versionString_;
1617#include <Sawyer/WarningsRestore.h>
1618public:
1619 ~ShowVersion();
1620 ShowVersion() = delete;
1621protected:
1623 explicit ShowVersion(const std::string &versionString);
1624public:
1627
1632 static Ptr instance(const std::string &versionString);
1633protected:
1634 virtual void operator()(const ParserResult&) /*overload*/;
1635};
1636
1639class SAWYER_EXPORT ShowVersionAndExit: public ShowVersion {
1640 int exitStatus_;
1641public:
1643 ShowVersionAndExit() = delete;
1644protected:
1646 explicit ShowVersionAndExit(const std::string &versionString, int exitStatus);
1647public:
1650
1655 static Ptr instance(const std::string &versionString, int exitStatus);
1656protected:
1657 virtual void operator()(const ParserResult&) /*overload*/;
1658};
1659
1664class SAWYER_EXPORT ShowHelp: public SwitchAction {
1665public:
1666 ~ShowHelp();
1667protected:
1670public:
1673
1678 static Ptr instance();
1679protected:
1680 virtual void operator()(const ParserResult&) /*override*/;
1681};
1682
1685class SAWYER_EXPORT ShowHelpAndExit: public ShowHelp {
1686 int exitStatus_;
1687public:
1689 ShowHelpAndExit() = delete;
1690protected:
1692 explicit ShowHelpAndExit(int exitStatus);
1693public:
1696
1701 static Ptr instance(int exitStatus);
1702protected:
1703 virtual void operator()(const ParserResult&) /*override*/;
1704};
1705
1721class SAWYER_EXPORT ConfigureDiagnostics: public SwitchAction {
1722#include <Sawyer/WarningsOff.h>
1723 std::string switchKey_;
1724 Message::Facilities &facilities_;
1725 bool exitOnHelp_;
1726#include <Sawyer/WarningsRestore.h>
1727public:
1729 ConfigureDiagnostics() = delete;
1730protected:
1732 ConfigureDiagnostics(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp);
1733public:
1736
1741 static Ptr instance(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp = true);
1742
1748 bool exitOnHelp() const;
1749 void exitOnHelp(bool);
1751protected:
1752 virtual void operator()(const ParserResult&) /*override*/;
1753};
1754
1762class SAWYER_EXPORT ConfigureDiagnosticsQuiet: public SwitchAction {
1763#include <Sawyer/WarningsOff.h>
1764 Message::Facilities &facilities_;
1765#include <Sawyer/WarningsRestore.h>
1766public:
1768 ConfigureDiagnosticsQuiet() = delete;
1769protected:
1771
1772public:
1775
1780 static Ptr instance(Message::Facilities &facilities);
1781
1782protected:
1783 virtual void operator()(const ParserResult&) /*override*/;
1784};
1785
1805template<class Functor>
1807 Functor &functor_;
1808protected:
1810 UserAction(Functor &f): functor_(f) {}
1811public:
1814
1819 static Ptr instance(Functor &f) { return Ptr(new UserAction(f)); }
1820protected:
1821 virtual void operator()(const ParserResult &parserResult) /*override*/ { (functor_)(parserResult); }
1822};
1823
1853SAWYER_EXPORT ShowVersion::Ptr showVersion(const std::string &versionString);
1854SAWYER_EXPORT ShowVersionAndExit::Ptr showVersionAndExit(const std::string &versionString, int exitStatus);
1855
1856SAWYER_EXPORT ShowHelp::Ptr showHelp();
1857
1858SAWYER_EXPORT ShowHelpAndExit::Ptr showHelpAndExit(int exitStatus);
1859
1860SAWYER_EXPORT ConfigureDiagnostics::Ptr configureDiagnostics(const std::string&, Message::Facilities&, bool exitOnHelp=true);
1861
1863
1864template<class Functor>
1865typename UserAction<Functor>::Ptr userAction(const Functor &functor) {
1866 return UserAction<Functor>::instance(functor);
1867}
1873// Switch value agumenters
1875
1890class SAWYER_EXPORT ValueAugmenter: public SharedObject {
1891public:
1894 virtual ~ValueAugmenter();
1895
1900 virtual ParsedValues operator()(const ParsedValues &savedValues, const ParsedValues &newValues) = 0;
1901};
1902
1915template<typename T>
1916class Sum: public ValueAugmenter {
1917protected:
1919 Sum() {}
1920public:
1923
1928 static Ptr instance() { return Ptr(new Sum<T>); }
1929
1930 virtual ParsedValues operator()(const ParsedValues &savedValues, const ParsedValues &newValues) /*override*/ {
1931 ASSERT_forbid(newValues.empty());
1932 T sum = 0;
1933 BOOST_FOREACH (const ParsedValue &pv, savedValues)
1934 sum = sum + boost::any_cast<T>(pv.value());
1935 BOOST_FOREACH (const ParsedValue &pv, newValues)
1936 sum = sum + boost::any_cast<T>(pv.value());
1937 ParsedValue pval = newValues.front(); // so we keep the same location information
1938 pval.value(sum);
1939 ParsedValues pvals;
1940 pvals.push_back(pval);
1941 return pvals;
1942 }
1943};
1944
1974template<typename T>
1975typename Sum<T>::Ptr sum() {
1976 return Sum<T>::instance();
1977}
1983// Switch descriptors
1985
1986// Used internally to pass around switch properties that are common among parsers, switch groups, and switches.
1987struct SAWYER_EXPORT ParsingProperties {
1988#include <Sawyer/WarningsOff.h>
1989 std::vector<std::string> longPrefixes; // Prefixes for long command-line switches
1990 bool inheritLongPrefixes; // True if this also inherits longPrefixes from a higher layer
1991 std::vector<std::string> shortPrefixes;
1992 bool inheritShortPrefixes;
1993 std::vector<std::string> valueSeparators; // What separates a long switch from its value.
1994 bool inheritValueSeparators;
1995 ShowGroupName showGroupName; // How to show group name in switch synopsis
1996#include <Sawyer/WarningsRestore.h>
1999 ParsingProperties inherit(const ParsingProperties &base) const;
2000};
2001
2011
2034class SAWYER_EXPORT Switch {
2035private:
2036#include <Sawyer/WarningsOff.h>
2037 std::vector<std::string> longNames_; // Long name of switch, or empty string.
2038 std::string shortNames_; // Optional short names for this switch.
2039 std::string key_; // Unique key, usually the long name or the first short name.
2040 ParsingProperties properties_; // Properties valid at multiple levels of the hierarchy.
2041 std::string synopsis_; // User-defined synopsis or empty string.
2042 std::string documentation_; // Main documentation for the switch.
2043 std::string documentationKey_; // For sorting documentation.
2044 bool hidden_; // Whether to hide documentation.
2045 std::vector<SwitchArgument> arguments_; // Arguments with optional default values.
2046 SwitchAction::Ptr action_; // Optional action to perform during ParserResult::apply.
2047 WhichValue whichValue_; // Which switch values should be saved.
2048 ValueAugmenter::Ptr valueAugmenter_; // Used if <code>whichValue_==SAVE_AUGMENTED</code>.
2049 ParsedValue intrinsicValue_; // Value for switches that have no declared arguments.
2050 bool explosiveLists_; // Whether to expand ListParser::ValueList into separate values.
2051 SwitchSkipping skipping_; // Whether to skip over this switch without saving or acting.
2052#include <Sawyer/WarningsRestore.h>
2053
2054public:
2055 ~Switch();
2056 Switch() = delete;
2057
2070 explicit Switch(const std::string &longName, char shortName='\0');
2071
2072 // FIXME[Robb Matzke 2014-03-03]: test that "--prefix=5" works when names are "pre" and "prefix" in that order
2077 Switch& longName(const std::string &name);
2078 const std::string& longName() const;
2079 const std::vector<std::string>& longNames() const;
2088 const std::string& shortNames() const;
2093 std::string preferredName() const;
2094
2103 Switch& key(const std::string &s);
2104 const std::string& key() const;
2138 Switch& synopsis(const std::string &s);
2139 std::string synopsis() const;
2177 Switch& doc(const std::string &s);
2178 const std::string& doc() const;
2185 Switch& docKey(const std::string &s);
2186 const std::string& docKey() const;
2193 Switch& hidden(bool b);
2194 bool hidden() const;
2223 Switch& resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2224 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2225 Switch& longPrefix(const std::string &s1);
2226 const std::vector<std::string>& longPrefixes() const;
2240 Switch& resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2241 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2242 Switch& shortPrefix(const std::string &s1);
2243 const std::vector<std::string>& shortPrefixes() const;
2262 Switch& resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2263 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2264 Switch& valueSeparator(const std::string &s1);
2265 const std::vector<std::string>& valueSeparators() const;
2290 Switch& argument(const std::string &name, const ValueParser::Ptr &parser = anyParser());
2291 Switch& argument(const std::string &name, const ValueParser::Ptr &parser, const std::string &defaultValue);
2293 const SwitchArgument& argument(size_t idx) const;
2294 const std::vector<SwitchArgument>& arguments() const;
2298 size_t nArguments() const;
2299
2302 size_t nRequiredArguments() const;
2303
2333 template<typename T>
2334 Switch& intrinsicValue(const T &value, T &storage) {
2335 intrinsicValue_ = ParsedValue(value, NOWHERE, boost::lexical_cast<std::string>(value), TypedSaver<T>::instance(storage));
2336 return *this;
2337 }
2338 Switch& intrinsicValue(const char *value, std::string &storage);
2339 Switch& intrinsicValue(const std::string &text, const ValueParser::Ptr &p);
2340 Switch& intrinsicValue(const std::string &text);
2368 bool explosiveLists() const;
2437public:
2438 // Used internally
2439 const ParsingProperties& properties() const;
2440
2441private:
2442 friend class Parser;
2443 friend class ParserResult;
2444
2445 void init(const std::string &longName, char shortName);
2446
2448 std::runtime_error noSeparator(const std::string &switchString, const Cursor&, const ParsingProperties&) const;
2449
2451 std::runtime_error extraTextAfterSwitch(const std::string &switchString, const Location &endOfSwitch, const Cursor&,
2452 const ParsingProperties&, const ParsedValues&) const;
2453
2455 std::runtime_error extraTextAfterArgument(const Cursor&, const ParsedValue &va) const;
2456
2458 std::runtime_error notEnoughArguments(const std::string &switchString, const Cursor&, size_t nargs) const;
2459
2461 std::runtime_error missingArgument(const std::string &switchString, const Cursor &cursor,
2462 const SwitchArgument &sa, const std::string &reason) const;
2463
2465 std::runtime_error malformedArgument(const std::string &switchString, const Cursor &cursor,
2466 const SwitchArgument &sa, const std::string &reason) const;
2467
2474 size_t matchLongName(Cursor&/*in,out*/, const ParsingProperties &props,
2475 const std::string &optionalPart, const std::string &requiredPart) const;
2476
2483 size_t matchShortName(Cursor&/*in,out*/, const ParsingProperties &props, std::string &name) const;
2484
2486 bool explode(ParsedValues &pvals /*in,out*/) const;
2487
2492 void matchLongArguments(const std::string &switchString, Cursor &cursor /*in,out*/, const ParsingProperties &props,
2493 ParsedValues &result /*out*/) const;
2494
2498 void matchShortArguments(const std::string &switchString, Cursor &cursor /*in,out*/, const ParsingProperties &props,
2499 ParsedValues &result /*out*/, bool mayNestle) const;
2500
2508 size_t matchArguments(const std::string &switchString, const Location &endOfSwitch, Cursor &cursor /*in,out*/,
2509 const ParsingProperties &props, ParsedValues &result /*out*/, bool isLongSwitch) const;
2510
2512 std::string synopsisForArgument(const SwitchArgument&) const;
2513
2514 // If the synopsis is empty, create one from an optional switch group and name space separator
2515 std::string synopsis(const ParsingProperties &swProps, const SwitchGroup *sg, const std::string &nameSpaceSeparator) const;
2516};
2517
2519// Switch groups
2521
2522
2550class SAWYER_EXPORT SwitchGroup {
2551#include <Sawyer/WarningsOff.h>
2552 std::vector<Switch> switches_;
2553 ParsingProperties properties_;
2554 std::string name_; // name optionally prepended to all switches
2555 std::string title_; // title showing in documentation
2556 std::string docKey_; // for sorting
2557 std::string documentation_;
2558 SortOrder switchOrder_;
2559#include <Sawyer/WarningsRestore.h>
2560public:
2561 ~SwitchGroup();
2562
2565
2572 explicit SwitchGroup(const std::string &title, const std::string &docKey = "");
2573
2579 const std::string& title() const;
2580 SwitchGroup& title(const std::string &title);
2593 const std::string& name() const;
2594 SwitchGroup& name(const std::string &name);
2609 const std::string& docKey() const;
2610 SwitchGroup& docKey(const std::string &key);
2625 SwitchGroup& doc(const std::string &s);
2626 const std::string& doc() const;
2641 SwitchGroup& resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2642 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2643 SwitchGroup& longPrefix(const std::string &s1);
2644 const std::vector<std::string>& longPrefixes() const;
2649 SwitchGroup& resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2650 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2651 SwitchGroup& shortPrefix(const std::string &s1);
2652 const std::vector<std::string>& shortPrefixes() const;
2657 SwitchGroup& resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2658 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2659 SwitchGroup& valueSeparator(const std::string &s1);
2660 const std::vector<std::string>& valueSeparators() const;
2664 size_t nSwitches() const;
2665
2668 const std::vector<Switch>& switches() const;
2669
2671 bool nameExists(const std::string &switchName);
2672
2675 const Switch& getByName(const std::string &switchName);
2676
2678 bool keyExists(const std::string &switchKey);
2679
2681 const Switch& getByKey(const std::string &switchKey);
2682
2685
2688
2691
2694 SwitchGroup& removeByName(const std::string &switchName);
2695
2697 SwitchGroup& removeByKey(const std::string &switchKey);
2698
2710 const SortOrder& switchOrder() const;
2714public:
2715 // Used internally
2716 const ParsingProperties& properties() const;
2717
2718private:
2719 friend class Parser;
2720 bool removeByPointer(const void*);
2721};
2722
2725
2728
2730// Parser
2732
2738class SAWYER_EXPORT Parser {
2739#include <Sawyer/WarningsOff.h>
2740 std::vector<SwitchGroup> switchGroups_;
2741 ParsingProperties properties_;
2742 std::string groupNameSeparator_;
2743 std::vector<std::string> terminationSwitches_;
2744 bool shortMayNestle_;
2745 std::vector<std::string> inclusionPrefixes_;
2746 bool skipNonSwitches_;
2747 bool skipUnknownSwitches_;
2748 mutable std::string programName_;
2749 std::string purpose_;
2750 std::string versionString_;
2751 mutable std::string dateString_;
2752 int chapterNumber_;
2753 std::string chapterName_;
2755 StringStringMap sectionDoc_;
2756 StringStringMap sectionOrder_;
2757 Message::SProxy errorStream_;
2758 Optional<std::string> exitMessage_;
2759 SortOrder switchGroupOrder_;
2760 bool reportingAmbiguities_;
2761 std::string environmentVariable_;
2762#include <Sawyer/WarningsRestore.h>
2763
2764public:
2765 ~Parser();
2766
2770
2775 Parser& with(const SwitchGroup &sg, const std::string &docKey);
2776 Parser& with(const std::vector<SwitchGroup> &sgs);
2777 Parser& with(const Switch &sw);
2778 Parser& with(Switch sw, const std::string &docKey);
2784 const std::vector<SwitchGroup>& switchGroups() const;
2785 std::vector<SwitchGroup>& switchGroups();
2791 bool switchGroupExists(const std::string &name) const;
2792
2799 const SwitchGroup& switchGroup(const std::string &name) const;
2800 SwitchGroup& switchGroup(const std::string &name);
2807 bool eraseSwitchGroup(const std::string &name);
2808
2831 const std::string& groupNameSeparator() const;
2832 Parser& groupNameSeparator(const std::string &s);
2852 Parser& resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2853 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2854 Parser& longPrefix(const std::string &s1);
2855 const std::vector<std::string>& longPrefixes() const;
2862 Parser& resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2863 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2864 Parser& shortPrefix(const std::string &s1);
2865 const std::vector<std::string>& shortPrefixes() const;
2874 Parser& resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2875 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2876 Parser& valueSeparator(const std::string &s1);
2877 const std::vector<std::string>& valueSeparators() const;
2884 Parser& resetTerminationSwitches(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2885 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2886 Parser& terminationSwitch(const std::string &s1);
2887 const std::vector<std::string>& terminationSwitches() const;
2898 bool shortMayNestle() const;
2912 Parser& resetInclusionPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2913 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2914 Parser& inclusionPrefix(const std::string &s1);
2915 const std::vector<std::string>& inclusionPrefixes() const;
2966 Parser& exitMessage(const std::string &s);
2967 std::string exitMessage() const;
2976 Parser& environmentVariable(const std::string &s);
2977 const std::string& environmentVariable() const;
2983 ParserResult parse(int argc, char *argv[]);
2984
2986 ParserResult parse(const std::vector<std::string>&);
2987
2988#if 0 /* [Robb Matzke 2014-03-04] */
2991 template<typename Iterator>
2992 ParserResult parse(Iterator begin, Iterator end) {
2993 std::vector<std::string> args(begin, end);
2994 return parse(args);
2995 }
2996#endif
2997
3001 static std::vector<std::string> splitLineIntoWords(std::string);
3002
3008 static std::vector<std::string> readArgsFromFile(const std::string &filename);
3009
3014 static std::vector<std::string> readArgsFromEnvVar(const std::string &varName);
3015
3020 std::vector<std::string> expandIncludedFiles(const std::vector<std::string> &args);
3021
3024 DEFAULT_GROUPING = 0,
3025 PROHIBIT_EMPTY_GROUPS = 0x0001,
3026 SPLIT_SINGLE_GROUP = 0x0002
3028
3036 std::vector<std::vector<std::string> >
3037 regroupArgs(const std::vector<std::string> &args,
3039 unsigned flags = 0 /*GroupingFlags*/);
3040
3044 Parser& programName(const std::string& programName);
3045 const std::string& programName() const;
3052 Parser& purpose(const std::string &purpose);
3053 const std::string& purpose() const;
3059 Parser& version(const std::string &versionString, const std::string &dateString="");
3060 Parser& version(const std::pair<std::string, std::string> &p);
3061 std::pair<std::string, std::string> version() const;
3079 Parser& chapter(int chapterNumber, const std::string &chapterName="");
3080 Parser& chapter(const std::pair<int, std::string> &p);
3081 std::pair<int, std::string> chapter() const;
3122 Parser& doc(const std::string &sectionName, const std::string &docKey, const std::string &text);
3123 Parser& doc(const std::string &sectionName, const std::string &text);
3124 Parser& doc(const std::pair<std::string /*sectionName*/, std::string /*text*/>&);
3125 std::vector<std::string> docSections() const;
3126 std::string docForSwitches() const;
3127 std::string docForSection(const std::string &sectionName) const;
3134 std::string documentationMarkup() const;
3135
3139 std::string podDocumentation() const;
3140
3142 std::string textDocumentation() const;
3143
3146
3147 template<class Grammar>
3148 bool emitDocumentationToPager() const {
3149 Grammar grammar;
3150 initDocGrammar(grammar);
3151 grammar.title(programName(), boost::lexical_cast<std::string>(chapter().first), chapter().second);
3152 grammar.version(version().first, version().second);
3153 return grammar.emit(documentationMarkup());
3154 }
3155
3168 void insertLongSwitchStrings(Canonical, NamedSwitches &index /*in,out*/) const;
3169
3173 void insertShortSwitchStrings(NamedSwitches &index /*in,out*/) const;
3174
3179 void insertSwitchStrings(Canonical, NamedSwitches &index /*in,out*/) const;
3180
3184 static void printIndex(std::ostream&, const NamedSwitches&, const std::string &linePrefix = "");
3185
3190
3195
3208 Sawyer::Optional<Switch> removeMatchingSwitch(const std::vector<std::string> &args);
3211public:
3212 // Used internally
3213 const ParsingProperties& properties() const;
3214
3215private:
3216 void init();
3217
3218 // Implementation for the public parse methods.
3219 ParserResult parseInternal(std::vector<std::string> programArguments);
3220
3221 // Parse one switch from the current position in the command line and return the switch descriptor. If the cursor is at
3222 // the end of the command line then return false without updating the cursor or parsed values. If the cursor is at a
3223 // termination switch (e.g., "--") then consume the terminator and return false. If the switch name is valid but the
3224 // arguments cannot be parsed, then throw an error. If the cursor is at what appears to be a switch but no matching switch
3225 // declaration can be found, then throw an error. The cursor will not be modified when an error is thrown.
3226 bool parseOneSwitch(Cursor&, const NamedSwitches &ambiguities, ParserResult&/*out*/);
3227
3234 const Switch* parseLongSwitch(Cursor&, ParsedValues&, const NamedSwitches &ambiguities, Optional<std::runtime_error>&);
3235
3244 const Switch* parseShortSwitch(Cursor&, ParsedValues&, const NamedSwitches &ambiguities,
3245 Optional<std::runtime_error>&, bool mayNestle);
3246
3247 // Returns true if the program argument at the cursor looks like it might be a switch. Apparent switches are any program
3248 // argument that starts with a long or short prefix.
3249 bool apparentSwitch(const Cursor&) const;
3250
3251 // Returns the best prefix for each switch--the one used for documentation
3252 void preferredSwitchPrefixes(Container::Map<std::string, std::string> &prefixMap /*out*/) const;
3253
3254 // Construct an error message for an ambiguous switch, switchString, having an optional group name part (including the
3255 // separator), and the required switch name. The switchString must be present in the ambiguities table.
3256 std::string ambiguityErrorMesg(const std::string &longSwitchString, const std::string &optionalPart,
3257 const std::string &longSwitchName, const NamedSwitches &ambiguities);
3258 std::string ambiguityErrorMesg(const std::string &shortSwitchString, const NamedSwitches &ambiguities);
3259
3260 // Initialize a documentation parser by registering things like @s, @man, etc. The argument is a subclass such as
3261 // Document::PodMarkup.
3262 void initDocGrammar(Document::Markup::Grammar& /*in,out*/) const;
3263
3264 // FIXME[Robb Matzke 2014-02-21]: Some way to parse command-lines from a config file, or to merge parsed command-lines with
3265 // a yaml config file, etc.
3266};
3267
3292class SAWYER_EXPORT ParserResult {
3293#include <Sawyer/WarningsOff.h>
3294 Parser parser_;
3295 Cursor cursor_;
3296 ParsedValues values_;
3297
3298 // Maps a name to indexes into the values_ vector.
3300 NameIndex keyIndex_; // Values per switch key
3301 NameIndex switchIndex_; // Values per switch preferred name
3302
3303 // List of parsed values organized by their location on the command line. The location is for the switch itself even if
3304 // the values are spread out across subsequent argv members. We do it this way because many of the values are defaults that
3305 // don't actually have an argv location. The integers are indexes into the values_ vector. In other words, this is a
3306 // mapping from switch location to values_ elements for the switch's values.
3308 ArgvIndex argvIndex_;
3309
3310 // Information about program arguments that the parser skipped over. Indexes into argv_.
3311 typedef std::vector<size_t> SkippedIndex;
3312 SkippedIndex skippedIndex_;
3313
3314 // Information about terminator switches like "--". Indexes into argv_.
3315 SkippedIndex terminators_;
3316
3319#include <Sawyer/WarningsRestore.h>
3320
3321public:
3322 ~ParserResult();
3323 ParserResult();
3324
3325private:
3326 friend class Parser;
3327 ParserResult(const Parser &parser, const std::vector<std::string> &argv);
3328
3329public:
3332 const ParserResult& apply() const;
3333
3336 size_t have(const std::string &switchKey) const;
3337
3356 const ParsedValue& parsed(const std::string &switchKey, size_t idx) const;
3357 ParsedValues parsed(const std::string &switchKey) const;
3370 std::vector<std::string> skippedArgs() const;
3371
3378 std::vector<std::string> unreachedArgs() const;
3379
3394 std::vector<std::string> unparsedArgs(bool includeTerminators=false) const;
3395
3400 std::vector<std::string> parsedArgs() const;
3401
3406 const std::vector<std::string>& allArgs() const;
3407
3409 const Parser& parser() const;
3410
3411private:
3412 // Insert more parsed values. Values should be inserted one switch's worth at a time (or fewer)
3413 void insertValuesForSwitch(const ParsedValues&, const Parser*, const Switch*);
3414 void insertOneValue(const ParsedValue&, const Switch*, bool save=true);
3415
3416 // Indicate that we're skipping over a program argument
3417 void skip(const Location&);
3418
3419 // Add a terminator
3420 void terminator(const Location&);
3421
3422 Cursor& cursor();
3423};
3424
3425} // namespace
3426} // namespace
3427
3428#endif
Stores a vector of enum bit flags.
Parses any argument as plain text.
AnyParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
AnyParser()
Constructor for derived classes.
static Ptr instance()
Allocating constructor.
SharedPointer< AnyParser > Ptr
Reference counting pointer for this class.
Parses a boolean value and converts it to numeric type T.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
static Ptr instance()
Allocating constructor.
SharedPointer< BooleanParser > Ptr
Reference counting pointer for this class.
BooleanParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
BooleanParser()
Constructor for derived classes.
Function to configure diagnostics to quiet mode.
SharedPointer< ConfigureDiagnosticsQuiet > Ptr
Reference counting pointer for this class.
static Ptr instance(Message::Facilities &facilities)
Allocating constructor.
Functor to configure diagnostics.
static Ptr instance(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp=true)
Allocating constructor.
bool exitOnHelp() const
Property: program exit after help is displayed.
ConfigureDiagnostics(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp)
Constructor for derived classes.
void exitOnHelp(bool)
Property: program exit after help is displayed.
SharedPointer< ConfigureDiagnostics > Ptr
Reference counting pointer for this class.
Input stream for command line arguments.
const std::string & arg() const
Return the entire current program argument regardless of where the cursor is in that argument.
std::string rest() const
Return the part of an argument at and beyond the cursor location.
void replace(const std::vector< std::string > &)
Replace the current string with new strings.
const std::vector< std::string > & strings() const
All strings for the cursor.
void consumeArgs(size_t nargs)
Advance the cursor to the beginning of the next string.
Cursor()
Constructs a not-very-useful cursor to nothing.
Cursor(const std::vector< std::string > &strings)
Construct a cursor from an ordered set of strings.
bool atArgEnd() const
True when the cursor is at the end of an argument.
const Location & location() const
Property: current position of the cursor.
void consumeArg()
Advance the cursor to the beginning of the next string.
std::string rest(const Location &location) const
Return the part of an argument at and beyond the cursor location.
std::string substr(const Location &limit, const std::string &separator=" ") const
Returns all characters within limits.
void consumeChars(size_t nchars)
Advance over characters.
bool atArgBegin() const
True when the cursor is at the beginning of an argument.
Cursor & location(const Location &loc)
Property: current position of the cursor.
const std::string & arg(const Location &location) const
Return the entire current program argument regardless of where the cursor is in that argument.
bool atEnd() const
Returns true when the cursor is after all arguments.
Cursor(const std::string &string)
Constructs a cursor for a single string.
size_t linearDistance() const
Number of characters from the beginning of the cursor to its current location.
bool atEnd(const Location &location) const
Returns true when the cursor is after all arguments.
std::string substr(const Location &limit1, const Location &limit2, const std::string &separator=" ") const
Returns all characters within limits.
Parses an enumerated constant.
EnumParser()
Constructor for derived classes.
SharedPointer< EnumParser > Ptr
Reference counting pointer for this class.
static Ptr instance()
Allocating constructor.
EnumParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
Ptr with(const std::string &name, T value)
Adds enum members.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
Guards a cursor and restores it when the guard is destroyed.
ExcursionGuard(Cursor &)
Construct a guard for a cursor.
const Location & startingLocation() const
Starting location.
void cancel()
Cancel the excursion guard.
Parses an integer and converts it to numeric type T.
static Ptr instance()
Allocating constructor.
IntegerParser()
Constructor for derived classes.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
IntegerParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
SharedPointer< IntegerParser > Ptr
Reference counting pointer for this class.
static Ptr instance(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe="[,;:]\\s*")
Allocating constructor.
Ptr limit(size_t maxLength)
Specify limits for the number of values parsed.
Ptr nextMember(const ValueParser::Ptr &elmtType, const std::string &separatorRe="[,;:]\\s*")
Specifies element type and separator.
SharedPointer< ListParser > Ptr
Reference counting pointer for this class.
Ptr limit(size_t minLength, size_t maxLength)
Specify limits for the number of values parsed.
ListParser(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe)
Constructor for derived classes.
Ptr exactly(size_t length)
Specify limits for the number of values parsed.
std::list< ParsedValue > ValueList
Value type for list ParsedValue.
Parses a non-negative integer and converts it to numeric type T.
NonNegativeIntegerParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
SharedPointer< NonNegativeIntegerParser > Ptr
Reference counting pointer for this class.
static Ptr instance()
Allocating constructor.
NonNegativeIntegerParser()
Constructor for derived classes.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
Information about a parsed switch value.
bool isEmpty() const
True if the value is void.
const std::string & switchString() const
The string for the switch that caused this value to be parsed.
void value(const boost::any &v)
Property: the parsed value.
const std::string & string() const
String representation.
boost::int64_t asInt64() const
Convenience cast.
float asFloat() const
Convenience cast.
ParsedValue()
Construct a new empty value.
ParsedValue & switchKey(const std::string &s)
Property: switch key.
int asInt() const
Convenience cast.
const boost::any & value() const
Property: the parsed value.
unsigned asUnsigned() const
Convenience cast.
const ValueSaver::Ptr valueSaver() const
How to save a value at a user-supplied location.
boost::uint64_t asUnsigned64() const
Convenience cast.
bool asBool() const
Convenience cast.
T as() const
Convenient any_cast.
Location switchLocation() const
The command-line location of the switch to which this value belongs.
long asLong() const
Convenience cast.
size_t switchSequence() const
How this value relates to others created by the same switch.
void print(std::ostream &) const
Print some debugging information.
std::string asString() const
Convenience cast.
double asDouble() const
Convenience cast.
ParsedValue & valueLocation(const Location &loc)
Property: command-line location from whence this value came.
const std::string & switchKey() const
Property: switch key.
ParsedValue(const boost::any value, const Location &loc, const std::string &str, const ValueSaver::Ptr &saver)
Construct a new value.
Location valueLocation() const
Property: command-line location from whence this value came.
void save() const
Save this value in switch-supplied storage.
size_t keySequence() const
How this value relates to others with the same key.
unsigned long asUnsignedLong() const
Convenience cast.
ParsedValue & switchInfo(const std::string &key, const Location &loc, const std::string &str)
Update switch information.
The result from parsing a command line.
ParsedValues parsed(const std::string &switchKey) const
Returns values for a key.
const ParserResult & apply() const
Saves parsed values in switch-specified locations.
std::vector< std::string > unparsedArgs(bool includeTerminators=false) const
Returns unparsed switches.
const std::vector< std::string > & allArgs() const
The original command line.
std::vector< std::string > parsedArgs() const
Returns the program arguments that were processed.
std::vector< std::string > skippedArgs() const
Program arguments that were skipped over during parsing.
const ParsedValue & parsed(const std::string &switchKey, size_t idx) const
Returns values for a key.
size_t have(const std::string &switchKey) const
Returns the number of values for the specified key.
const Parser & parser() const
That parser that created this result.
std::vector< std::string > unreachedArgs() const
Returns program arguments that were not reached during parsing.
The parser for a program command line.
NamedSwitches findAmbiguities() const
Find switch string ambiguities.
std::vector< SwitchGroup > & switchGroups()
List of all switch groups.
Parser & with(const SwitchGroup &sg)
Add switch declarations.
Parser & resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE, const std::string &s3=STR_NONE, const std::string &s4=STR_NONE)
Prefixes to use for short command-line switches.
bool skippingNonSwitches() const
Whether to skip over non-switch arguments when parsing.
Parser & resetInclusionPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE, const std::string &s3=STR_NONE, const std::string &s4=STR_NONE)
Strings that indicate that arguments are to be read from a file.
const std::vector< std::string > & valueSeparators() const
Strings that separate a long switch from its value.
SwitchGroup & switchGroup(const std::string &name)
Switch group having specified name.
Parser & with(const SwitchGroup &sg, const std::string &docKey)
Add switch declarations.
Sawyer::Optional< Switch > removeMatchingSwitch(const std::vector< std::string > &args)
Remove the switch by matching parse sentence.
static void printIndex(std::ostream &, const NamedSwitches &, const std::string &linePrefix="")
Print a switch index.
Parser & with(const Switch &sw)
Add switch declarations.
const std::string & environmentVariable() const
Name of environment variable holding initial arguments.
Parser & longPrefix(const std::string &s1)
Prefixes to use for long command-line switches.
Parser & switchGroupOrder(SortOrder order)
Property: How to order switch groups in documentation.
Parser & shortMayNestle(bool b)
Indicates whether short switches can nestle together.
GroupingFlags
Bit flags for argument grouping.
void insertShortSwitchStrings(NamedSwitches &index) const
Insert records for short switch strings.
Sawyer::Optional< Switch > removeMatchingSwitch(const std::string &arg)
Remove the switch by matching parse sentence.
Parser & purpose(const std::string &purpose)
Program purpose.
Parser & doc(const std::string &sectionName, const std::string &docKey, const std::string &text)
Documentation for a section of the manual.
Parser & inclusionPrefix(const std::string &s1)
Strings that indicate that arguments are to be read from a file.
const std::vector< std::string > & shortPrefixes() const
Prefixes to use for short command-line switches.
const std::vector< std::string > & terminationSwitches() const
Strings that indicate the end of the argument list.
Parser & version(const std::pair< std::string, std::string > &p)
Program version.
Parser & shortPrefix(const std::string &s1)
Prefixes to use for short command-line switches.
void insertSwitchStrings(Canonical, NamedSwitches &index) const
Insert records for long and short switch strings.
std::vector< std::string > docSections() const
Documentation for a section of the manual.
std::vector< std::vector< std::string > > regroupArgs(const std::vector< std::string > &args, const Container::Interval< size_t > &limits=Container::Interval< size_t >::whole(), unsigned flags=0)
Group arguments by "--" separators.
Parser()
Default constructor.
ParserResult parse(const std::vector< std::string > &)
Parse program arguments.
std::string textDocumentation() const
Generate plain text documentation.
Parser & reportingAmbiguities(bool b)
Property: Whether to report ambiguities.
Parser & resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE, const std::string &s3=STR_NONE, const std::string &s4=STR_NONE)
Strings that separate a long switch from its value.
bool skippingUnknownSwitches() const
Whether to skip over unrecognized switches.
Parser & skippingNonSwitches(bool b)
Whether to skip over non-switch arguments when parsing.
static std::vector< std::string > readArgsFromEnvVar(const std::string &varName)
Read an envrionment variable to obtain arguments.
Parser & skippingUnknownSwitches(bool b)
Whether to skip over unrecognized switches.
std::string exitMessage() const
Extra text to print before exit.
std::string documentationMarkup() const
Full documentation.
Parser & valueSeparator(const std::string &s1)
Strings that separate a long switch from its value.
static std::vector< std::string > splitLineIntoWords(std::string)
Split line of text into words.
std::string podDocumentation() const
Generate Perl POD documentation.
bool switchGroupExists(const std::string &name) const
Predicate to determine whether a switch group exists.
const std::vector< std::string > & inclusionPrefixes() const
Strings that indicate that arguments are to be read from a file.
NamedSwitches findUnresolvableAmbiguities() const
Find unresolvable switch string ambiguities.
Parser & doc(const std::pair< std::string, std::string > &)
Documentation for a section of the manual.
Parser & resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE, const std::string &s3=STR_NONE, const std::string &s4=STR_NONE)
Prefixes to use for long command-line switches.
Parser & showingGroupNames(ShowGroupName)
Property: How to show group names in switch documentation.
Parser & chapter(int chapterNumber, const std::string &chapterName="")
Manual chapter.
const std::vector< SwitchGroup > & switchGroups() const
List of all switch groups.
ShowGroupName showingGroupNames() const
Property: How to show group names in switch documentation.
const std::string & programName() const
Program name for documentation.
Parser & programName(const std::string &programName)
Program name for documentation.
static std::vector< std::string > readArgsFromFile(const std::string &filename)
Read a text file to obtain arguments.
bool eraseSwitchGroup(const std::string &name)
Remove switch group from parser.
const SwitchGroup & switchGroup(const std::string &name) const
Switch group having specified name.
std::pair< std::string, std::string > version() const
Program version.
std::string docForSection(const std::string &sectionName) const
Documentation for a section of the manual.
Parser & version(const std::string &versionString, const std::string &dateString="")
Program version.
ParserResult parse(int argc, char *argv[])
Parse program arguments.
std::string docForSwitches() const
Documentation for a section of the manual.
Parser & resetTerminationSwitches(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE, const std::string &s3=STR_NONE, const std::string &s4=STR_NONE)
Strings that indicate the end of the argument list.
SortOrder switchGroupOrder() const
Property: How to order switch groups in documentation.
Parser & errorStream(const Message::SProxy &stream)
Specifies a message stream to which errors are sent.
const Message::SProxy & errorStream() const
Specifies a message stream to which errors are sent.
Parser & environmentVariable(const std::string &s)
Name of environment variable holding initial arguments.
const std::string & groupNameSeparator() const
Property: String separating group name from switch name.
Parser & with(const std::vector< SwitchGroup > &sgs)
Add switch declarations.
std::pair< int, std::string > chapter() const
Manual chapter.
Parser & groupNameSeparator(const std::string &s)
Property: String separating group name from switch name.
const std::string & purpose() const
Program purpose.
Parser & with(Switch sw, const std::string &docKey)
Add switch declarations.
bool emitDocumentationToPager() const
Print documentation to standard output.
Parser & exitMessage(const std::string &s)
Extra text to print before exit.
const std::vector< std::string > & longPrefixes() const
Prefixes to use for long command-line switches.
Parser & terminationSwitch(const std::string &s1)
Strings that indicate the end of the argument list.
Parser & doc(const std::string &sectionName, const std::string &text)
Documentation for a section of the manual.
bool shortMayNestle() const
Indicates whether short switches can nestle together.
bool reportingAmbiguities() const
Property: Whether to report ambiguities.
void insertLongSwitchStrings(Canonical, NamedSwitches &index) const
Insert records for long switch strings.
Parser & chapter(const std::pair< int, std::string > &p)
Manual chapter.
std::vector< std::string > expandIncludedFiles(const std::vector< std::string > &args)
Expand file arguments.
Parses a positive integer and converts it to numeric type T.
static Ptr instance()
Allocating constructor.
PositiveIntegerParser()
Constructor for derived classes.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
SharedPointer< PositiveIntegerParser > Ptr
Reference counting pointer for this class.
PositiveIntegerParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
Parses a real number and converts it to numeric type T.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
static Ptr instance()
Allocating constructor.
RealNumberParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
RealNumberParser()
Constructor for derived classes.
SharedPointer< RealNumberParser > Ptr
Reference counting pointer for this class.
Functor to print the Unix man page and exit.
static Ptr instance(int exitStatus)
Allocating constructor.
ShowHelpAndExit(int exitStatus)
Constructor for derived classes.
SharedPointer< ShowHelpAndExit > Ptr
Reference counting pointer for this class.
Functor to print the Unix man page.
static Ptr instance()
Allocating constructor.
SharedPointer< ShowHelp > Ptr
Reference counting pointer for this class.
ShowHelp()
Constructor for derived classes.
Functor to print a version string and exit.
ShowVersionAndExit(const std::string &versionString, int exitStatus)
Constructor for derived classes.
SharedPointer< ShowVersionAndExit > Ptr
Reference counting pointer for this class.
static Ptr instance(const std::string &versionString, int exitStatus)
Allocating constructor.
Functor to print a version string.
ShowVersion(const std::string &versionString)
Constructor for derived classes.
SharedPointer< ShowVersion > Ptr
Reference counting pointer for this class.
static Ptr instance(const std::string &versionString)
Allocating constructor.
Parses any one of a set of strings.
static Ptr instance()
Allocating constructor.
StringSetParser(const ValueSaver::Ptr &)
Constructor for derived classes.
Ptr with(InputIterator begin, InputIterator end)
Adds string members.
static Ptr instance(const ValueSaver::Ptr &)
Allocating constructor.
SharedPointer< StringSetParser > Ptr
Reference counting pointer for this class.
StringSetParser()
Constructor for derived classes.
Ptr with(const std::vector< std::string >)
Adds string members.
Ptr with(const std::string &)
Adds string members.
Sums all previous and current values.
SharedPointer< Sum > Ptr
Reference counting pointer for this class.
virtual ParsedValues operator()(const ParsedValues &savedValues, const ParsedValues &newValues)
Called when a switch's value is about to be stored into the ParserResult.
static Ptr instance()
Allocating constructor.
Sum()
Constructor for derived classes.
Base class for switch actions.
SharedPointer< SwitchAction > Ptr
Reference counting pointer for this class.
void run(const ParserResult &parserResult)
Runs the action.
Describes one argument of a command-line switch.
SwitchArgument(const std::string &name, const ValueParser::Ptr &parser=anyParser())
Construct a new required argument.
SwitchArgument(const std::string &name, const ValueParser::Ptr &parser, const std::string &defaultValueString)
Construct a new switch optional argument.
bool isRequired() const
Returns true if this argument is required.
const std::string & name() const
Argument name.
std::string nameAsText() const
Returns the name without markup.
const ValueParser::Ptr & parser() const
Returns a pointer to the parser.
const ParsedValue & defaultValue() const
The parsed default value.
bool isOptional() const
Returns true if this argument is not required.
const std::string & defaultValueString() const
The default value string.
A collection of related switch declarations.
SwitchGroup & removeByKey(const std::string &switchKey)
Remove a switch from the group.
const std::vector< Switch > & switches() const
List of all declared switches.
void showingGroupNames(ShowGroupName x)
Property: How to show group name in switch synopsis.
SwitchGroup & longPrefix(const std::string &s1)
Property: prefixes for long names.
SwitchGroup & title(const std::string &title)
Property: Title of the switch group.
const SortOrder & switchOrder() const
Property: Order of switches in documentation.
const Switch & getByName(const std::string &switchName)
Returns the first switch with the specified name.
SwitchGroup & removeByName(const std::string &switchName)
Remove a switch from the group.
SwitchGroup & resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE, const std::string &s3=STR_NONE, const std::string &s4=STR_NONE)
Property: prefixes for long names.
SwitchGroup & doc(const std::string &s)
Property: Detailed description.
const Switch & getByKey(const std::string &switchKey)
Returns the first switch with the specified key.
const std::string & docKey() const
Property: Documentation sort key.
size_t nSwitches() const
Number of switches declared.
SwitchGroup(const std::string &title, const std::string &docKey="")
Construct a titled group.
SwitchGroup & removeByIndex(size_t n)
Remove a switch from the group.
const std::string & name() const
Property: Group name.
const std::vector< std::string > & longPrefixes() const
Property: prefixes for long names.
const std::vector< std::string > & valueSeparators() const
Property: strings that separate a long switch from its value.
bool nameExists(const std::string &switchName)
Returns true if a switch with the specified name exists.
SwitchGroup & docKey(const std::string &key)
Property: Documentation sort key.
const std::vector< std::string > & shortPrefixes() const
Property: prefixes for short names.
SwitchGroup & name(const std::string &name)
Property: Group name.
const std::string & title() const
Property: Title of the switch group.
SwitchGroup & insert(const SwitchGroup &)
Insert switches from another group into this one.
SwitchGroup & valueSeparator(const std::string &s1)
Property: strings that separate a long switch from its value.
SwitchGroup & shortPrefix(const std::string &s1)
Property: prefixes for short names.
SwitchGroup & resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE, const std::string &s3=STR_NONE, const std::string &s4=STR_NONE)
Property: strings that separate a long switch from its value.
ShowGroupName showingGroupNames() const
Property: How to show group name in switch synopsis.
bool keyExists(const std::string &switchKey)
Returns true if a switch with the specified key exists.
SwitchGroup & insert(const Switch &)
Insert a switch into the group.
SwitchGroup & switchOrder(SortOrder order)
Property: Order of switches in documentation.
SwitchGroup()
Construct an unnamed, untitled group.
SwitchGroup & resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE, const std::string &s3=STR_NONE, const std::string &s4=STR_NONE)
Property: prefixes for short names.
const std::string & doc() const
Property: Detailed description.
Describes one command-line switch.
const std::string & doc() const
Property: detailed description.
Switch & argument(const std::string &name, const ValueParser::Ptr &parser=anyParser())
Property: switch argument.
Switch & longPrefix(const std::string &s1)
Property: prefixes for long names.
Switch & intrinsicValue(const std::string &text)
Property: value for a switch that has no declared arguments.
const std::vector< SwitchArgument > & arguments() const
Property: switch argument.
Switch & whichValue(WhichValue s)
Property: how to handle multiple occurrences.
Switch & argument(const SwitchArgument &arg)
Property: switch argument.
size_t nRequiredArguments() const
Number of required arguments.
std::string preferredName() const
Name by which switch prefers to be known.
Switch & synopsis(const std::string &s)
Property: abstract summary of the switch syntax.
Switch & hidden(bool b)
Property: whether this switch appears in documentation.
ParsedValue intrinsicValue() const
Property: value for a switch that has no declared arguments.
std::string synopsis() const
Property: abstract summary of the switch syntax.
Switch & resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE, const std::string &s3=STR_NONE, const std::string &s4=STR_NONE)
Property: strings that separate a long switch from its value.
Switch & docKey(const std::string &s)
Property: key to control order of documentation.
Switch & resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE, const std::string &s3=STR_NONE, const std::string &s4=STR_NONE)
Property: prefixes for long names.
Switch & valueAugmenter(const ValueAugmenter::Ptr &f)
Property: functor to agument values.
size_t nArguments() const
Total number of arguments.
Switch & intrinsicValue(const char *value, std::string &storage)
Property: value for a switch that has no declared arguments.
const std::string & shortNames() const
Property: switch short name.
Switch(const std::string &longName, char shortName='\0')
Constructs a switch declaration.
Switch & valueSeparator(const std::string &s1)
Property: strings that separate a long switch from its value.
Switch & resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE, const std::string &s3=STR_NONE, const std::string &s4=STR_NONE)
Property: prefixes for short names.
const std::vector< std::string > & longNames() const
Property: switch long name.
SwitchSkipping skipping() const
Property: whether to skip over this switch.
Switch & explosiveLists(bool b)
Property: whether to convert a list value to individual values.
const std::vector< std::string > & longPrefixes() const
Property: prefixes for long names.
bool hidden() const
Property: whether this switch appears in documentation.
Switch & intrinsicValue(const ParsedValue &value)
Property: value for a switch that has no declared arguments.
const SwitchArgument & argument(size_t idx) const
Property: switch argument.
const std::string & longName() const
Property: switch long name.
const std::vector< std::string > & valueSeparators() const
Property: strings that separate a long switch from its value.
Switch & shortName(char c)
Property: switch short name.
ValueAugmenter::Ptr valueAugmenter() const
Property: functor to agument values.
const std::string & docKey() const
Property: key to control order of documentation.
Switch & intrinsicValue(const std::string &text, const ValueParser::Ptr &p)
Property: value for a switch that has no declared arguments.
Switch & doc(const std::string &s)
Property: detailed description.
Switch & intrinsicValue(const T &value, T &storage)
Property: value for a switch that has no declared arguments.
WhichValue whichValue() const
Property: how to handle multiple occurrences.
const std::string & key() const
Property: value storage key.
const SwitchAction::Ptr & action() const
Property: action to occur.
Switch & skipping(SwitchSkipping how)
Property: whether to skip over this switch.
Switch & longName(const std::string &name)
Property: switch long name.
bool explosiveLists() const
Property: whether to convert a list value to individual values.
Switch & action(const SwitchAction::Ptr &f)
Property: action to occur.
const std::vector< std::string > & shortPrefixes() const
Property: prefixes for short names.
Switch & shortPrefix(const std::string &s1)
Property: prefixes for short names.
Switch & argument(const std::string &name, const ValueParser::Ptr &parser, const std::string &defaultValue)
Property: switch argument.
Switch & key(const std::string &s)
Property: value storage key.
Wrapper around a user functor.
SharedPointer< class UserAction > Ptr
Reference counting pointer for this class.
UserAction(Functor &f)
Constructor for derived classes.
static Ptr instance(Functor &f)
Allocating constructor.
Base class for value agumentors.
virtual ParsedValues operator()(const ParsedValues &savedValues, const ParsedValues &newValues)=0
Called when a switch's value is about to be stored into the ParserResult.
SharedPointer< ValueAugmenter > Ptr
Reference counting pointer for this class.
Base class parsing a value from input.
ParsedValue matchString(const std::string &)
Parse the entire string and return a value.
const ValueSaver::Ptr valueSaver() const
Property: functor responsible for saving a parsed value in user storage.
SharedPointer< ValueParser > Ptr
Reference counting pointer for this class.
ValueParser()
Constructor for derived classes.
ParsedValue match(Cursor &)
Parse a value from the beginning of the specified string.
ValueParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
Ptr valueSaver(const ValueSaver::Ptr &f)
Property: functor responsible for saving a parsed value in user storage.
A container holding a set of values.
Definition IntervalSet.h:53
Range of values delimited by endpoints.
Definition Interval.h:31
Container associating values with keys.
Definition Sawyer/Map.h:72
Map & insert(const Key &key, const Value &value)
Insert or update a key/value pair.
Definition Sawyer/Map.h:646
Ordered set of values.
Definition Set.h:56
Collection of facilities.
Definition Message.h:1736
Holds a value or nothing.
Definition Optional.h:54
Creates SharedPointer from this.
SharedPointer< ValueParser > sharedFromThis()
Create a shared pointer from this.
Base class for reference counted objects.
Reference-counting intrusive smart pointer.
SharedPointer< U > dynamicCast() const
Dynamic cast.
UserAction< Functor >::Ptr userAction(const Functor &functor)
Factory for switch action.
ShowHelpAndExit::Ptr showHelpAndExit(int exitStatus)
Factory for switch action.
ShowHelp::Ptr showHelp()
Factory for switch action.
ShowVersionAndExit::Ptr showVersionAndExit(const std::string &versionString, int exitStatus)
Factory for switch action.
ConfigureDiagnostics::Ptr configureDiagnostics(const std::string &, Message::Facilities &, bool exitOnHelp=true)
Factory for switch action.
ConfigureDiagnosticsQuiet::Ptr configureDiagnosticsQuiet(Message::Facilities &)
Factory for switch action.
ShowVersion::Ptr showVersion(const std::string &versionString)
Factory for switch action.
Sum< T >::Ptr sum()
Factory for value agumenter.
PositiveIntegerParser< T >::Ptr positiveIntegerParser()
Factory for value parsers.
RealNumberParser< T >::Ptr realNumberParser()
Factory for value parsers.
NonNegativeIntegerParser< T >::Ptr nonNegativeIntegerParser()
Factory for value parsers.
StringSetParser::Ptr stringSetParser()
Factory for value parsers.
ListParser::Ptr listParser(const ValueParser::Ptr &, const std::string &sepRe="[,;:]\\s*")
Factory for value parsers.
AnyParser< T >::Ptr anyParser(T &storage)
Factory for value parsers.
IntegerParser< T >::Ptr integerParser()
Factory for value parsers.
BooleanParser< T >::Ptr booleanParser()
Factory for value parsers.
EnumParser< T >::Ptr enumParser()
Factory for value parsers.
AnyParser< T >::Ptr anyParser()
Factory for value parsers.
Canonical
Format of a switch string.
@ CANONICAL
Switch strings that are qualified with the switch group name or which belong to a group that has no n...
@ ALL_STRINGS
The union of CANONICAL and NONCANONICAL.
@ NONCANONICAL
Switch strings that are not CANONICAL.
std::vector< ParsedValue > ParsedValues
A vector of parsed values.
SortOrder
The order in which things are sorted in the documentation.
@ DOCKEY_ORDER
Entities are sorted according to their documentation keys.
@ INSERTION_ORDER
Entities appear in the documentation in the same order they are inserted into the container.
const Location NOWHERE
Indicates an invalid location.
ShowGroupName
How to show group names in switch synopsis.
@ SHOW_GROUP_OPTIONAL
Show name as being optional, like "--[group-]switch".
@ SHOW_GROUP_INHERIT
Group inherits value from the parser.
@ SHOW_GROUP_NONE
Never show the group name.
@ SHOW_GROUP_REQUIRED
Show name as being required, like "--group-switch".
Container::Map< const SwitchGroup *, std::set< const Switch * > > GroupedSwitches
Subset of switches grouped by their switch groups.
SwitchSkipping
Whether to skip a switch.
@ SKIP_STRONG
Skip switch and its argument(s) without saving any value.
@ SKIP_NEVER
Treat the switch normally.
@ SKIP_WEAK
Process switch normally, but also add to skipped list.
std::ostream & operator<<(std::ostream &, const Location &)
Print a location.
Container::Map< std::string, GroupedSwitches > NamedSwitches
Subset of switches indexed by their command-line representation.
WhichValue
Describes how to handle switches that occur multiple times.
@ SAVE_AUGMENTED
Save the first value, or modify previously saved value.
@ SAVE_ONE
The switch cannot occur more than once.
@ SAVE_LAST
Use only the last occurrence and ignore all previous.
@ SAVE_ALL
Save all values as a vector.
@ SAVE_NONE
The switch is disabled.
@ SAVE_FIRST
Use only the first occurrence and ignore all previous.
Sawyer support library.
boost::int64_t strtoll(const char *, char **, int)
Portable replacement for strtoll.
boost::uint64_t strtoull(const char *, char **, int)
Portable replacement for strtoull.
This namespace contains template functions that operate on the ROSE AST.
Definition sageGeneric.h:38
Position within a command-line.
bool operator!=(const Location &other) const
Inequality.
Location()
Constructs the location of the first character of the first string.
bool operator<=(const Location &other) const
Less than or equal.
size_t offset
Character offset within a program argument string.
bool operator<(const Location &other) const
Less than.
Location(size_t idx, size_t offset)
Constructs a location that points to a particular character of a particular string.
size_t idx
Index into some vector of program argument strings.
bool operator==(const Location &other) const
Equality.