12#include "../Formatter.hpp"
23CLI11_INLINE std::string
25 std::stringstream out;
27 out <<
"\n" << group <<
":\n";
28 for(
const Option *opt : opts) {
36 std::vector<const Option *> opts =
37 app->get_options([](
const Option *opt) {
return !opt->get_group().empty() && opt->get_positional(); });
46 std::stringstream out;
47 std::vector<std::string> groups = app->get_groups();
50 for(
const std::string &group : groups) {
51 std::vector<const Option *> opts = app->get_options([app, mode, &group](
const Option *opt) {
52 return opt->get_group() == group
53 && opt->nonpositional()
54 && (mode != AppFormatMode::Sub
55 || (app->get_help_ptr() != opt
56 && app->get_help_all_ptr() != opt));
58 if(!group.empty() && !opts.empty()) {
71 std::string desc = app->get_description();
72 auto min_options = app->get_require_option_min();
73 auto max_options = app->get_require_option_max();
75 if(app->get_required()) {
76 desc +=
" " +
get_label(
"REQUIRED") +
" ";
80 if(max_options == min_options) {
81 desc +=
" \n[Exactly " + std::to_string(min_options) +
" of the following options are required]";
82 }
else if(max_options > 0) {
83 desc +=
" \n[Between " + std::to_string(min_options) +
" and " + std::to_string(max_options) +
84 " of the following options are required]";
86 desc +=
" \n[At least " + std::to_string(min_options) +
" of the following options are required]";
88 }
else if(max_options > 0) {
89 desc +=
" \n[At most " + std::to_string(max_options) +
" of the following options are allowed]";
92 return (!desc.empty()) ? desc +
"\n" : std::string{};
96 std::string usage = app->get_usage();
98 return usage +
"\n\n";
101 std::stringstream out;
109 std::vector<std::string> groups = app->get_groups();
112 std::vector<const Option *> non_pos_options =
113 app->get_options([](
const Option *opt) {
return opt->nonpositional(); });
114 if(!non_pos_options.empty())
115 out <<
" [" <<
get_label(
"OPTIONS") <<
"]";
118 std::vector<const Option *> positionals = app->get_options([](
const Option *opt) {
return opt->get_positional(); });
121 if(!positionals.empty()) {
123 std::vector<std::string> positional_names(positionals.size());
124 std::transform(positionals.begin(), positionals.end(), positional_names.begin(), [
this](
const Option *opt) {
125 return make_option_usage(opt);
128 out <<
" " << detail::join(positional_names,
" ");
132 if(!app->get_subcommands(
133 [](
const CLI::App *subc) { return ((!subc->get_disabled()) && (!subc->get_name().empty())); })
135 out <<
' ' << (app->get_require_subcommand_min() == 0 ?
"[" :
"")
136 <<
get_label(app->get_require_subcommand_max() < 2 || app->get_require_subcommand_min() > 1 ?
"SUBCOMMAND"
138 << (app->get_require_subcommand_min() == 0 ?
"]" :
"");
147 std::string footer = app->get_footer();
149 return std::string{};
151 return '\n' + footer +
"\n\n";
157 if(mode == AppFormatMode::Sub)
160 std::stringstream out;
161 if((app->get_name().empty()) && (app->get_parent() !=
nullptr)) {
162 if(app->get_group() !=
"SUBCOMMANDS") {
163 out << app->get_group() <<
':';
168 detail::streamOutAsParagraph(
179 std::stringstream out;
181 std::vector<const App *> subcommands = app->get_subcommands({});
184 std::vector<std::string> subcmd_groups_seen;
185 for(
const App *com : subcommands) {
186 if(com->get_name().empty()) {
187 if(!com->get_group().empty() && com->get_group().front() !=
'+') {
192 std::string group_key = com->get_group();
193 if(!group_key.empty() &&
194 std::find_if(subcmd_groups_seen.begin(), subcmd_groups_seen.end(), [&group_key](std::string a) {
195 return detail::to_lower(a) == detail::to_lower(group_key);
196 }) == subcmd_groups_seen.end())
197 subcmd_groups_seen.push_back(group_key);
201 for(
const std::string &group : subcmd_groups_seen) {
202 out <<
'\n' << group <<
":\n";
203 std::vector<const App *> subcommands_group = app->get_subcommands(
204 [&group](
const App *sub_app) {
return detail::to_lower(sub_app->get_group()) == detail::to_lower(group); });
205 for(
const App *new_com : subcommands_group) {
206 if(new_com->get_name().empty())
208 if(mode != AppFormatMode::All) {
211 out << new_com->help(new_com->get_name(), AppFormatMode::Sub);
221 std::stringstream out;
222 std::string name =
" " + sub->get_display_name(
true) + (sub->get_required() ?
" " +
get_label(
"REQUIRED") :
"");
224 out << std::setw(static_cast<int>(
column_width_)) << std::left << name;
225 detail::streamOutAsParagraph(
232 std::stringstream out;
233 out << sub->get_display_name(
true) <<
'\n';
235 detail::streamOutAsParagraph(
238 if(sub->get_name().empty() && !sub->get_aliases().empty()) {
239 detail::format_aliases(out, sub->get_aliases(),
column_width_ + 2);
252 std::stringstream out;
256 out << std::setw(static_cast<int>(
column_width_)) << std::left << left;
259 bool skipFirstLinePrefix =
true;
262 skipFirstLinePrefix =
false;
264 detail::streamOutAsParagraph(
273 const auto names = detail::split(namesCombined,
',');
274 std::vector<std::string> vshortNames;
275 std::vector<std::string> vlongNames;
276 std::for_each(names.begin(), names.end(), [&vshortNames, &vlongNames](
const std::string &name) {
277 if(name.find(
"--", 0) != std::string::npos)
278 vlongNames.push_back(name);
280 vshortNames.push_back(name);
284 std::string shortNames = detail::join(vshortNames,
", ");
285 std::string longNames = detail::join(vlongNames,
", ");
288 const auto shortNamesColumnWidth =
static_cast<int>(
column_width_ / 3);
289 const auto longNamesColumnWidth =
static_cast<int>(std::ceil(
291 int shortNamesOverSize = 0;
294 if(shortNames.length() > 0) {
295 shortNames =
" " + shortNames;
296 if(longNames.length() == 0 && opts.length() > 0)
298 if(longNames.length() > 0)
300 if(
static_cast<int>(shortNames.length()) >= shortNamesColumnWidth) {
302 shortNamesOverSize =
static_cast<int>(shortNames.length()) - shortNamesColumnWidth;
304 out << std::setw(shortNamesColumnWidth) << std::left << shortNames;
306 out << std::setw(shortNamesColumnWidth) << std::left <<
"";
311 (std::min)(shortNamesOverSize, longNamesColumnWidth);
312 const auto adjustedLongNamesColumnWidth = longNamesColumnWidth - shortNamesOverSize;
315 if(longNames.length() > 0) {
316 if(opts.length() > 0)
318 if(
static_cast<int>(longNames.length()) >= adjustedLongNamesColumnWidth)
321 out << std::setw(adjustedLongNamesColumnWidth) << std::left << longNames;
323 out << std::setw(adjustedLongNamesColumnWidth) << std::left <<
"";
327 bool skipFirstLinePrefix =
true;
330 skipFirstLinePrefix =
false;
332 detail::streamOutAsParagraph(
343 return opt->get_name(
true,
false);
345 return opt->get_name(
false,
true);
349 std::stringstream out;
351 if(!opt->get_option_text().empty()) {
352 out <<
" " << opt->get_option_text();
354 if(opt->get_type_size() != 0) {
355 if(!opt->get_type_name().empty())
356 out <<
" " <<
get_label(opt->get_type_name());
357 if(!opt->get_default_str().empty())
358 out <<
" [" << opt->get_default_str() <<
"] ";
359 if(opt->get_expected_max() == detail::expected_max_vector_size)
361 else if(opt->get_expected_min() > 1)
362 out <<
" x " << opt->get_expected();
364 if(opt->get_required())
367 if(!opt->get_envname().empty())
368 out <<
" (" <<
get_label(
"Env") <<
":" << opt->get_envname() <<
")";
369 if(!opt->get_needs().empty()) {
371 for(
const Option *op : opt->get_needs())
372 out <<
" " << op->get_name();
374 if(!opt->get_excludes().empty()) {
375 out <<
" " <<
get_label(
"Excludes") <<
":";
376 for(
const Option *op : opt->get_excludes())
377 out <<
" " << op->get_name();
387 std::stringstream out;
389 if(opt->get_expected_max() >= detail::expected_max_vector_size)
391 else if(opt->get_expected_max() > 1)
392 out <<
"(" << opt->get_expected() <<
"x)";
394 return opt->get_required() ? out.str() :
"[" + out.str() +
"]";
Creates a command line program, with very few defaults.
Definition App.hpp:90
Definition Option.hpp:231