-
Notifications
You must be signed in to change notification settings - Fork 362
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
148 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
#include <CLI/CLI.hpp> | ||
#include <nlohmann/json.hpp> | ||
|
||
// This example is only built on GCC 7 on Travis due to mismatch in stdlib | ||
// for clang (CLI11 is forgiving about mismatches, json.hpp is not) | ||
|
||
using nlohmann::json; | ||
|
||
class ConfigJSON : public CLI::Config { | ||
public: | ||
std::string to_config(const CLI::App *app, bool default_also, bool, std::string) const override { | ||
|
||
json j; | ||
|
||
for(const CLI::Option *opt : app->get_options({})) { | ||
|
||
// Only process option with a long-name and configurable | ||
if(!opt->get_lnames().empty() && opt->get_configurable()) { | ||
std::string name = opt->get_lnames()[0]; | ||
|
||
// Non-flags | ||
if(opt->get_type_size() != 0) { | ||
|
||
// If the option was found on command line | ||
if(opt->count() == 1) | ||
j[name] = opt->results().at(0); | ||
else if(opt->count() > 1) | ||
j[name] = opt->results(); | ||
|
||
// If the option has a default and is requested by optional argument | ||
else if(default_also && !opt->get_defaultval().empty()) | ||
j[name] = opt->get_defaultval(); | ||
|
||
// Flag, one passed | ||
} else if(opt->count() == 1) { | ||
j[name] = true; | ||
|
||
// Flag, multiple passed | ||
} else if(opt->count() > 1) { | ||
j[name] = opt->count(); | ||
|
||
// Flag, not present | ||
} else if(opt->count() == 0 && default_also) { | ||
j[name] = false; | ||
} | ||
} | ||
} | ||
|
||
for(const CLI::App *subcom : app->get_subcommands({})) | ||
j[subcom->get_name()] = json(to_config(subcom, default_also, false, "")); | ||
|
||
return j.dump(4); | ||
} | ||
|
||
std::vector<CLI::ConfigItem> from_config(std::istream &input) const override { | ||
json j; | ||
input >> j; | ||
return _from_config(j); | ||
} | ||
|
||
std::vector<CLI::ConfigItem> | ||
_from_config(json j, std::string name = "", std::vector<std::string> prefix = {}) const { | ||
std::vector<CLI::ConfigItem> results; | ||
|
||
if(j.is_object()) { | ||
for(json::iterator item = j.begin(); item != j.end(); ++item) { | ||
auto copy_prefix = prefix; | ||
if(!name.empty()) | ||
copy_prefix.push_back(name); | ||
auto sub_results = _from_config(*item, item.key(), copy_prefix); | ||
results.insert(results.end(), sub_results.begin(), sub_results.end()); | ||
} | ||
} else if(!name.empty()) { | ||
results.emplace_back(); | ||
CLI::ConfigItem &res = results.back(); | ||
res.name = name; | ||
res.parents = prefix; | ||
if(j.is_boolean()) { | ||
res.inputs = {j.get<bool>() ? "true" : "false"}; | ||
} else if(j.is_number()) { | ||
std::stringstream ss; | ||
ss << j.get<double>(); | ||
res.inputs = {ss.str()}; | ||
} else if(j.is_string()) { | ||
res.inputs = {j.get<std::string>()}; | ||
} else if(j.is_array()) { | ||
for(std::string ival : j) | ||
res.inputs.push_back(ival); | ||
} else { | ||
throw CLI::ConversionError("Failed to convert " + name); | ||
} | ||
} else { | ||
throw CLI::ConversionError("You must make all top level values objects in json!"); | ||
} | ||
|
||
return results; | ||
} | ||
}; | ||
|
||
int main(int argc, char **argv) { | ||
CLI::App app; | ||
app.config_formatter(std::make_shared<ConfigJSON>()); | ||
|
||
int item; | ||
|
||
app.add_flag("--simple"); | ||
app.add_option("--item", item); | ||
app.set_config("--config"); | ||
|
||
CLI11_PARSE(app, argc, argv); | ||
|
||
std::cout << app.config_to_str(true, true) << std::endl; | ||
} |