39void GOption::set_scalar_value(
const string& v) {
40 if (v.empty())
return;
46 auto key = value.begin()->first.as<
string>();
47 value[key] = value_to_set;
57void GOption::set_value(
const YAML::Node& v) {
60 for (
const auto& element : v) {
61 if (!does_the_option_set_all_necessary_values(element)) {
63 <<
" but missing mandatory values." << endl;
64 cerr <<
" Use the option: " <<
YELLOWHHL <<
" help " << name
65 <<
" " <<
RSTHHR <<
" for details." << endl << endl;
75 auto default_value_node = defaultValue.begin()->second;
77 for (
const auto& map_element_in_default_value : default_value_node) {
78 for (
auto default_value_iterator = map_element_in_default_value.begin();
79 default_value_iterator != map_element_in_default_value.end(); ++default_value_iterator) {
80 auto default_key = default_value_iterator->first.as<
string>();
81 auto default_value = default_value_iterator->second;
84 for (
auto map_element_in_value : value[name]) {
85 bool key_found =
false;
87 for (
auto value_iterator = map_element_in_value.begin();
88 value_iterator != map_element_in_value.end(); ++value_iterator) {
89 auto value_key = value_iterator->first.as<
string>();
90 if (default_key == value_key) {
97 map_element_in_value[default_key] = default_value;
106 const auto update_existing_value = [
this](
const YAML::Node& desired_key,
const YAML::Node& desired_value) {
107 for (
auto existing_map : value[name]) {
108 for (
auto existing_map_iterator = existing_map.begin();
109 existing_map_iterator != existing_map.end(); ++existing_map_iterator) {
110 auto first_key = existing_map_iterator->first.as<
string>();
111 auto second_key = desired_key.as<
string>();
114 if (first_key == second_key) {
115 existing_map[existing_map_iterator->first] = desired_value;
122 for (
auto desired_value_iterator = v.begin();
123 desired_value_iterator != v.end(); ++desired_value_iterator) {
124 update_existing_value(desired_value_iterator->first, desired_value_iterator->second);
128 for (
const auto& map_element_in_desired_value : v) {
129 for (
auto desired_value_iterator = map_element_in_desired_value.begin();
130 desired_value_iterator != map_element_in_desired_value.end(); ++desired_value_iterator) {
131 update_existing_value(desired_value_iterator->first, desired_value_iterator->second);
144bool GOption::does_the_option_set_all_necessary_values(
const YAML::Node& v) {
145 vector<string> this_keys;
146 if (v.Type() == YAML::NodeType::Map) {
147 for (
const auto& it : v) {
148 this_keys.push_back(it.first.as<
string>());
152 for (
const auto& key : mandatory_keys) {
153 if (find(this_keys.begin(), this_keys.end(), key) == this_keys.end()) {
166void GOption::saveOption(std::ofstream* yamlConf)
const {
167 std::vector<std::string> missing;
172 std::function<YAML::Node(YAML::Node, std::string)> clean =
173 [&](YAML::Node n,
const std::string& path) -> YAML::Node {
175 missing.push_back(path.empty() ? name : path);
176 return YAML::Node(
"not provided");
180 YAML::Node res(YAML::NodeType::Map);
182 const std::string key = it.first.as<std::string>();
183 res[it.first] = clean(it.second, path.empty() ? key : path +
"." + key);
188 if (n.IsSequence()) {
189 YAML::Node res(YAML::NodeType::Sequence);
190 for (std::size_t i = 0; i < n.size(); ++i) {
191 res.push_back(clean(n[i], path +
"[" + std::to_string(i) +
"]"));
199 YAML::Node out = clean(value,
"");
204 for (
const auto& p : missing) {
205 *yamlConf <<
"# " << p <<
" not provided\n";
209 out.SetStyle(YAML::EmitterStyle::Block);
210 *yamlConf << out <<
'\n';
220void GOption::printHelp(
bool detailed)
const {
226 string helpString =
"-" + name +
RST;
227 bool is_sequence = defaultValue.begin()->second.IsSequence();
228 helpString += is_sequence ?
"=<sequence>" :
"=<value>";
231 cout <<
KGRN <<
" " << left;
232 cout.width(fill_width);
235 cout << helpString <<
": " << description << endl << endl;
236 cout << detailedHelp() << endl;
239 cout << helpString <<
": " << description << endl;
249string GOption::detailedHelp()
const {
251 YAML::Node yvalues = defaultValue.begin()->second;
253 if (yvalues.IsSequence()) {
256 for (
unsigned i = 0; i < yvalues.size(); i++) {
257 YAML::Node this_node = yvalues[i];
259 for (
auto it = this_node.begin(); it != this_node.end(); ++it) {
261 <<
": " << gvar_descs[i] <<
"Default value: " << it->second.as<
string>() << endl;
268 for (
const auto& line : help_lines) {
283 YAML::Node option_node = value.begin()->second;
285 if (option_node.IsSequence()) {
286 bool updated =
false;
288 for (
auto it = option_node.begin(); it != option_node.end(); ++it) {
290 if ((*it).IsMap() && (*it)[subkey]) {
291 (*it)[subkey] = YAML::Load(subvalue);
297 cerr <<
"Sub-option key '" << subkey <<
"' not found in option '" << name <<
"'." << endl;
301 else if (option_node.IsMap()) {
302 if (option_node[subkey]) {
303 option_node[subkey] = YAML::Load(subvalue);
306 cerr <<
"Sub-option key '" << subkey <<
"' not found in option '" << name <<
"'." << endl;
311 cerr <<
"Option '" << name <<
"' is not structured to accept sub–options." << endl;
void set_sub_option_value(const std::string &subkey, const std::string &subvalue)
Updates a structured sub-option using dot-notation semantics.
Definitions of GVariable : and GOption : used by GOptions : .
Conventions, constants, and error codes for the GOptions : / GOption : subsystem.
#define EC__NOOPTIONFOUND
Option/switch/key not found, or invalid command-line token.
#define HELPFILLSPACE
Padding used when printing option/switch help.
#define GVERSION_STRING
Reserved option tag used to store version information.
#define EC__MANDATORY_NOT_FILLED
Mandatory structured option key (NODFLT) missing.
vector< string > getStringVectorFromStringWithDelimiter(const string &input, const string &x)
string replaceCharInStringWithChars(const std::string &input, const std::string &toReplace, const std::string &replacement)