13 #ifndef __STOUT_FLAGS_FLAGS_HPP__ 14 #define __STOUT_FLAGS_FLAGS_HPP__ 84 const char*
const* argv,
85 bool unknowns =
false,
86 bool duplicates =
false);
100 bool unknowns =
false,
101 bool duplicates =
false);
115 bool unknowns =
false,
123 const std::map<std::string, std::string>& values,
124 bool unknowns =
false,
171 const_iterator
begin()
const {
return flags_.begin(); }
172 const_iterator
end()
const {
return flags_.end(); }
174 typedef std::map<std::string, Flag>::iterator
iterator;
176 iterator
begin() {
return flags_.begin(); }
177 iterator
end() {
return flags_.end(); }
185 template <
typename Flags,
typename T1,
typename T2,
typename F>
190 const std::string&
help,
194 template <
typename Flags,
typename T1,
typename T2,
typename F>
199 const std::string& help,
203 add(t1, name, alias, help, &t2, validate);
206 template <
typename Flags,
typename T1,
typename T2,
typename F>
210 const std::string& help,
214 add(t1, name,
None(), help, &t2, validate);
217 template <
typename Flags,
typename T1,
typename T2>
221 const std::string& help,
224 add(t1, name,
None(), help, &t2, [](
const T1&) {
return None(); });
227 template <
typename Flags,
typename T>
231 const std::string& help)
237 static_cast<const T*>(
nullptr),
238 [](
const T&) {
return None(); });
241 template <
typename Flags,
typename T1,
typename T2>
246 const std::string& help,
249 add(t1, name, alias, help, &t2, [](
const T1&) {
return None(); });
252 template <
typename Flags,
typename T,
typename F>
257 const std::string& help,
260 template <
typename Flags,
typename T,
typename F>
264 const std::string& help,
267 add(option, name,
None(), help, validate);
270 template <
typename Flags,
typename T>
274 const std::string& help)
279 template <
typename Flags,
typename T>
284 const std::string& help)
298 std::map<std::string, Option<std::string>>
extract(
299 const std::string& prefix)
const;
320 bool unknowns =
false,
321 bool duplicates =
false,
325 std::map<std::string, Flag> flags_;
328 std::map<std::string, std::string> aliases;
332 template <
typename Flags,
typename T1,
typename T2,
typename F>
337 const std::string& help,
346 Flags*
flags =
dynamic_cast<Flags*
>(
this);
347 if (flags ==
nullptr) {
348 ABORT(
"Attempted to add flag '" + name.
value +
349 "' with incompatible type");
356 flag.
boolean =
typeid(T1) ==
typeid(
bool);
373 Flags* flags =
dynamic_cast<Flags*
>(
base);
374 if (flags !=
nullptr) {
379 flags->*t1 = t.
get();
381 return Error(
"Failed to load value '" + value +
"': " + t.
error());
389 const Flags* flags =
dynamic_cast<const Flags*
>(&
base);
390 if (flags !=
nullptr) {
397 const Flags* flags =
dynamic_cast<const Flags*
>(&
base);
398 if (flags !=
nullptr) {
405 flag.
help += help.size() > 0 && help.find_last_of(
"\n\r") != help.size() - 1
417 template <
typename Flags,
typename T,
typename F>
422 const std::string& help,
426 if (option ==
nullptr) {
430 Flags*
flags =
dynamic_cast<Flags*
>(
this);
431 if (flags ==
nullptr) {
432 ABORT(
"Attempted to add flag '" + name.
value +
433 "' with incompatible type");
440 flag.
boolean =
typeid(T) ==
typeid(
bool);
449 Flags* flags =
dynamic_cast<Flags*
>(
base);
450 if (flags !=
nullptr) {
453 Try<T> t = fetch<T>(value);
455 flags->*option =
Some(t.
get());
457 return Error(
"Failed to load value '" + value +
"': " + t.
error());
465 const Flags* flags =
dynamic_cast<const Flags*
>(&
base);
466 if (flags !=
nullptr) {
467 if ((flags->*option).isSome()) {
468 return stringify((flags->*option).get());
475 const Flags* flags =
dynamic_cast<const Flags*
>(&
base);
476 if (flags !=
nullptr) {
489 std::vector<Name> names = {flag.
name};
490 if (flag.
alias.isSome()) {
493 <<
"Attempted to add flag '" << flag.
name.
value <<
"' with an alias" 494 <<
" that is same as the flag name";
497 names.push_back(flag.
alias.get());
500 foreach (
const Name& name, names) {
501 if (flags_.count(name.
value) > 0) {
503 <<
"Attempted to add duplicate flag '" << name.
value <<
"'";
504 }
else if (name.
value.find(
"no-") == 0) {
506 <<
"Attempted to add flag '" << name.
value 507 <<
"' that starts with the reserved 'no-' prefix";
512 if (flag.
alias.isSome()) {
520 const std::string& prefix)
const 522 std::map<std::string, Option<std::string>> values;
525 const std::string& value,
527 if (key.find(prefix) == 0) {
528 std::string name = key.substr(prefix.size());
535 if (flags_.count(flag_name) > 0 || aliases.count(flag_name) > 0) {
548 std::map<std::string, std::string> result;
553 const std::string key = prefix.
isSome()
557 result[key] = value.
get();
574 const char*
const *argv,
581 programName_ = argc > 0 ?
Path(argv[0]).
basename() :
"";
584 for (
int i = 1; i < argc; i++) {
593 if (arg.find(
"--") != 0) {
600 size_t eq = arg.find_first_of(
'=');
601 if (eq == std::string::npos && arg.find(
"--no-") == 0) {
602 name = arg.substr(2);
603 }
else if (eq == std::string::npos) {
604 name = arg.substr(2);
606 name = arg.substr(2, eq - 2);
607 value = arg.substr(eq + 1);
612 values.
put(name, value);
615 return load(values, unknowns, duplicates, prefix);
629 programName_ = *argc > 0 ?
Path(*(argv[0])).
basename() :
"";
632 std::vector<char*> args;
635 for (
int i = 1; i < *argc; i++) {
641 for (
int j = i + 1; j < *argc; j++) {
642 args.push_back((*argv)[j]);
648 if (arg.find(
"--") != 0) {
649 args.push_back((*argv)[i]);
656 size_t eq = arg.find_first_of(
'=');
657 if (eq == std::string::npos && arg.find(
"--no-") == 0) {
658 name = arg.substr(2);
659 }
else if (eq == std::string::npos) {
660 name = arg.substr(2);
662 name = arg.substr(2, eq - 2);
663 value = arg.substr(eq + 1);
668 values.
put(name, value);
675 CHECK_LE(args.size(), (size_t) *argc);
677 foreach (
char* arg, args) {
686 (*argv)[i++] =
nullptr;
702 values_.
put(name, value);
704 return load(values_, unknowns,
false, prefix);
709 const std::map<std::string, std::string>& values,
714 foreachpair (
const std::string& name,
const std::string& value, values) {
715 values_.
put(name,
Some(value));
717 return load(values_, unknowns,
false, prefix);
738 if (!values.contains(name)) {
739 values.put(name, value);
748 std::string flag_name = !is_negated ? name : name.substr(3);
750 auto iter = aliases.count(flag_name)
751 ? flags_.find(aliases[flag_name])
752 : flags_.find(flag_name);
754 if (iter == flags_.end()) {
756 return Error(
"Failed to load unknown flag '" + flag_name +
"'" +
757 (!is_negated ?
"" :
" via '" + name +
"'"));
763 Flag* flag = &(iter->second);
766 return Error(
"Flag '" + flag_name +
"' is already loaded via name '" +
774 return Error(
"Failed to load non-boolean flag '" + flag_name +
775 "' via '" + name +
"'");
779 return Error(
"Failed to load non-boolean flag '" + flag_name +
783 value_ = value.
get();
785 if (value.
isNone() || value.
get() ==
"") {
786 value_ = !is_negated ?
"true" :
"false";
787 }
else if (!is_negated) {
788 value_ = value.
get();
791 "Failed to load boolean flag '" + flag_name +
"' via '" + name +
792 "' with value '" + value.
get() +
"'");
797 if (load.isError()) {
798 return Error(
"Failed to load flag '" + flag_name +
"': " + load.error());
804 if (aliases.count(flag_name)) {
813 Warning(
"Loaded deprecated flag '" + flag_name +
"'"));
826 "' is required, but it was not provided");
846 usage = message.
get() +
"\n\n";
849 if (usageMessage_.
isNone()) {
850 usage +=
"Usage: " + programName_ +
" [options]\n\n";
852 usage += usageMessage_.
get() +
"\n\n";
855 std::map<std::string, std::string> col1;
863 if (flag.
alias.isSome()) {
869 if (flag.
alias.isSome()) {
879 std::string line = col1[flag.
name.
value];
881 std::string pad(PAD + width - line.size(),
' ');
884 size_t pos1 = 0, pos2 = 0;
885 pos2 = flag.
help.find_first_of(
"\n\r", pos1);
886 line += flag.
help.substr(pos1, pos2 - pos1) +
"\n";
889 while (pos2 != std::string::npos) {
892 std::string pad2(PAD + width,
' ');
894 pos2 = flag.
help.find_first_of(
"\n\r", pos1);
895 line += flag.
help.substr(pos1, pos2 - pos1) +
"\n";
906 std::vector<std::string> _flags;
921 #endif // __STOUT_FLAGS_FLAGS_HPP__ bool boolean
Definition: flag.hpp:89
void add(Option< T > Flags::*option, const Name &name, const Option< Name > &alias, const std::string &help)
Definition: flags.hpp:280
Definition: nothing.hpp:16
Option< Error > validate(const std::string &imageDir)
Definition: errorbase.hpp:36
std::vector< Warning > warnings
Definition: flag.hpp:73
#define ABORT(...)
Definition: abort.hpp:40
void add(T1 Flags::*t1, const Name &name, const Option< Name > &alias, const std::string &help, const T2 &t2, F validate)
Definition: flags.hpp:195
T & get()&
Definition: try.hpp:80
std::stringstream & join(std::stringstream &stream, const std::string &separator, T &&...args)
Definition: strings.hpp:307
constexpr const char * prefix
Definition: os.hpp:96
iterator begin()
Definition: flags.hpp:176
FlagsBase()
Definition: flags.hpp:47
iterator end()
Definition: flags.hpp:177
#define EXIT(status)
Definition: exit.hpp:31
const_iterator begin() const
Definition: flags.hpp:171
bool isSome() const
Definition: option.hpp:116
std::string remove(const std::string &from, const std::string &substring, Mode mode=ANY)
Definition: strings.hpp:41
std::map< std::string, std::string > buildEnvironment(const Option< std::string > &prefix=None()) const
Definition: flags.hpp:545
std::string programName_
Definition: flags.hpp:309
#define CHECK_SOME(expression)
Definition: check.hpp:50
std::map< std::string, Flag >::iterator iterator
Definition: flags.hpp:174
std::string help
Definition: flag.hpp:88
Represents a POSIX or Windows file system path and offers common path manipulations.
Definition: path.hpp:212
Option< T > max(const Option< T > &left, const Option< T > &right)
Definition: option.hpp:214
std::map< std::string, Option< std::string > > extract(const std::string &prefix) const
Definition: flags.hpp:519
Option< std::string > usageMessage_
Definition: flags.hpp:315
bool isSome() const
Definition: try.hpp:77
void setUsageMessage(const std::string &message)
Definition: flags.hpp:164
const T & get() const &
Definition: option.hpp:119
#define foreachpair(KEY, VALUE, ELEMS)
Definition: foreach.hpp:51
virtual ~FlagsBase()=default
Option< Name > alias
Definition: flag.hpp:80
void add(Option< T > Flags::*option, const Name &name, const std::string &help)
Definition: flags.hpp:271
std::map< std::string, std::string > environment()
Definition: environment.hpp:24
Name name
Definition: flag.hpp:79
lambda::function< Try< Nothing >FlagsBase *, const std::string &)> load
Definition: flag.hpp:90
#define foreachvalue(VALUE, ELEMS)
Definition: foreach.hpp:77
bool required
Definition: flag.hpp:93
virtual Try< Warnings > load(const std::string &prefix)
Definition: flags.hpp:565
std::string usage(const Option< std::string > &message=None()) const
Definition: flags.hpp:839
static Try error(const E &e)
Definition: try.hpp:43
Definition: multimap.hpp:30
std::map< std::string, Flag >::const_iterator const_iterator
Definition: flags.hpp:169
lambda::function< Option< Error >const FlagsBase &)> validate
Definition: flag.hpp:92
std::string value
Definition: flag.hpp:47
std::string upper(const std::string &s)
Definition: strings.hpp:437
_Some< typename std::decay< T >::type > Some(T &&t)
Definition: some.hpp:42
bool help
Definition: flags.hpp:295
Iterable< V > map(F &&f, const Iterable< U, Us... > &input)
Definition: lambda.hpp:46
bool isError() const
Definition: try.hpp:78
std::ostream & operator<<(std::ostream &stream, const SecurePathOrValue &flag)
Definition: flag.hpp:113
std::string error(const std::string &msg, uint32_t code)
void add(T Flags::*t, const Name &name, const std::string &help)
Definition: flags.hpp:228
void put(const K &key, const V &value)
Definition: multimap.hpp:53
void add(T1 Flags::*t1, const Name &name, const Option< Name > &alias, const std::string &help, const T2 *t2, F validate)
Definition: flags.hpp:333
void add(T1 Flags::*t1, const Name &name, const Option< Name > &alias, const std::string &help, const T2 &t2)
Definition: flags.hpp:242
bool isNone() const
Definition: option.hpp:117
Option< Name > loaded_name
Definition: flag.hpp:86
lambda::function< Option< std::string >const FlagsBase &)> stringify
Definition: flag.hpp:91
void add(T1 Flags::*t1, const Name &name, const std::string &help, const T2 &t2, F validate)
Definition: flags.hpp:207
std::string basename() const
Extracts the component following the final '/'.
Definition: path.hpp:249
std::string stringify(int flags)
bool startsWith(const std::string &s, const std::string &prefix)
Definition: strings.hpp:381
FlagsBase & operator=(const FlagsBase &)=default
void add(Option< T > Flags::*option, const Name &name, const std::string &help, F validate)
Definition: flags.hpp:261
const Name & effective_name() const
Definition: flag.hpp:97
std::string lower(const std::string &s)
Definition: strings.hpp:429
const_iterator end() const
Definition: flags.hpp:172
constexpr const char * name
Definition: shell.hpp:41
std::string trim(const std::string &from, Mode mode=ANY, const std::string &chars=WHITESPACE)
Definition: strings.hpp:67
void add(T1 Flags::*t1, const Name &name, const std::string &help, const T2 &t2)
Definition: flags.hpp:218
Definition: strings.hpp:35