ROSE 0.11.145.134
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;
222 Location(): idx(0), offset(0) {}
223
225 Location(size_t idx, size_t offset): idx(idx), offset(offset) {}
226
229 bool operator==(const Location &other) const { return idx==other.idx && offset==other.offset; }
230
233 bool operator!=(const Location &other) const { return !(*this==other); }
234
237 bool operator<(const Location &other) const { return idx<other.idx || (idx==other.idx && offset<other.offset); }
238
241 bool operator<=(const Location &other) const { return *this<other || *this==other; }
242};
243
245SAWYER_EXPORT std::ostream& operator<<(std::ostream&, const Location&);
246
250SAWYER_EXPORT extern const Location NOWHERE;
251
255class SAWYER_EXPORT Cursor {
256#include <Sawyer/WarningsOff.h>
257 std::vector<std::string> strings_;
258 Location loc_;
259#include <Sawyer/WarningsRestore.h>
260public:
263 Cursor(const std::vector<std::string> &strings): strings_(strings) { location(Location()); }
264
267 Cursor(const std::string &string): strings_(1, string) { location(Location()); }
268
271
273 const std::vector<std::string>& strings() const { return strings_; }
274
292 const Location& location() const { return loc_; }
298 bool atArgBegin() const { return loc_.idx<strings_.size() && 0==loc_.offset; }
299
302 bool atArgEnd() const { return loc_.idx<strings_.size() && loc_.offset>=strings_[loc_.idx].size(); }
303
308 bool atEnd() const { return atEnd(loc_); }
309 bool atEnd(const Location &location) const { return location.idx >= strings_.size(); }
316 const std::string& arg() const { return arg(loc_); }
317 const std::string& arg(const Location &location) const;
324 std::string rest() const { return rest(loc_); }
325 std::string rest(const Location &location) const;
333 std::string substr(const Location &limit, const std::string &separator=" ") const { return substr(loc_, limit, separator); }
334 std::string substr(const Location &limit1, const Location &limit2, const std::string &separator=" ") const;
339 void replace(const std::vector<std::string>&);
340
344 void consumeChars(size_t nchars);
345
350 void consumeArgs(size_t nargs) {
351 loc_.idx = std::min(strings_.size(), loc_.idx+nargs);
352 loc_.offset = 0;
353 }
354 void consumeArg() { consumeArgs(1); }
362 size_t linearDistance() const;
363};
364
368 Cursor &cursor_;
369 Location loc_;
370 bool canceled_;
371public:
374 ExcursionGuard(Cursor &cursor): cursor_(cursor), loc_(cursor.location()), canceled_(false) {} // implicit
375 ~ExcursionGuard() { if (!canceled_) cursor_.location(loc_); }
376
379 void cancel() { canceled_ = true; }
380
383 const Location &startingLocation() const { return loc_; }
384};
385
386
388// Switch value savers
390
391// used internally
392class SAWYER_EXPORT ValueSaver: public SharedObject {
393protected:
394 ValueSaver() {}
395public:
397 virtual ~ValueSaver() {}
398 virtual void save(const boost::any&, const std::string &switchKey) = 0;
399};
400
401// used internally
402template<typename T>
403class TypedSaver: public ValueSaver {
404 T &storage_;
405protected:
406 TypedSaver(T &storage): storage_(storage) {}
407public:
409 static Ptr instance(T &storage) { return Ptr(new TypedSaver(storage)); }
410 virtual void save(const boost::any &value, const std::string &/*switchKey*/) /*override*/ {
411 storage_ = boost::any_cast<T>(value);
412 }
413};
414
415// Partial specialization of TypedSaver, saving a value of any type T into a container of type CONTAINER_TEMPLATE calling the
416// containers INSERT_METHOD with one argument: the value. The CONTAINER_TEMPLATE is the name of a class template that
417// takes one argument: type type of value stored by the container.
418#define SAWYER_COMMANDLINE_SEQUENCE_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
419 template<typename T> \
420 class TypedSaver<CONTAINER_TEMPLATE<T> >: public ValueSaver { \
421 CONTAINER_TEMPLATE<T> &storage_; \
422 protected: \
423 TypedSaver(CONTAINER_TEMPLATE<T> &storage): storage_(storage) {} \
424 public: \
425 static Ptr instance(CONTAINER_TEMPLATE<T> &storage) { return Ptr(new TypedSaver(storage)); } \
426 virtual void save(const boost::any &value, const std::string &/*switchKey*/) /*override*/ { \
427 T typed = boost::any_cast<T>(value); \
428 storage_.INSERT_METHOD(typed); \
429 } \
430 }
431
432// Partial specialization of TypedSaver for saving values into map-like containers. The CONTAINER_TEMPLATE should take two
433// parameters: the key type (always std::string) and the value type (not part of this specialization). The value is stored by
434// invoking the INSERT_METHOD with two arguments: the key string for the switch whose value is being saved, and the value to
435// save.
436#define SAWYER_COMMANDLINE_MAP_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
437 template<typename T> \
438 class TypedSaver<CONTAINER_TEMPLATE<std::string, T> >: public ValueSaver { \
439 CONTAINER_TEMPLATE<std::string, T> &storage_; \
440 protected: \
441 TypedSaver(CONTAINER_TEMPLATE<std::string, T> &storage): storage_(storage) {} \
442 public: \
443 static Ptr instance(CONTAINER_TEMPLATE<std::string, T> &storage) { return Ptr(new TypedSaver(storage)); } \
444 virtual void save(const boost::any &value, const std::string &switchKey) /*override*/ { \
445 T typed = boost::any_cast<T>(value); \
446 storage_.INSERT_METHOD(switchKey, typed); \
447 } \
448 }
449
450// Partial specialization of TypedSaver for saving values into set-like containers. The CONTAINER_TEMPLATE should take one
451// parameter: the value type (not part of this specialization). The value is stored by invoking the INSERT_METHOD with one
452// argument: the value to save. The value is always an interval.
453#define SAWYER_COMMANDLINE_INTERVALSET_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
454 template<typename Interval> \
455 class TypedSaver<CONTAINER_TEMPLATE<Interval> >: public ValueSaver { \
456 CONTAINER_TEMPLATE<Interval> &storage_; \
457 protected: \
458 TypedSaver(CONTAINER_TEMPLATE<Interval> &storage): storage_(storage) {} \
459 public: \
460 static Ptr instance(CONTAINER_TEMPLATE<Interval> &storage) { return Ptr(new TypedSaver(storage)); } \
461 virtual void save(const boost::any &value, const std::string &/*switchKey*/) /*override*/ { \
462 Interval typed = boost::any_cast<Interval>(value); \
463 storage_.INSERT_METHOD(typed); \
464 } \
465 }
466
467// Partial specialization of TypedSaver for saving values into map-like containers using the STL approach where the insert
468// operator takes an std::pair(key,value) rather than two arguments. The CONTAINER_TEMPLATE should take two parameters: the key
469// type (always std::string) and the value type (not part of this specialization). The value is stored by invoking the
470// INSERT_METHOD with two arguments: the key string for the switch whose value is being saved, and the value to save.
471#define SAWYER_COMMANDLINE_MAP_PAIR_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
472 template<typename T> \
473 class TypedSaver<CONTAINER_TEMPLATE<std::string, T> >: public ValueSaver { \
474 CONTAINER_TEMPLATE<std::string, T> &storage_; \
475 protected: \
476 TypedSaver(CONTAINER_TEMPLATE<std::string, T> &storage): storage_(storage) {} \
477 public: \
478 static Ptr instance(CONTAINER_TEMPLATE<std::string, T> &storage) { return Ptr(new TypedSaver(storage)); } \
479 virtual void save(const boost::any &value, const std::string &switchKey) /*override*/ { \
480 T typed = boost::any_cast<T>(value); \
481 storage_.INSERT_METHOD(std::make_pair(switchKey, typed)); \
482 } \
483 }
484
485SAWYER_COMMANDLINE_SEQUENCE_SAVER(std::vector, push_back);
486SAWYER_COMMANDLINE_SEQUENCE_SAVER(std::list, push_back);
487SAWYER_COMMANDLINE_SEQUENCE_SAVER(std::set, insert);
488SAWYER_COMMANDLINE_SEQUENCE_SAVER(Sawyer::Container::Set, insert);
489SAWYER_COMMANDLINE_SEQUENCE_SAVER(Optional, operator=);
490SAWYER_COMMANDLINE_SEQUENCE_SAVER(BitFlags, set);
491SAWYER_COMMANDLINE_MAP_PAIR_SAVER(std::map, insert);
492SAWYER_COMMANDLINE_MAP_SAVER(Sawyer::Container::Map, insert);
493SAWYER_COMMANDLINE_INTERVALSET_SAVER(Sawyer::Container::IntervalSet, insert);
494
496// Parsed value
498
505class SAWYER_EXPORT ParsedValue {
506#include <Sawyer/WarningsOff.h>
507 boost::any value_;
508 Location valueLocation_;
509 std::string valueString_;
510 std::string switchKey_;
511 Location switchLocation_;
512 std::string switchString_;
513 size_t keySequence_;
514 size_t switchSequence_;
515 ValueSaver::Ptr valueSaver_;
516#include <Sawyer/WarningsRestore.h>
517
518public:
520 ParsedValue(): keySequence_(0), switchSequence_(0) {}
521
531 ParsedValue(const boost::any value, const Location &loc, const std::string &str, const ValueSaver::Ptr &saver)
532 : value_(value), valueLocation_(loc), valueString_(str), keySequence_(0), switchSequence_(0), valueSaver_(saver) {}
533
536 ParsedValue& switchInfo(const std::string &key, const Location &loc, const std::string &str) {
537 switchKey_ = key;
538 switchLocation_ = loc;
539 switchString_ = str;
540 return *this;
541 }
542
543private:
544 friend class ParserResult;
545 void sequenceInfo(size_t keySequence, size_t switchSequence) {
546 keySequence_ = keySequence;
547 switchSequence_ = switchSequence;
548 }
549
550public:
556 const boost::any& value() const { return value_; }
557 void value(const boost::any &v) { value_ = v; }
563 Location valueLocation() const { return valueLocation_; }
564 ParsedValue& valueLocation(const Location &loc) { valueLocation_ = loc; return *this; }
568 const std::string &string() const { return valueString_; }
569
575 int asInt() const;
576 unsigned asUnsigned() const;
577 long asLong() const;
578 unsigned long asUnsignedLong() const;
579 boost::int64_t asInt64() const;
580 boost::uint64_t asUnsigned64() const;
581 double asDouble() const;
582 float asFloat() const;
583 bool asBool() const;
584 std::string asString() const;
589 template<typename T> T as() const { return boost::any_cast<T>(value_); }
590
593 ParsedValue& switchKey(const std::string &s) { switchKey_ = s; return *this; }
594 const std::string& switchKey() const { return switchKey_; }
604 const std::string& switchString() const { return switchString_; }
605
609 Location switchLocation() const { return switchLocation_; }
610
613 size_t keySequence() const { return keySequence_; }
614
617 size_t switchSequence() const { return switchSequence_; }
618
621 const ValueSaver::Ptr valueSaver() const { return valueSaver_; }
622
625 void save() const;
626
628 bool isEmpty() const { return value_.empty(); }
629
631 void print(std::ostream&) const;
632};
633
635SAWYER_EXPORT std::ostream& operator<<(std::ostream&, const ParsedValue&);
636
638typedef std::vector<ParsedValue> ParsedValues;
639
640
641
642
644// Switch argument parsers
646
699class SAWYER_EXPORT ValueParser: public SharedObject, public SharedFromThis<ValueParser> {
700#include <Sawyer/WarningsOff.h>
701 ValueSaver::Ptr valueSaver_;
702#include <Sawyer/WarningsRestore.h>
703protected:
706
708 explicit ValueParser(const ValueSaver::Ptr &valueSaver): valueSaver_(valueSaver) {}
709public:
712
713 virtual ~ValueParser() {}
714
718 ParsedValue matchString(const std::string&) /*final*/;
719
725
740 Ptr valueSaver(const ValueSaver::Ptr &f) { valueSaver_ = f; return sharedFromThis(); }
741 const ValueSaver::Ptr valueSaver() const { return valueSaver_; }
744private:
747 virtual ParsedValue operator()(Cursor&);
748 virtual ParsedValue operator()(const char *input, const char **endptr, const Location&);
750};
751
752// used internally to convert from one type to another via boost::lexical_cast or throw a runtime_error with a decent message.
753template<typename T>
755 static T convert(const std::string &src) {
756 try {
757 return boost::lexical_cast<T>(src);
758 } catch (const boost::bad_lexical_cast &e) {
759 throw std::runtime_error(e.what());
760 }
761 }
762};
763
764template<>
765struct LexicalCast<boost::regex> {
766 static boost::regex convert(const std::string &src) {
767 return boost::regex(src);
768 }
769};
770
771template<>
772struct LexicalCast<std::regex> {
773 static std::regex convert(const std::string &src) {
774 return std::regex(src);
775 }
776};
777
778template<>
779struct LexicalCast<boost::filesystem::path> {
780 static boost::filesystem::path convert(const std::string &src) {
781 return boost::filesystem::path(src);
782 }
783};
784
785template<>
786struct LexicalCast<boost::any> {
787 static boost::any convert(const std::string &src) {
788 return src;
789 }
790};
791
792template<typename T>
794 static T convert(const std::string &src) {
795 return LexicalCast<T>::convert(src);
796 }
797};
798
799template<typename T>
801 static T convert(const std::string &src) {
802 return LexicalCast<T>::convert(src);
803 }
804};
805
806template<typename T>
807struct LexicalCast<Sawyer::Container::Map<std::string, T> > {
808 static T convert(const std::string &src) {
809 return LexicalCast<T>::convert(src);
810 }
811};
812
813template<typename T>
814struct LexicalCast<std::vector<T> > {
815 static T convert(const std::string &src) {
816 return LexicalCast<T>::convert(src);
817 }
818};
819
820template<typename T>
821struct LexicalCast<std::set<T> > {
822 static T convert(const std::string &src) {
823 return LexicalCast<T>::convert(src);
824 }
825};
826
827template<typename T>
828struct LexicalCast<std::list<T> > {
829 static T convert(const std::string &src) {
830 return LexicalCast<T>::convert(src);
831 }
832};
833
834template<typename T>
835struct LexicalCast<std::map<std::string, T> > {
836 static T convert(const std::string &src) {
837 return LexicalCast<T>::convert(src);
838 }
839};
840
864template<typename T>
865class AnyParser: public ValueParser {
866protected:
869
872public:
875
879 static Ptr instance() { return Ptr(new AnyParser); }
880
885private:
886 virtual ParsedValue operator()(Cursor &cursor) /*override*/ {
887 if (cursor.atEnd())
888 throw std::runtime_error("string expected");
889 Location startLoc = cursor.location();
890 std::string s = cursor.rest();
891 cursor.consumeChars(s.size());
892 return ParsedValue(LexicalCast<T>::convert(s), startLoc, s, valueSaver());
893 }
894};
895
896// used internally to cast one numeric type to another and throw a range_error with a decent message.
897template<typename Target, typename Source>
899 static Target convert(Source from, const std::string &parsed) {
900 try {
901 return boost::numeric_cast<Target>(from);
902 } catch (const boost::numeric::positive_overflow&) {
903 std::string bound = boost::lexical_cast<std::string>(boost::numeric::bounds<Target>::highest());
904 throw std::range_error("parsed string \""+parsed+"\" is greater than "+bound);
905 } catch (const boost::numeric::negative_overflow&) {
906 std::string bound = boost::lexical_cast<std::string>(boost::numeric::bounds<Target>::lowest());
907 throw std::range_error("parsed string \""+parsed+"\" is less than "+bound);
908 } catch (const boost::numeric::bad_numeric_cast&) {
909 throw std::range_error("cannot cast \""+parsed+"\" to destination type");
910 }
911 }
912};
913
914// partial specialization for Sawyer::Optional<Target>
915template<typename Target, typename Source>
916struct NumericCast<Optional<Target>, Source> {
917 static Target convert(Source from, const std::string &parsed) {
918 return NumericCast<Target, Source>::convert(from, parsed);
919 }
920};
921
922// partial specialization for std::vector<Target>
923template<typename Target, typename Source>
924struct NumericCast<std::vector<Target>, Source> {
925 static Target convert(Source from, const std::string &parsed) {
926 return NumericCast<Target, Source>::convert(from, parsed);
927 }
928};
929
930// partial specialization for std::list<Target>
931template<typename Target, typename Source>
932struct NumericCast<std::list<Target>, Source> {
933 static Target convert(Source from, const std::string &parsed) {
934 return NumericCast<Target, Source>::convert(from, parsed);
935 }
936};
937
938// partial specialization for std::set<Target>
939template<typename Target, typename Source>
940struct NumericCast<std::set<Target>, Source> {
941 static Target convert(Source from, const std::string &parsed) {
942 return NumericCast<Target, Source>::convert(from, parsed);
943 }
944};
945
946// partial specialization for Sawyer::Container::Set<Target>
947template<typename Target, typename Source>
948struct NumericCast<Sawyer::Container::Set<Target>, Source> {
949 static Target convert(Source from, const std::string &parsed) {
950 return NumericCast<Target, Source>::convert(from, parsed);
951 }
952};
953
954// partial specialization for std::map<std::string, Target>
955template<typename Target, typename Source>
956struct NumericCast<std::map<std::string, Target>, Source> {
957 static Target convert(Source from, const std::string &parsed) {
958 return NumericCast<Target, Source>::convert(from, parsed);
959 }
960};
961
962// partial specialization for Sawyer::Container::Map<std::string, Target>
963template<typename Target, typename Source>
964struct NumericCast<Sawyer::Container::Map<std::string, Target>, Source> {
965 static Target convert(Source from, const std::string &parsed) {
966 return NumericCast<Target, Source>::convert(from, parsed);
967 }
968};
969
979template<typename T>
981protected:
984
987public:
990
997 static Ptr instance() { return Ptr(new IntegerParser); }
998
1006private:
1007 virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1008 errno = 0;
1009 boost::int64_t big = strtoll(input, (char**)rest, 0);
1010 if (*rest==input)
1011 throw std::runtime_error("integer expected");
1012 while (isspace(**rest)) ++*rest;
1013 std::string parsed(input, *rest-input);
1014 if (ERANGE==errno)
1015 throw std::range_error("integer overflow when parsing \""+parsed+"\"");
1016 return ParsedValue(NumericCast<T, boost::int64_t>::convert(big, parsed), loc, parsed, valueSaver());
1017 }
1018};
1019
1030template<typename T>
1032protected:
1035
1038public:
1041
1045 static Ptr instance() { return Ptr(new NonNegativeIntegerParser); }
1046
1051private:
1052 virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1053 errno = 0;
1054 while (isspace(*input)) ++input;
1055 if ('+'!=*input && !isdigit(*input))
1056 throw std::runtime_error("unsigned integer expected");
1057 boost::uint64_t big = strtoull(input, (char**)rest, 0);
1058 if (*rest==input)
1059 throw std::runtime_error("unsigned integer expected");
1060 while (isspace(**rest)) ++*rest;
1061 std::string parsed(input, *rest-input);
1062 if (ERANGE==errno)
1063 throw std::range_error("integer overflow when parsing \""+parsed+"\"");
1064 return ParsedValue(NumericCast<T, boost::uint64_t>::convert(big, parsed), loc, parsed, valueSaver());
1065 }
1066};
1067
1078template<typename T>
1080protected:
1083
1086public:
1089
1093 static Ptr instance() { return Ptr(new PositiveIntegerParser); }
1094
1099private:
1100 virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1101 errno = 0;
1102 while (isspace(*input)) ++input;
1103 if ('+'!=*input && !isdigit(*input))
1104 throw std::runtime_error("positive integer expected");
1105 boost::uint64_t big = strtoull(input, (char**)rest, 0);
1106 if (*rest==input || big==0)
1107 throw std::runtime_error("positive integer expected");
1108 while (isspace(**rest)) ++*rest;
1109 std::string parsed(input, *rest-input);
1110 if (ERANGE==errno)
1111 throw std::range_error("integer overflow when parsing \""+parsed+"\"");
1112 return ParsedValue(NumericCast<T, boost::uint64_t>::convert(big, parsed), loc, parsed, valueSaver());
1113 }
1114};
1115
1125template<typename T>
1127protected:
1130
1133public:
1136
1140 static Ptr instance() { return Ptr(new RealNumberParser); }
1141
1146private:
1147 virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1148 double big = strtod(input, (char**)rest);
1149 if (*rest==input)
1150 throw std::runtime_error("real number expected");
1151 while (isspace(**rest)) ++*rest;
1152 std::string parsed(input, *rest-input);
1153 return ParsedValue(NumericCast<T, double>::convert(big, parsed), loc, parsed, valueSaver());
1154 }
1155};
1156
1163template<typename T>
1165protected:
1168
1171public:
1174
1178 static Ptr instance() { return Ptr(new BooleanParser); }
1179
1184private:
1185 virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1186 static const char *neg[] = {"false", "off", "no", "0", "f", "n"}; // longest to shortest
1187 static const char *pos[] = {"true", "yes", "on", "1", "t", "y"};
1188 const char *start = input;
1189 while (isspace(*input)) ++input;
1190 for (int negpos=0; negpos<2; ++negpos) {
1191 const char **list = 0==negpos ? neg : pos;
1192 size_t listsz = 0==negpos ? sizeof(neg)/sizeof(*neg) : sizeof(pos)/sizeof(*pos);
1193 for (size_t i=0; i<listsz; ++i) {
1194 if (0==my_strncasecmp(list[i], input, strlen(list[i]))) {
1195 *rest = input + strlen(list[i]);
1196 while (isspace(**rest)) ++*rest;
1197 std::string parsed(start, *rest-start);
1198 return ParsedValue(NumericCast<T, bool>::convert(0!=negpos, parsed), loc, parsed, valueSaver());
1199 }
1200 }
1201 }
1202 throw std::runtime_error("Boolean expected");
1203 }
1204
1205 // Microsoft doesn't have the POSIX.1-2001 strncasecmp function
1206 int my_strncasecmp(const char *a, const char *b, size_t nchars) {
1207 ASSERT_not_null(a);
1208 ASSERT_not_null(b);
1209 for (size_t i=0; i<nchars; ++i) {
1210 if (!a[i] || !b[i])
1211 return a[i] ? 1 : (b[i] ? -1 : 0);
1212 char achar = (char)tolower(a[i]);
1213 char bchar = (char)tolower(b[i]);
1214 if (achar != bchar)
1215 return achar < bchar ? -1 : 1;
1216 }
1217 return 0;
1218 }
1219};
1220
1229class SAWYER_EXPORT StringSetParser: public ValueParser {
1230#include <Sawyer/WarningsOff.h>
1231 std::vector<std::string> strings_;
1232#include <Sawyer/WarningsRestore.h>
1233protected:
1236
1238 StringSetParser(const ValueSaver::Ptr &valueSaver): ValueParser(valueSaver) {}
1239public:
1242
1246 static Ptr instance() { return Ptr(new StringSetParser); }
1247
1251 static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new StringSetParser(valueSaver)); }
1252
1255 Ptr with(const std::string &s) { return with(&s, &s+1); }
1256 Ptr with(const std::vector<std::string> sv) { return with(sv.begin(), sv.end()); }
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>
1325protected:
1327 ListParser(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe)
1328 : minLength_(1), maxLength_((size_t)-1) {
1329 elements_.push_back(ParserSep(firstElmtType, separatorRe));
1330 }
1331public:
1334
1336 typedef std::list<ParsedValue> ValueList;
1337
1345 static Ptr instance(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe="[,;:]\\s*") {
1346 return Ptr(new ListParser(firstElmtType, separatorRe));
1347 }
1348
1355 Ptr nextMember(const ValueParser::Ptr &elmtType, const std::string &separatorRe="[,;:]\\s*") {
1356 elements_.push_back(ParserSep(elmtType, separatorRe));
1357 return sharedFromThis().dynamicCast<ListParser>();
1358 }
1359
1366 Ptr limit(size_t minLength, size_t maxLength);
1367 Ptr limit(size_t maxLength) { return limit(std::min(minLength_, maxLength), maxLength); }
1368 Ptr exactly(size_t length) { return limit(length, length); }
1370private:
1371 virtual ParsedValue operator()(Cursor&) /*override*/;
1372};
1373
1429template<typename T>
1430typename AnyParser<T>::Ptr anyParser(T &storage) {
1432}
1433template<typename T>
1435 return AnyParser<T>::instance();
1436}
1438
1439template<typename T>
1443template<typename T>
1448
1449template<typename T>
1453template<typename T>
1458
1459template<typename T>
1463template<typename T>
1468
1469template<typename T>
1473template<typename T>
1478
1479template<typename T>
1483template<typename T>
1488
1489template<typename T>
1490typename EnumParser<T>::Ptr enumParser(T &storage) {
1492}
1493template<typename T>
1494typename EnumParser<T>::Ptr enumParser(std::vector<T> &storage) {
1495 return EnumParser<T>::instance(TypedSaver<std::vector<T> >::instance(storage));
1496}
1497template<typename T>
1499 return EnumParser<T>::instance(TypedSaver<Optional<T> >::instance(storage));
1500}
1501template<typename T>
1503 return EnumParser<T>::instance(TypedSaver<BitFlags<T> >::instance(storage));
1504}
1505template<typename T>
1509
1510SAWYER_EXPORT StringSetParser::Ptr stringSetParser(std::string &storage);
1512
1513SAWYER_EXPORT ListParser::Ptr listParser(const ValueParser::Ptr&, const std::string &sepRe="[,;:]\\s*");
1518// Switch argument descriptors
1520
1535class SAWYER_EXPORT SwitchArgument {
1536#include <Sawyer/WarningsOff.h>
1537 std::string name_; // argument name for synopsis
1538 ValueParser::Ptr parser_; // how to match and parse this argument
1539 ParsedValue defaultValue_; // default value if the argument is optional
1540#include <Sawyer/WarningsRestore.h>
1541public:
1544 explicit SwitchArgument(const std::string &name, const ValueParser::Ptr &parser = anyParser())
1545 : name_(name), parser_(parser) {}
1546
1550 SwitchArgument(const std::string &name, const ValueParser::Ptr &parser, const std::string &defaultValueString)
1551 : name_(name), parser_(parser), defaultValue_(parser->matchString(defaultValueString)) {
1552 defaultValue_.valueLocation(NOWHERE);
1553 }
1554
1556 bool isRequired() const {
1557 return defaultValue_.isEmpty();
1558 }
1559
1562 bool isOptional() const {
1563 return !isRequired();
1564 }
1565
1571 const std::string &name() const { return name_; }
1572
1574 std::string nameAsText() const;
1575
1577 const ParsedValue& defaultValue() const {
1578 return defaultValue_;
1579 }
1580
1584 const std::string& defaultValueString() const {
1585 return defaultValue_.string();
1586 }
1587
1589 const ValueParser::Ptr& parser() const { return parser_; }
1590};
1591
1592
1594// Switch actions
1596
1612class SAWYER_EXPORT SwitchAction: public SharedObject {
1613public:
1616 virtual ~SwitchAction() {}
1617
1619 void run(const ParserResult &parserResult) /*final*/ { (*this)(parserResult); }
1620protected:
1621 virtual void operator()(const ParserResult&) = 0;
1622};
1623
1627class SAWYER_EXPORT ShowVersion: public SwitchAction {
1628#include <Sawyer/WarningsOff.h>
1629 std::string versionString_;
1630#include <Sawyer/WarningsRestore.h>
1631protected:
1633 explicit ShowVersion(const std::string &versionString): versionString_(versionString) {}
1634public:
1637
1642 static Ptr instance(const std::string &versionString) { return Ptr(new ShowVersion(versionString)); }
1643protected:
1644 virtual void operator()(const ParserResult&) /*overload*/;
1645};
1646
1649class SAWYER_EXPORT ShowVersionAndExit: public ShowVersion {
1650 int exitStatus_;
1651protected:
1653 explicit ShowVersionAndExit(const std::string &versionString, int exitStatus)
1654 : ShowVersion(versionString), exitStatus_(exitStatus) {}
1655public:
1658
1663 static Ptr instance(const std::string &versionString, int exitStatus) {
1664 return Ptr(new ShowVersionAndExit(versionString, exitStatus));
1665 }
1666protected:
1667 virtual void operator()(const ParserResult&) /*overload*/;
1668};
1669
1674class SAWYER_EXPORT ShowHelp: public SwitchAction {
1675protected:
1678public:
1681
1686 static Ptr instance() { return Ptr(new ShowHelp); }
1687protected:
1688 virtual void operator()(const ParserResult&) /*override*/;
1689};
1690
1693class SAWYER_EXPORT ShowHelpAndExit: public ShowHelp {
1694 int exitStatus_;
1695protected:
1697 ShowHelpAndExit(int exitStatus): exitStatus_(exitStatus) {}
1698public:
1701
1706 static Ptr instance(int exitStatus) { return Ptr(new ShowHelpAndExit(exitStatus)); }
1707protected:
1708 virtual void operator()(const ParserResult&) /*override*/;
1709};
1710
1726class SAWYER_EXPORT ConfigureDiagnostics: public SwitchAction {
1727#include <Sawyer/WarningsOff.h>
1728 std::string switchKey_;
1729 Message::Facilities &facilities_;
1730 bool exitOnHelp_;
1731#include <Sawyer/WarningsRestore.h>
1732protected:
1734 ConfigureDiagnostics(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp)
1735 : switchKey_(switchKey), facilities_(facilities), exitOnHelp_(exitOnHelp) {}
1736public:
1739
1744 static Ptr instance(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp=true) {
1745 return Ptr(new ConfigureDiagnostics(switchKey, facilities, exitOnHelp));
1746 }
1747
1753 bool exitOnHelp() const { return exitOnHelp_; }
1754 void exitOnHelp(bool b) { exitOnHelp_=b; }
1756protected:
1757 virtual void operator()(const ParserResult&) /*override*/;
1758};
1759
1767class SAWYER_EXPORT ConfigureDiagnosticsQuiet: public SwitchAction {
1768#include <Sawyer/WarningsOff.h>
1769 Message::Facilities &facilities_;
1770#include <Sawyer/WarningsRestore.h>
1771protected:
1773 : facilities_(facilities) {
1774 }
1775
1776public:
1779
1784 static Ptr instance(Message::Facilities &facilities) {
1785 return Ptr(new ConfigureDiagnosticsQuiet(facilities));
1786 }
1787
1788protected:
1789 virtual void operator()(const ParserResult&) /*override*/;
1790};
1791
1811template<class Functor>
1813 Functor &functor_;
1814protected:
1816 UserAction(Functor &f): functor_(f) {}
1817public:
1820
1825 static Ptr instance(Functor &f) { return Ptr(new UserAction(f)); }
1826protected:
1827 virtual void operator()(const ParserResult &parserResult) /*override*/ { (functor_)(parserResult); }
1828};
1829
1859SAWYER_EXPORT ShowVersion::Ptr showVersion(const std::string &versionString);
1860SAWYER_EXPORT ShowVersionAndExit::Ptr showVersionAndExit(const std::string &versionString, int exitStatus);
1861
1862SAWYER_EXPORT ShowHelp::Ptr showHelp();
1863
1864SAWYER_EXPORT ShowHelpAndExit::Ptr showHelpAndExit(int exitStatus);
1865
1866SAWYER_EXPORT ConfigureDiagnostics::Ptr configureDiagnostics(const std::string&, Message::Facilities&, bool exitOnHelp=true);
1867
1869
1870template<class Functor>
1871typename UserAction<Functor>::Ptr userAction(const Functor &functor) {
1872 return UserAction<Functor>::instance(functor);
1873}
1879// Switch value agumenters
1881
1896class SAWYER_EXPORT ValueAugmenter: public SharedObject {
1897public:
1900 virtual ~ValueAugmenter() {}
1901
1906 virtual ParsedValues operator()(const ParsedValues &savedValues, const ParsedValues &newValues) = 0;
1907};
1908
1921template<typename T>
1922class Sum: public ValueAugmenter {
1923protected:
1925 Sum() {}
1926public:
1929
1934 static Ptr instance() { return Ptr(new Sum<T>); }
1935
1936 virtual ParsedValues operator()(const ParsedValues &savedValues, const ParsedValues &newValues) /*override*/ {
1937 ASSERT_forbid(newValues.empty());
1938 T sum = 0;
1939 BOOST_FOREACH (const ParsedValue &pv, savedValues)
1940 sum = sum + boost::any_cast<T>(pv.value());
1941 BOOST_FOREACH (const ParsedValue &pv, newValues)
1942 sum = sum + boost::any_cast<T>(pv.value());
1943 ParsedValue pval = newValues.front(); // so we keep the same location information
1944 pval.value(sum);
1945 ParsedValues pvals;
1946 pvals.push_back(pval);
1947 return pvals;
1948 }
1949};
1950
1980template<typename T>
1981typename Sum<T>::Ptr sum() {
1982 return Sum<T>::instance();
1983}
1989// Switch descriptors
1991
1992// Used internally to pass around switch properties that are common among parsers, switch groups, and switches.
1993struct SAWYER_EXPORT ParsingProperties {
1994#include <Sawyer/WarningsOff.h>
1995 std::vector<std::string> longPrefixes; // Prefixes for long command-line switches
1996 bool inheritLongPrefixes; // True if this also inherits longPrefixes from a higher layer
1997 std::vector<std::string> shortPrefixes;
1998 bool inheritShortPrefixes;
1999 std::vector<std::string> valueSeparators; // What separates a long switch from its value.
2000 bool inheritValueSeparators;
2001 ShowGroupName showGroupName; // How to show group name in switch synopsis
2002#include <Sawyer/WarningsRestore.h>
2004 : inheritLongPrefixes(true), inheritShortPrefixes(true), inheritValueSeparators(true),
2005 showGroupName(SHOW_GROUP_INHERIT) {}
2006 ParsingProperties inherit(const ParsingProperties &base) const;
2007};
2008
2018
2041class SAWYER_EXPORT Switch {
2042private:
2043#include <Sawyer/WarningsOff.h>
2044 std::vector<std::string> longNames_; // Long name of switch, or empty string.
2045 std::string shortNames_; // Optional short names for this switch.
2046 std::string key_; // Unique key, usually the long name or the first short name.
2047 ParsingProperties properties_; // Properties valid at multiple levels of the hierarchy.
2048 std::string synopsis_; // User-defined synopsis or empty string.
2049 std::string documentation_; // Main documentation for the switch.
2050 std::string documentationKey_; // For sorting documentation.
2051 bool hidden_; // Whether to hide documentation.
2052 std::vector<SwitchArgument> arguments_; // Arguments with optional default values.
2053 SwitchAction::Ptr action_; // Optional action to perform during ParserResult::apply.
2054 WhichValue whichValue_; // Which switch values should be saved.
2055 ValueAugmenter::Ptr valueAugmenter_; // Used if <code>whichValue_==SAVE_AUGMENTED</code>.
2056 ParsedValue intrinsicValue_; // Value for switches that have no declared arguments.
2057 bool explosiveLists_; // Whether to expand ListParser::ValueList into separate values.
2058 SwitchSkipping skipping_; // Whether to skip over this switch without saving or acting.
2059#include <Sawyer/WarningsRestore.h>
2060
2061public:
2074 explicit Switch(const std::string &longName, char shortName='\0')
2075 : hidden_(false), whichValue_(SAVE_LAST), intrinsicValue_(ParsedValue(true, NOWHERE, "true", ValueSaver::Ptr())),
2076 explosiveLists_(false), skipping_(SKIP_NEVER) {
2077 init(longName, shortName);
2078 }
2079
2080 // FIXME[Robb Matzke 2014-03-03]: test that "--prefix=5" works when names are "pre" and "prefix" in that order
2085 Switch& longName(const std::string &name);
2086 const std::string& longName() const { return longNames_.front(); }
2087 const std::vector<std::string>& longNames() const { return longNames_; }
2095 Switch& shortName(char c) { if (c) shortNames_ += std::string(1, c); return *this; }
2096 const std::string& shortNames() const { return shortNames_; }
2101 std::string preferredName() const { return longNames_.empty() ? std::string(1, shortNames_[0]) : longNames_[0]; }
2102
2111 Switch& key(const std::string &s) { key_ = s; return *this; }
2112 const std::string &key() const { return key_; }
2146 Switch& synopsis(const std::string &s) { synopsis_ = s; return *this; }
2147 std::string synopsis() const;
2185 Switch& doc(const std::string &s) { documentation_ = s; return *this; }
2186 const std::string& doc() const { return documentation_; }
2193 Switch& docKey(const std::string &s) { documentationKey_ = s; return *this; }
2194 const std::string &docKey() const { return documentationKey_; }
2201 Switch& hidden(bool b) { hidden_ = b; return *this; }
2202 bool hidden() const { return hidden_; }
2216 Switch& skipping(SwitchSkipping how) { skipping_ = how; return *this; }
2217 SwitchSkipping skipping() const { return skipping_; }
2231 Switch& resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2232 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2233 Switch& longPrefix(const std::string &s1) { properties_.longPrefixes.push_back(s1); return *this; }
2234 const std::vector<std::string>& longPrefixes() const { return properties_.longPrefixes; }
2248 Switch& resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2249 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2250 Switch& shortPrefix(const std::string &s1) { properties_.shortPrefixes.push_back(s1); return *this; }
2251 const std::vector<std::string>& shortPrefixes() const { return properties_.shortPrefixes; }
2270 Switch& resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2271 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2272 Switch& valueSeparator(const std::string &s1) { properties_.valueSeparators.push_back(s1); return *this; }
2273 const std::vector<std::string>& valueSeparators() const { return properties_.valueSeparators; }
2298 Switch& argument(const std::string &name, const ValueParser::Ptr &parser = anyParser());
2299 Switch& argument(const std::string &name, const ValueParser::Ptr &parser, const std::string &defaultValue);
2300 Switch& argument(const SwitchArgument &arg) { arguments_.push_back(arg); return *this; }
2301 const SwitchArgument& argument(size_t idx) const { return arguments_[idx]; }
2302 const std::vector<SwitchArgument>& arguments() const { return arguments_; }
2306 size_t nArguments() const { return arguments_.size(); }
2307
2310 size_t nRequiredArguments() const;
2311
2341 template<typename T>
2342 Switch& intrinsicValue(const T &value, T &storage) {
2343 intrinsicValue_ = ParsedValue(value, NOWHERE, boost::lexical_cast<std::string>(value), TypedSaver<T>::instance(storage));
2344 return *this;
2345 }
2346 Switch& intrinsicValue(const char *value, std::string &storage) {
2347 intrinsicValue_ = ParsedValue(std::string(value), NOWHERE, value, TypedSaver<std::string>::instance(storage));
2348 return *this;
2349 }
2350 Switch& intrinsicValue(const std::string &text, const ValueParser::Ptr &p) {
2351 intrinsicValue_ = p->matchString(text);
2352 intrinsicValue_.valueLocation(NOWHERE);
2353 return *this;
2354 }
2355 Switch& intrinsicValue(const std::string &text) {
2356 intrinsicValue_ = anyParser()->matchString(text);
2357 intrinsicValue_.valueLocation(NOWHERE);
2358 return *this;
2359 }
2360 Switch& intrinsicValue(const ParsedValue &value) { intrinsicValue_ = value; return *this; }
2361 ParsedValue intrinsicValue() const { return intrinsicValue_; }
2386 Switch& explosiveLists(bool b) { explosiveLists_ = b; return *this; }
2387 bool explosiveLists() const { return explosiveLists_; }
2411 Switch& action(const SwitchAction::Ptr &f) { action_ = f; return *this; }
2412 const SwitchAction::Ptr& action() const { return action_; }
2440 Switch& whichValue(WhichValue s) { whichValue_ = s; return *this; }
2441 WhichValue whichValue() const { return whichValue_; }
2452 Switch& valueAugmenter(const ValueAugmenter::Ptr &f) { valueAugmenter_ = f; return *this; }
2453 ValueAugmenter::Ptr valueAugmenter() const { return valueAugmenter_; }
2456public:
2457 // Used internally
2458 const ParsingProperties& properties() const { return properties_; }
2459
2460private:
2461 friend class Parser;
2462 friend class ParserResult;
2463
2464 void init(const std::string &longName, char shortName);
2465
2467 std::runtime_error noSeparator(const std::string &switchString, const Cursor&, const ParsingProperties&) const;
2468
2470 std::runtime_error extraTextAfterSwitch(const std::string &switchString, const Location &endOfSwitch, const Cursor&,
2471 const ParsingProperties&, const ParsedValues&) const;
2472
2474 std::runtime_error extraTextAfterArgument(const Cursor&, const ParsedValue &va) const;
2475
2477 std::runtime_error notEnoughArguments(const std::string &switchString, const Cursor&, size_t nargs) const;
2478
2480 std::runtime_error missingArgument(const std::string &switchString, const Cursor &cursor,
2481 const SwitchArgument &sa, const std::string &reason) const;
2482
2484 std::runtime_error malformedArgument(const std::string &switchString, const Cursor &cursor,
2485 const SwitchArgument &sa, const std::string &reason) const;
2486
2493 size_t matchLongName(Cursor&/*in,out*/, const ParsingProperties &props,
2494 const std::string &optionalPart, const std::string &requiredPart) const;
2495
2502 size_t matchShortName(Cursor&/*in,out*/, const ParsingProperties &props, std::string &name) const;
2503
2505 bool explode(ParsedValues &pvals /*in,out*/) const;
2506
2511 void matchLongArguments(const std::string &switchString, Cursor &cursor /*in,out*/, const ParsingProperties &props,
2512 ParsedValues &result /*out*/) const;
2513
2517 void matchShortArguments(const std::string &switchString, Cursor &cursor /*in,out*/, const ParsingProperties &props,
2518 ParsedValues &result /*out*/, bool mayNestle) const;
2519
2527 size_t matchArguments(const std::string &switchString, const Location &endOfSwitch, Cursor &cursor /*in,out*/,
2528 const ParsingProperties &props, ParsedValues &result /*out*/, bool isLongSwitch) const;
2529
2531 std::string synopsisForArgument(const SwitchArgument&) const;
2532
2533 // If the synopsis is empty, create one from an optional switch group and name space separator
2534 std::string synopsis(const ParsingProperties &swProps, const SwitchGroup *sg, const std::string &nameSpaceSeparator) const;
2535};
2536
2538// Switch groups
2540
2541
2569class SAWYER_EXPORT SwitchGroup {
2570#include <Sawyer/WarningsOff.h>
2571 std::vector<Switch> switches_;
2572 ParsingProperties properties_;
2573 std::string name_; // name optionally prepended to all switches
2574 std::string title_; // title showing in documentation
2575 std::string docKey_; // for sorting
2576 std::string documentation_;
2577 SortOrder switchOrder_;
2578#include <Sawyer/WarningsRestore.h>
2579public:
2581 SwitchGroup(): switchOrder_(DOCKEY_ORDER) { initializeLibrary(); }
2582
2589 explicit SwitchGroup(const std::string &title, const std::string &docKey="")
2590 : title_(title), docKey_(docKey), switchOrder_(DOCKEY_ORDER) {}
2591
2597 const std::string& title() const { return title_; }
2598 SwitchGroup& title(const std::string &title) { title_ = title; return *this; }
2611 const std::string& name() const { return name_; }
2612 SwitchGroup& name(const std::string &name) { name_ = name; return *this; }
2627 const std::string& docKey() const { return docKey_; }
2628 SwitchGroup& docKey(const std::string &key) { docKey_ = key; return *this; }
2643 SwitchGroup& doc(const std::string &s) { documentation_ = s; return *this; }
2644 const std::string& doc() const { return documentation_; }
2653 ShowGroupName showingGroupNames() const { return properties_.showGroupName; }
2654 void showingGroupNames(ShowGroupName x) { properties_.showGroupName = x; }
2659 SwitchGroup& resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2660 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2661 SwitchGroup& longPrefix(const std::string &s1) { properties_.longPrefixes.push_back(s1); return *this; }
2662 const std::vector<std::string>& longPrefixes() const { return properties_.longPrefixes; }
2667 SwitchGroup& resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2668 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2669 SwitchGroup& shortPrefix(const std::string &s1) { properties_.shortPrefixes.push_back(s1); return *this; }
2670 const std::vector<std::string>& shortPrefixes() const { return properties_.shortPrefixes; }
2675 SwitchGroup& resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2676 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2677 SwitchGroup& valueSeparator(const std::string &s1) { properties_.valueSeparators.push_back(s1); return *this; }
2678 const std::vector<std::string>& valueSeparators() const { return properties_.valueSeparators; }
2682 size_t nSwitches() const { return switches_.size(); }
2683
2686 const std::vector<Switch>& switches() const { return switches_; }
2687
2689 bool nameExists(const std::string &switchName);
2690
2693 const Switch& getByName(const std::string &switchName);
2694
2696 bool keyExists(const std::string &switchKey);
2697
2699 const Switch& getByKey(const std::string &switchKey);
2700
2703
2706
2709
2712 SwitchGroup& removeByName(const std::string &switchName);
2713
2715 SwitchGroup& removeByKey(const std::string &switchKey);
2716
2728 const SortOrder& switchOrder() const { return switchOrder_; }
2729 SwitchGroup& switchOrder(SortOrder order) { switchOrder_ = order; return *this; }
2732public:
2733 // Used internally
2734 const ParsingProperties& properties() const { return properties_; }
2735
2736private:
2737 friend class Parser;
2738 bool removeByPointer(const void*);
2739};
2740
2743
2746
2748// Parser
2750
2756class SAWYER_EXPORT Parser {
2757#include <Sawyer/WarningsOff.h>
2758 std::vector<SwitchGroup> switchGroups_;
2759 ParsingProperties properties_;
2760 std::string groupNameSeparator_;
2761 std::vector<std::string> terminationSwitches_;
2762 bool shortMayNestle_;
2763 std::vector<std::string> inclusionPrefixes_;
2764 bool skipNonSwitches_;
2765 bool skipUnknownSwitches_;
2766 mutable std::string programName_;
2767 std::string purpose_;
2768 std::string versionString_;
2769 mutable std::string dateString_;
2770 int chapterNumber_;
2771 std::string chapterName_;
2773 StringStringMap sectionDoc_;
2774 StringStringMap sectionOrder_;
2775 Message::SProxy errorStream_;
2776 Optional<std::string> exitMessage_;
2777 SortOrder switchGroupOrder_;
2778 bool reportingAmbiguities_;
2779 std::string environmentVariable_;
2780#include <Sawyer/WarningsRestore.h>
2781
2782public:
2786 : groupNameSeparator_("-"), shortMayNestle_(true), skipNonSwitches_(false), skipUnknownSwitches_(false),
2787 versionString_("alpha"), chapterNumber_(1), chapterName_("User Commands"), switchGroupOrder_(INSERTION_ORDER),
2788 reportingAmbiguities_(true) {
2789 init();
2790 }
2791
2796 switchGroups_.push_back(sg);
2797 return *this;
2798 }
2799 Parser& with(const SwitchGroup &sg, const std::string &docKey) {
2800 switchGroups_.push_back(sg);
2801 switchGroups_.back().docKey(docKey);
2802 return *this;
2803 }
2804 Parser& with(const std::vector<SwitchGroup> &sgs) {
2805 switchGroups_.insert(switchGroups_.end(), sgs.begin(), sgs.end());
2806 return *this;
2807 }
2808 Parser& with(const Switch &sw) {
2809 switchGroups_.push_back(SwitchGroup().insert(sw));
2810 return *this;
2811 }
2812 Parser& with(Switch sw, const std::string &docKey) {
2813 sw.docKey(docKey);
2814 switchGroups_.push_back(SwitchGroup().insert(sw));
2815 return *this;
2816 }
2822 const std::vector<SwitchGroup>& switchGroups() const {
2823 return switchGroups_;
2824 }
2825 std::vector<SwitchGroup>& switchGroups() {
2826 return switchGroups_;
2827 }
2833 bool switchGroupExists(const std::string &name) const;
2834
2841 const SwitchGroup& switchGroup(const std::string &name) const;
2842 SwitchGroup& switchGroup(const std::string &name);
2849 bool eraseSwitchGroup(const std::string &name);
2850
2862 bool reportingAmbiguities() const { return reportingAmbiguities_; }
2863 Parser& reportingAmbiguities(bool b) { reportingAmbiguities_ = b; return *this; }
2873 const std::string& groupNameSeparator() const { return groupNameSeparator_; }
2874 Parser& groupNameSeparator(const std::string &s) { groupNameSeparator_ = s; return *this; }
2886 ShowGroupName showingGroupNames() const { return properties_.showGroupName; }
2887 Parser& showingGroupNames(ShowGroupName x) { properties_.showGroupName = x; return *this; }
2894 Parser& resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2895 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2896 Parser& longPrefix(const std::string &s1) { properties_.longPrefixes.push_back(s1); return *this; }
2897 const std::vector<std::string>& longPrefixes() const { return properties_.longPrefixes; }
2904 Parser& resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2905 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2906 Parser& shortPrefix(const std::string &s1) { properties_.shortPrefixes.push_back(s1); return *this; }
2907 const std::vector<std::string>& shortPrefixes() const { return properties_.shortPrefixes; }
2916 Parser& resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2917 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2918 Parser& valueSeparator(const std::string &s1) { properties_.valueSeparators.push_back(s1); return *this; }
2919 const std::vector<std::string>& valueSeparators() const { return properties_.valueSeparators; }
2926 Parser& resetTerminationSwitches(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2927 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2928 Parser& terminationSwitch(const std::string &s1) { terminationSwitches_.push_back(s1); return *this; }
2929 const std::vector<std::string>& terminationSwitches() const { return terminationSwitches_; }
2939 Parser& shortMayNestle(bool b) { shortMayNestle_ = b; return *this; }
2940 bool shortMayNestle() const { return shortMayNestle_; }
2954 Parser& resetInclusionPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2955 const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2956 Parser& inclusionPrefix(const std::string &s1) { inclusionPrefixes_.push_back(s1); return *this; }
2957 const std::vector<std::string>& inclusionPrefixes() const { return inclusionPrefixes_; }
2967 Parser& skippingNonSwitches(bool b) { skipNonSwitches_ = b; return *this; }
2968 bool skippingNonSwitches() const { return skipNonSwitches_; }
2977 Parser& skippingUnknownSwitches(bool b) { skipUnknownSwitches_ = b; return *this; }
2978 bool skippingUnknownSwitches() const { return skipUnknownSwitches_; }
2998 Parser& errorStream(const Message::SProxy &stream) { errorStream_ = stream; return *this; }
2999 const Message::SProxy& errorStream() const { return errorStream_; }
3008 Parser& exitMessage(const std::string &s) { exitMessage_ = s; return *this; }
3009 std::string exitMessage() const { return exitMessage_ ? *exitMessage_ : std::string(); }
3018 Parser& environmentVariable(const std::string &s) { environmentVariable_ = s; return *this; }
3019 const std::string& environmentVariable() const { return environmentVariable_; }
3025 ParserResult parse(int argc, char *argv[]);
3026
3028 ParserResult parse(const std::vector<std::string>&);
3029
3030#if 0 /* [Robb Matzke 2014-03-04] */
3033 template<typename Iterator>
3034 ParserResult parse(Iterator begin, Iterator end) {
3035 std::vector<std::string> args(begin, end);
3036 return parse(args);
3037 }
3038#endif
3039
3043 static std::vector<std::string> splitLineIntoWords(std::string);
3044
3050 static std::vector<std::string> readArgsFromFile(const std::string &filename);
3051
3056 static std::vector<std::string> readArgsFromEnvVar(const std::string &varName);
3057
3062 std::vector<std::string> expandIncludedFiles(const std::vector<std::string> &args);
3063
3066 DEFAULT_GROUPING = 0,
3067 PROHIBIT_EMPTY_GROUPS = 0x0001,
3068 SPLIT_SINGLE_GROUP = 0x0002
3070
3078 std::vector<std::vector<std::string> >
3079 regroupArgs(const std::vector<std::string> &args,
3081 unsigned flags = 0 /*GroupingFlags*/);
3082
3086 Parser& programName(const std::string& programName) { programName_ = programName; return *this; }
3087 const std::string& programName() const;
3094 Parser& purpose(const std::string &purpose) { purpose_ = purpose; return *this; }
3095 const std::string& purpose() const { return purpose_; }
3101 Parser& version(const std::string &versionString, const std::string &dateString="");
3102 Parser& version(const std::pair<std::string, std::string> &p) { return version(p.first, p.second); }
3103 std::pair<std::string, std::string> version() const;
3121 Parser& chapter(int chapterNumber, const std::string &chapterName="");
3122 Parser& chapter(const std::pair<int, std::string> &p) { return chapter(p.first, p.second); }
3123 std::pair<int, std::string> chapter() const;
3164 Parser& doc(const std::string &sectionName, const std::string &docKey, const std::string &text);
3165 Parser& doc(const std::string &sectionName, const std::string &text) { return doc(sectionName, sectionName, text); }
3166 Parser& doc(const std::pair<std::string /*sectionName*/, std::string /*text*/>&);
3167 std::vector<std::string> docSections() const;
3168 std::string docForSwitches() const;
3169 std::string docForSection(const std::string &sectionName) const;
3176 std::string documentationMarkup() const;
3177
3181 std::string podDocumentation() const;
3182
3184 std::string textDocumentation() const;
3185
3188
3189 template<class Grammar>
3190 void emitDocumentationToPager() const {
3191 Grammar grammar;
3192 initDocGrammar(grammar);
3193 grammar.title(programName(), boost::lexical_cast<std::string>(chapter().first), chapter().second);
3194 grammar.version(version().first, version().second);
3195 grammar.emit(documentationMarkup());
3196 }
3197
3203 SortOrder switchGroupOrder() const { return switchGroupOrder_; }
3204 Parser& switchGroupOrder(SortOrder order) { switchGroupOrder_ = order; return *this; }
3210 void insertLongSwitchStrings(Canonical, NamedSwitches &index /*in,out*/) const;
3211
3215 void insertShortSwitchStrings(NamedSwitches &index /*in,out*/) const;
3216
3221 void insertSwitchStrings(Canonical, NamedSwitches &index /*in,out*/) const;
3222
3226 static void printIndex(std::ostream&, const NamedSwitches&, const std::string &linePrefix = "");
3227
3232
3237
3250 Sawyer::Optional<Switch> removeMatchingSwitch(const std::vector<std::string> &args);
3253public:
3254 // Used internally
3255 const ParsingProperties& properties() const { return properties_; }
3256
3257private:
3258 void init();
3259
3260 // Implementation for the public parse methods.
3261 ParserResult parseInternal(std::vector<std::string> programArguments);
3262
3263 // Parse one switch from the current position in the command line and return the switch descriptor. If the cursor is at
3264 // the end of the command line then return false without updating the cursor or parsed values. If the cursor is at a
3265 // termination switch (e.g., "--") then consume the terminator and return false. If the switch name is valid but the
3266 // arguments cannot be parsed, then throw an error. If the cursor is at what appears to be a switch but no matching switch
3267 // declaration can be found, then throw an error. The cursor will not be modified when an error is thrown.
3268 bool parseOneSwitch(Cursor&, const NamedSwitches &ambiguities, ParserResult&/*out*/);
3269
3276 const Switch* parseLongSwitch(Cursor&, ParsedValues&, const NamedSwitches &ambiguities, Optional<std::runtime_error>&);
3277
3286 const Switch* parseShortSwitch(Cursor&, ParsedValues&, const NamedSwitches &ambiguities,
3287 Optional<std::runtime_error>&, bool mayNestle);
3288
3289 // Returns true if the program argument at the cursor looks like it might be a switch. Apparent switches are any program
3290 // argument that starts with a long or short prefix.
3291 bool apparentSwitch(const Cursor&) const;
3292
3293 // Returns the best prefix for each switch--the one used for documentation
3294 void preferredSwitchPrefixes(Container::Map<std::string, std::string> &prefixMap /*out*/) const;
3295
3296 // Construct an error message for an ambiguous switch, switchString, having an optional group name part (including the
3297 // separator), and the required switch name. The switchString must be present in the ambiguities table.
3298 std::string ambiguityErrorMesg(const std::string &longSwitchString, const std::string &optionalPart,
3299 const std::string &longSwitchName, const NamedSwitches &ambiguities);
3300 std::string ambiguityErrorMesg(const std::string &shortSwitchString, const NamedSwitches &ambiguities);
3301
3302 // Initialize a documentation parser by registering things like @s, @man, etc. The argument is a subclass such as
3303 // Document::PodMarkup.
3304 void initDocGrammar(Document::Markup::Grammar& /*in,out*/) const;
3305
3306 // FIXME[Robb Matzke 2014-02-21]: Some way to parse command-lines from a config file, or to merge parsed command-lines with
3307 // a yaml config file, etc.
3308};
3309
3334class SAWYER_EXPORT ParserResult {
3335#include <Sawyer/WarningsOff.h>
3336 Parser parser_;
3337 Cursor cursor_;
3338 ParsedValues values_;
3339
3340 // Maps a name to indexes into the values_ vector.
3342 NameIndex keyIndex_; // Values per switch key
3343 NameIndex switchIndex_; // Values per switch preferred name
3344
3345 // List of parsed values organized by their location on the command line. The location is for the switch itself even if
3346 // the values are spread out across subsequent argv members. We do it this way because many of the values are defaults that
3347 // don't actually have an argv location. The integers are indexes into the values_ vector. In other words, this is a
3348 // mapping from switch location to values_ elements for the switch's values.
3350 ArgvIndex argvIndex_;
3351
3352 // Information about program arguments that the parser skipped over. Indexes into argv_.
3353 typedef std::vector<size_t> SkippedIndex;
3354 SkippedIndex skippedIndex_;
3355
3356 // Information about terminator switches like "--". Indexes into argv_.
3357 SkippedIndex terminators_;
3358
3361#include <Sawyer/WarningsRestore.h>
3362
3363private:
3364 friend class Parser;
3365 ParserResult(const Parser &parser, const std::vector<std::string> &argv): parser_(parser), cursor_(argv) {}
3366
3367public:
3368 ParserResult() {}
3369
3372 const ParserResult& apply() const;
3373
3376 size_t have(const std::string &switchKey) const {
3377 return keyIndex_.getOrDefault(switchKey).size();
3378 }
3379
3398 const ParsedValue& parsed(const std::string &switchKey, size_t idx) const;
3399 ParsedValues parsed(const std::string &switchKey) const;
3412 std::vector<std::string> skippedArgs() const;
3413
3420 std::vector<std::string> unreachedArgs() const;
3421
3436 std::vector<std::string> unparsedArgs(bool includeTerminators=false) const;
3437
3442 std::vector<std::string> parsedArgs() const;
3443
3448 const std::vector<std::string>& allArgs() const { return cursor_.strings(); }
3449
3451 const Parser& parser() const { return parser_; }
3452
3453private:
3454 // Insert more parsed values. Values should be inserted one switch's worth at a time (or fewer)
3455 void insertValuesForSwitch(const ParsedValues&, const Parser*, const Switch*);
3456 void insertOneValue(const ParsedValue&, const Switch*, bool save=true);
3457
3458 // Indicate that we're skipping over a program argument
3459 void skip(const Location&);
3460
3461 // Add a terminator
3462 void terminator(const Location&);
3463
3464 Cursor& cursor() { return cursor_; }
3465};
3466
3467} // namespace
3468} // namespace
3469
3470#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.
SharedPointer< ConfigureDiagnostics > Ptr
Reference counting pointer for this class.
void exitOnHelp(bool b)
Property: program exit after help is displayed.
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 &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.
void emitDocumentationToPager() const
Print documentation to standard output.
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.
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 & 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 & showingGroupNames(ShowGroupName x)
Property: How to show group names in switch documentation.
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.
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.
Ptr with(const std::string &s)
Adds string members.
static Ptr instance()
Allocating constructor.
Ptr with(InputIterator begin, InputIterator end)
Adds string members.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
SharedPointer< StringSetParser > Ptr
Reference counting pointer for this class.
Ptr with(const std::vector< std::string > sv)
Adds string members.
StringSetParser()
Constructor for derived classes.
StringSetParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
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
const Value & getOrDefault(const Key &key) const
Lookup and return a value or a default.
Definition Sawyer/Map.h:629
Ordered set of values.
Definition Set.h:56
Collection of facilities.
Definition Message.h:1736
Holds a value or nothing.
Definition Optional.h:56
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.