26inline std::string
convert_arg_for_ini(
const std::string &arg,
char stringQuote =
'"',
char characterQuote =
'\'') {
28 return std::string(2, stringQuote);
31 if(arg ==
"true" || arg ==
"false" || arg ==
"nan" || arg ==
"inf") {
35 if(arg.compare(0, 2,
"0x") != 0 && arg.compare(0, 2,
"0X") != 0) {
43 return std::string(1, characterQuote) + arg + characterQuote;
46 if(arg.front() ==
'0') {
48 if(std::all_of(arg.begin() + 2, arg.end(), [](
char x) {
49 return (x >=
'0' && x <=
'9') || (x >=
'A' && x <=
'F') || (x >=
'a' && x <=
'f');
53 }
else if(arg[1] ==
'o') {
54 if(std::all_of(arg.begin() + 2, arg.end(), [](
char x) { return (x >=
'0' && x <=
'7'); })) {
57 }
else if(arg[1] ==
'b') {
58 if(std::all_of(arg.begin() + 2, arg.end(), [](
char x) { return (x ==
'0' || x ==
'1'); })) {
63 if(arg.find_first_of(stringQuote) == std::string::npos) {
64 return std::string(1, stringQuote) + arg + stringQuote;
66 return characterQuote + arg + characterQuote;
71inline std::string
ini_join(
const std::vector<std::string> &args,
73 char arrayStart =
'[',
75 char stringQuote =
'"',
76 char characterQuote =
'\'') {
78 if(args.size() > 1 && arrayStart !=
'\0') {
79 joined.push_back(arrayStart);
81 std::size_t start = 0;
82 for(
const auto &arg : args) {
84 joined.push_back(sepChar);
85 if(isspace(sepChar) == 0) {
86 joined.push_back(
' ');
91 if(args.size() > 1 && arrayEnd !=
'\0') {
92 joined.push_back(arrayEnd);
97inline std::vector<std::string>
generate_parents(
const std::string §ion, std::string &name,
char parentSeparator) {
98 std::vector<std::string> parents;
100 if(section.find(parentSeparator) != std::string::npos) {
106 if(name.find(parentSeparator) != std::string::npos) {
107 std::vector<std::string> plist =
detail::split(name, parentSeparator);
111 parents.insert(parents.end(), plist.begin(), plist.end());
115 for(
auto &parent : parents) {
128 std::size_t msize = (parents.size() > 1U) ? parents.size() : 2;
129 while(
output.back().parents.size() >= msize) {
131 output.back().parents.pop_back();
134 if(parents.size() > 1) {
135 std::size_t common = 0;
136 std::size_t mpair = (std::min)(
output.back().parents.size(), parents.size() - 1);
137 for(std::size_t ii = 0; ii < mpair; ++ii) {
138 if(
output.back().parents[ii] != parents[ii]) {
143 if(common == mpair) {
146 while(
output.back().parents.size() > common + 1) {
148 output.back().parents.pop_back();
151 for(std::size_t ii = common; ii < parents.size() - 1; ++ii) {
153 output.back().parents.assign(parents.begin(), parents.begin() +
static_cast<std::ptrdiff_t
>(ii) + 1);
154 output.back().name =
"++";
157 }
else if(parents.size() > 1) {
158 for(std::size_t ii = 0; ii < parents.size() - 1; ++ii) {
160 output.back().parents.assign(parents.begin(), parents.begin() +
static_cast<std::ptrdiff_t
>(ii) + 1);
161 output.back().name =
"++";
167 output.back().parents = std::move(parents);
168 output.back().name =
"++";
174 std::string currentSection =
"default";
175 std::string previousSection =
"default";
176 std::vector<ConfigItem> output;
179 bool inSection{
false};
180 char aStart = (isINIArray) ?
'[' :
arrayStart;
181 char aEnd = (isINIArray) ?
']' :
arrayEnd;
183 int currentSectionIndex{0};
184 while(getline(input, line)) {
185 std::vector<std::string> items_buffer;
189 std::size_t len = line.length();
194 if(line.front() ==
'[' && line.back() ==
']') {
195 if(currentSection !=
"default") {
197 output.emplace_back();
199 output.back().name =
"--";
201 currentSection = line.substr(1, len - 2);
203 if(currentSection.size() > 1 && currentSection.front() ==
'[' && currentSection.back() ==
']') {
204 currentSection = currentSection.substr(1, currentSection.size() - 2);
207 currentSection =
"default";
212 if(currentSection == previousSection) {
213 ++currentSectionIndex;
215 currentSectionIndex = 0;
216 previousSection = currentSection;
222 if(line.front() ==
';' || line.front() ==
'#' || line.front() ==
commentChar) {
228 if(pos != std::string::npos) {
232 if(cloc != std::string::npos) {
233 item.erase(cloc, std::string::npos);
236 if(item.size() > 1 && item.front() == aStart) {
237 for(std::string multiline; item.back() != aEnd && std::getline(input, multiline);) {
241 items_buffer = detail::split_up(item.substr(1, item.length() - 2), aSep);
242 }
else if((isDefaultArray || isINIArray) && item.find_first_of(aSep) != std::string::npos) {
243 items_buffer = detail::split_up(item, aSep);
244 }
else if((isDefaultArray || isINIArray) && item.find_first_of(
' ') != std::string::npos) {
245 items_buffer = detail::split_up(item);
247 items_buffer = {item};
252 if(cloc != std::string::npos) {
253 name.erase(cloc, std::string::npos);
257 items_buffer = {
"true"};
263 for(
auto &it : items_buffer) {
278 parents.erase(parents.begin());
281 if(!output.empty() && name == output.back().name && parents == output.back().parents) {
282 output.back().inputs.insert(output.back().inputs.end(), items_buffer.begin(), items_buffer.end());
284 output.emplace_back();
285 output.back().parents = std::move(parents);
286 output.back().name = std::move(name);
287 output.back().inputs = std::move(items_buffer);
290 if(currentSection !=
"default") {
293 output.emplace_back();
295 output.back().name =
"--";
296 while(output.back().parents.size() > 1) {
297 output.push_back(output.back());
298 output.back().parents.pop_back();
306 std::stringstream out;
307 std::string commentLead;
309 commentLead.push_back(
' ');
311 std::vector<std::string> groups = app->
get_groups();
312 bool defaultUsed =
false;
313 groups.insert(groups.begin(), std::string(
"Options"));
317 for(
auto &group : groups) {
318 if(group ==
"Options" || group.empty()) {
324 if(write_description && group !=
"Options" && !group.empty()) {
325 out <<
'\n' << commentLead << group <<
" Options\n";
330 if(opt->get_configurable()) {
331 if(opt->get_group() != group) {
332 if(!(group ==
"Options" && opt->get_group().empty())) {
336 std::string name = prefix + opt->get_single_name();
340 if(value.empty() && default_also) {
341 if(!opt->get_default_str().empty()) {
343 }
else if(opt->get_expected_min() == 0) {
345 }
else if(opt->get_run_callback_for_default()) {
351 if(write_description && opt->has_description()) {
361 for(
const App *subcom : subcommands) {
362 if(subcom->get_name().empty()) {
363 if(write_description && !subcom->get_group().empty()) {
364 out <<
'\n' << commentLead << subcom->get_group() <<
" Options\n";
366 out <<
to_config(subcom, default_also, write_description, prefix);
370 for(
const App *subcom : subcommands) {
371 if(!subcom->get_name().empty()) {
373 if(!prefix.empty() || app->
get_parent() ==
nullptr) {
374 out <<
'[' << prefix << subcom->get_name() <<
"]\n";
378 while(p->get_parent() !=
nullptr) {
382 out <<
'[' << subname <<
"]\n";
384 out <<
to_config(subcom, default_also, write_description,
"");
387 subcom, default_also, write_description, prefix + subcom->get_name() +
parentSeparatorChar);
Creates a command line program, with very few defaults.
Definition App.hpp:85
bool get_configurable() const
Check the status of the allow windows style options.
Definition App.hpp:1677
App * get_parent()
Get the parent of this subcommand (or nullptr if main app)
Definition App.hpp:1750
std::vector< App * > get_subcommands() const
Definition App.hpp:1352
std::vector< const Option * > get_options(const std::function< bool(const Option *)> filter={}) const
Get the list of options (user facing function, so returns raw pointers), has optional filter function...
Definition App.hpp:1567
std::string get_description() const
Get the app or subcommand description.
Definition App.hpp:1558
bool got_subcommand(const App *subcom) const
Check to see if given subcommand was selected.
Definition App.hpp:1390
const std::string & get_name() const
Get the name of the current app.
Definition App.hpp:1756
std::vector< std::string > get_groups() const
Get the groups available directly from this option (in order)
Definition App.hpp:1814
std::vector< ConfigItem > from_config(std::istream &input) const override
Convert a configuration into an app.
Definition Config.hpp:172
std::string configSection
Specify the configuration section that should be used.
Definition ConfigFwd.hpp:104
char arraySeparator
the character used to separate elements in an array
Definition ConfigFwd.hpp:90
std::string to_config(const App *, bool default_also, bool write_description, std::string prefix) const override
Convert an app into a configuration.
Definition Config.hpp:305
char characterQuote
the character to use around single characters
Definition ConfigFwd.hpp:96
char stringQuote
the character to use around strings
Definition ConfigFwd.hpp:94
uint8_t maximumLayers
the maximum number of layers to allow
Definition ConfigFwd.hpp:98
char valueDelimiter
the character used separate the name from the value
Definition ConfigFwd.hpp:92
char arrayStart
the character used to start an array '\0' is a default to not use
Definition ConfigFwd.hpp:86
char parentSeparatorChar
the separator used to separator parent layers
Definition ConfigFwd.hpp:100
char arrayEnd
the character used to end an array '\0' is a default to not use
Definition ConfigFwd.hpp:88
int16_t configIndex
Specify the configuration index to use for arrayed sections.
Definition ConfigFwd.hpp:102
char commentChar
the character used for comments
Definition ConfigFwd.hpp:84
Definition Option.hpp:238
std::string & remove_quotes(std::string &str)
remove quotes at the front and back of a string either '"' or '\''
Definition StringTools.hpp:150
std::string ini_join(const std::vector< std::string > &args, char sepChar=',', char arrayStart='[', char arrayEnd=']', char stringQuote='"', char characterQuote = '\'')
Comma separated join, adds quotes if needed.
Definition Config.hpp:71
std::vector< std::string > output
Definition StringTools.hpp:354
std::string convert_arg_for_ini(const std::string &arg, char stringQuote='"', char characterQuote = '\'')
Definition Config.hpp:26
std::string trim_copy(const std::string &str)
Make a copy of the string and then trim it.
Definition StringTools.hpp:144
std::string & trim(std::string &str)
Trim whitespace from string.
Definition StringTools.hpp:138
std::string fix_newlines(const std::string &leader, std::string input)
Definition StringTools.hpp:164
std::vector< std::string > generate_parents(const std::string §ion, std::string &name, char parentSeparator)
Definition Config.hpp:97
std::vector< std::string > split(const std::string &s, char delim)
Split a string by a delim.
Definition StringTools.hpp:46
std::string to_lower(std::string str)
Return a lower case version of a string.
Definition StringTools.hpp:259
bool lexical_cast(const std::string &input, T &output)
Integer conversion.
Definition TypeTools.hpp:883
void checkParentSegments(std::vector< ConfigItem > &output, const std::string ¤tSection, char parentSeparator)
assuming non default segments do a check on the close and open of the segments in a configItem struct...
Definition Config.hpp:123