diff options
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/args.cc | 26 | ||||
-rw-r--r-- | src/libutil/args.hh | 83 | ||||
-rw-r--r-- | src/libutil/config.cc | 29 | ||||
-rw-r--r-- | src/libutil/config.hh | 6 |
4 files changed, 101 insertions, 43 deletions
diff --git a/src/libutil/args.cc b/src/libutil/args.cc index 115484f9e..df7e04087 100644 --- a/src/libutil/args.cc +++ b/src/libutil/args.cc @@ -3,6 +3,18 @@ namespace nix { +Args::FlagMaker Args::mkFlag() +{ + return FlagMaker(*this); +} + +Args::FlagMaker::~FlagMaker() +{ + assert(flag->longName != ""); + args.longFlags[flag->longName] = flag; + if (flag->shortName) args.shortFlags[flag->shortName] = flag; +} + void Args::parseCmdline(const Strings & _cmdline) { Strings pendingArgs; @@ -71,11 +83,13 @@ void Args::printHelp(const string & programName, std::ostream & out) void Args::printFlags(std::ostream & out) { Table2 table; - for (auto & flag : longFlags) + for (auto & flag : longFlags) { + if (hiddenCategories.count(flag.second->category)) continue; table.push_back(std::make_pair( - (flag.second.shortName ? std::string("-") + flag.second.shortName + ", " : " ") - + "--" + flag.first + renderLabels(flag.second.labels), - flag.second.description)); + (flag.second->shortName ? std::string("-") + flag.second->shortName + ", " : " ") + + "--" + flag.first + renderLabels(flag.second->labels), + flag.second->description)); + } printTable(out, table); } @@ -99,14 +113,14 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end) if (string(*pos, 0, 2) == "--") { auto i = longFlags.find(string(*pos, 2)); if (i == longFlags.end()) return false; - return process("--" + i->first, i->second); + return process("--" + i->first, *i->second); } if (string(*pos, 0, 1) == "-" && pos->size() == 2) { auto c = (*pos)[1]; auto i = shortFlags.find(c); if (i == shortFlags.end()) return false; - return process(std::string("-") + c, i->second); + return process(std::string("-") + c, *i->second); } return false; diff --git a/src/libutil/args.hh b/src/libutil/args.hh index f70bb7823..aa11373d5 100644 --- a/src/libutil/args.hh +++ b/src/libutil/args.hh @@ -29,15 +29,18 @@ protected: /* Flags. */ struct Flag { - char shortName; + typedef std::shared_ptr<Flag> ptr; + std::string longName; + char shortName = 0; std::string description; Strings labels; - size_t arity; + size_t arity = 0; std::function<void(Strings)> handler; + std::string category; }; - std::map<std::string, Flag> longFlags; - std::map<char, Flag> shortFlags; + std::map<std::string, Flag::ptr> longFlags; + std::map<char, Flag::ptr> shortFlags; virtual bool processFlag(Strings::iterator & pos, Strings::iterator end); @@ -55,33 +58,53 @@ protected: virtual bool processArgs(const Strings & args, bool finish); + std::set<std::string> hiddenCategories; + public: + class FlagMaker + { + Args & args; + Flag::ptr flag; + friend class Args; + FlagMaker(Args & args) : args(args), flag(std::make_shared<Flag>()) { }; + public: + ~FlagMaker(); + FlagMaker & longName(const std::string & s) { flag->longName = s; return *this; }; + FlagMaker & shortName(char s) { flag->shortName = s; return *this; }; + FlagMaker & description(const std::string & s) { flag->description = s; return *this; }; + FlagMaker & labels(const Strings & ls) { flag->labels = ls; return *this; }; + FlagMaker & arity(size_t arity) { flag->arity = arity; return *this; }; + FlagMaker & handler(std::function<void(Strings)> handler) { flag->handler = handler; return *this; }; + FlagMaker & category(const std::string & s) { flag->category = s; return *this; }; + }; + + FlagMaker mkFlag(); + /* Helper functions for constructing flags / positional arguments. */ void mkFlag(char shortName, const std::string & longName, - const Strings & labels, const std::string & description, - size_t arity, std::function<void(Strings)> handler) - { - auto flag = Flag{shortName, description, labels, arity, handler}; - if (shortName) shortFlags[shortName] = flag; - longFlags[longName] = flag; - } - - void mkFlag(char shortName, const std::string & longName, const std::string & description, std::function<void()> fun) { - mkFlag(shortName, longName, {}, description, 0, std::bind(fun)); + mkFlag() + .shortName(shortName) + .longName(longName) + .description(description) + .handler(std::bind(fun)); } void mkFlag1(char shortName, const std::string & longName, const std::string & label, const std::string & description, std::function<void(std::string)> fun) { - mkFlag(shortName, longName, {label}, description, 1, [=](Strings ss) { - fun(ss.front()); - }); + mkFlag() + .shortName(shortName) + .longName(longName) + .labels({label}) + .description(description) + .arity(1) + .handler([=](Strings ss) { fun(ss.front()); }); } void mkFlag(char shortName, const std::string & name, @@ -105,9 +128,11 @@ public: void mkFlag(char shortName, const std::string & longName, const std::string & description, T * dest, const T & value) { - mkFlag(shortName, longName, {}, description, 0, [=](Strings ss) { - *dest = value; - }); + mkFlag() + .shortName(shortName) + .longName(longName) + .description(description) + .handler([=](Strings ss) { *dest = value; }); } template<class I> @@ -123,12 +148,18 @@ public: void mkFlag(char shortName, const std::string & longName, const std::string & description, std::function<void(I)> fun) { - mkFlag(shortName, longName, {"N"}, description, 1, [=](Strings ss) { - I n; - if (!string2Int(ss.front(), n)) - throw UsageError(format("flag ‘--%1%’ requires a integer argument") % longName); - fun(n); - }); + mkFlag() + .shortName(shortName) + .longName(longName) + .labels({"N"}) + .description(description) + .arity(1) + .handler([=](Strings ss) { + I n; + if (!string2Int(ss.front(), n)) + throw UsageError(format("flag ‘--%1%’ requires a integer argument") % longName); + fun(n); + }); } /* Expect a string argument. */ diff --git a/src/libutil/config.cc b/src/libutil/config.cc index 612fb6e68..0682bcd5d 100644 --- a/src/libutil/config.cc +++ b/src/libutil/config.cc @@ -115,11 +115,11 @@ void Config::toJSON(JSONObject & out) } } -void Config::convertToArgs(Args & args) +void Config::convertToArgs(Args & args, const std::string & category) { for (auto & s : _settings) if (!s.second.isAlias) - s.second.setting->convertToArg(args); + s.second.setting->convertToArg(args, category); } AbstractSetting::AbstractSetting( @@ -135,7 +135,7 @@ void AbstractSetting::toJSON(JSONPlaceholder & out) out.write(to_string()); } -void AbstractSetting::convertToArg(Args & args) +void AbstractSetting::convertToArg(Args & args, const std::string & category) { } @@ -146,9 +146,14 @@ void BaseSetting<T>::toJSON(JSONPlaceholder & out) } template<typename T> -void BaseSetting<T>::convertToArg(Args & args) +void BaseSetting<T>::convertToArg(Args & args, const std::string & category) { - args.mkFlag(0, name, {}, description, 1, [=](Strings ss) { set(*ss.begin()); }); + args.mkFlag() + .longName(name) + .description(description) + .arity(1) + .handler([=](Strings ss) { set(*ss.begin()); }) + .category(category); } template<> void BaseSetting<std::string>::set(const std::string & str) @@ -191,10 +196,18 @@ template<> std::string BaseSetting<bool>::to_string() return value ? "true" : "false"; } -template<> void BaseSetting<bool>::convertToArg(Args & args) +template<> void BaseSetting<bool>::convertToArg(Args & args, const std::string & category) { - args.mkFlag(0, name, {}, description, 0, [=](Strings ss) { value = true; }); - args.mkFlag(0, "no-" + name, {}, description, 0, [=](Strings ss) { value = false; }); + args.mkFlag() + .longName(name) + .description(description) + .handler([=](Strings ss) { value = true; }) + .category(category); + args.mkFlag() + .longName("no-" + name) + .description(description) + .handler([=](Strings ss) { value = false; }) + .category(category); } template<> void BaseSetting<Strings>::set(const std::string & str) diff --git a/src/libutil/config.hh b/src/libutil/config.hh index 994eab911..99850c1cd 100644 --- a/src/libutil/config.hh +++ b/src/libutil/config.hh @@ -72,7 +72,7 @@ public: void toJSON(JSONObject & out); - void convertToArgs(Args & args); + void convertToArgs(Args & args, const std::string & category); }; class AbstractSetting @@ -109,7 +109,7 @@ protected: virtual void toJSON(JSONPlaceholder & out); - virtual void convertToArg(Args & args); + virtual void convertToArg(Args & args, const std::string & category); bool isOverriden() { return overriden; } }; @@ -144,7 +144,7 @@ public: std::string to_string() override; - void convertToArg(Args & args) override; + void convertToArg(Args & args, const std::string & category) override; void toJSON(JSONPlaceholder & out) override; }; |