Skip to content

Commit c24bf75

Browse files
dherrera-metahenryiii
authored andcommitted
[precompile] Split Formatter.hpp
1 parent 003e825 commit c24bf75

File tree

4 files changed

+304
-271
lines changed

4 files changed

+304
-271
lines changed

CLI11.hpp.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,6 @@ namespace {namespace} {{
7272

7373
{formatter_hpp}
7474

75+
{formatter_inl_hpp}
76+
7577
}} // namespace {namespace}

include/CLI/Formatter.hpp

Lines changed: 4 additions & 271 deletions
Original file line numberDiff line numberDiff line change
@@ -17,276 +17,9 @@
1717

1818
namespace CLI {
1919
// [CLI11:formatter_hpp:verbatim]
20-
21-
inline std::string
22-
Formatter::make_group(std::string group, bool is_positional, std::vector<const Option *> opts) const {
23-
std::stringstream out;
24-
25-
out << "\n" << group << ":\n";
26-
for(const Option *opt : opts) {
27-
out << make_option(opt, is_positional);
28-
}
29-
30-
return out.str();
31-
}
32-
33-
inline std::string Formatter::make_positionals(const App *app) const {
34-
std::vector<const Option *> opts =
35-
app->get_options([](const Option *opt) { return !opt->get_group().empty() && opt->get_positional(); });
36-
37-
if(opts.empty())
38-
return {};
39-
40-
return make_group(get_label("Positionals"), true, opts);
41-
}
42-
43-
inline std::string Formatter::make_groups(const App *app, AppFormatMode mode) const {
44-
std::stringstream out;
45-
std::vector<std::string> groups = app->get_groups();
46-
47-
// Options
48-
for(const std::string &group : groups) {
49-
std::vector<const Option *> opts = app->get_options([app, mode, &group](const Option *opt) {
50-
return opt->get_group() == group // Must be in the right group
51-
&& opt->nonpositional() // Must not be a positional
52-
&& (mode != AppFormatMode::Sub // If mode is Sub, then
53-
|| (app->get_help_ptr() != opt // Ignore help pointer
54-
&& app->get_help_all_ptr() != opt)); // Ignore help all pointer
55-
});
56-
if(!group.empty() && !opts.empty()) {
57-
out << make_group(group, false, opts);
58-
59-
if(group != groups.back())
60-
out << "\n";
61-
}
62-
}
63-
64-
return out.str();
65-
}
66-
67-
inline std::string Formatter::make_description(const App *app) const {
68-
std::string desc = app->get_description();
69-
auto min_options = app->get_require_option_min();
70-
auto max_options = app->get_require_option_max();
71-
if(app->get_required()) {
72-
desc += " REQUIRED ";
73-
}
74-
if((max_options == min_options) && (min_options > 0)) {
75-
if(min_options == 1) {
76-
desc += " \n[Exactly 1 of the following options is required]";
77-
} else {
78-
desc += " \n[Exactly " + std::to_string(min_options) + "options from the following list are required]";
79-
}
80-
} else if(max_options > 0) {
81-
if(min_options > 0) {
82-
desc += " \n[Between " + std::to_string(min_options) + " and " + std::to_string(max_options) +
83-
" of the follow options are required]";
84-
} else {
85-
desc += " \n[At most " + std::to_string(max_options) + " of the following options are allowed]";
86-
}
87-
} else if(min_options > 0) {
88-
desc += " \n[At least " + std::to_string(min_options) + " of the following options are required]";
89-
}
90-
return (!desc.empty()) ? desc + "\n" : std::string{};
91-
}
92-
93-
inline std::string Formatter::make_usage(const App *app, std::string name) const {
94-
std::stringstream out;
95-
96-
out << get_label("Usage") << ":" << (name.empty() ? "" : " ") << name;
97-
98-
std::vector<std::string> groups = app->get_groups();
99-
100-
// Print an Options badge if any options exist
101-
std::vector<const Option *> non_pos_options =
102-
app->get_options([](const Option *opt) { return opt->nonpositional(); });
103-
if(!non_pos_options.empty())
104-
out << " [" << get_label("OPTIONS") << "]";
105-
106-
// Positionals need to be listed here
107-
std::vector<const Option *> positionals = app->get_options([](const Option *opt) { return opt->get_positional(); });
108-
109-
// Print out positionals if any are left
110-
if(!positionals.empty()) {
111-
// Convert to help names
112-
std::vector<std::string> positional_names(positionals.size());
113-
std::transform(positionals.begin(), positionals.end(), positional_names.begin(), [this](const Option *opt) {
114-
return make_option_usage(opt);
115-
});
116-
117-
out << " " << detail::join(positional_names, " ");
118-
}
119-
120-
// Add a marker if subcommands are expected or optional
121-
if(!app->get_subcommands(
122-
[](const CLI::App *subc) { return ((!subc->get_disabled()) && (!subc->get_name().empty())); })
123-
.empty()) {
124-
out << " " << (app->get_require_subcommand_min() == 0 ? "[" : "")
125-
<< get_label(app->get_require_subcommand_max() < 2 || app->get_require_subcommand_min() > 1 ? "SUBCOMMAND"
126-
: "SUBCOMMANDS")
127-
<< (app->get_require_subcommand_min() == 0 ? "]" : "");
128-
}
129-
130-
out << std::endl;
131-
132-
return out.str();
133-
}
134-
135-
inline std::string Formatter::make_footer(const App *app) const {
136-
std::string footer = app->get_footer();
137-
if(footer.empty()) {
138-
return std::string{};
139-
}
140-
return footer + "\n";
141-
}
142-
143-
inline std::string Formatter::make_help(const App *app, std::string name, AppFormatMode mode) const {
144-
145-
// This immediately forwards to the make_expanded method. This is done this way so that subcommands can
146-
// have overridden formatters
147-
if(mode == AppFormatMode::Sub)
148-
return make_expanded(app);
149-
150-
std::stringstream out;
151-
if((app->get_name().empty()) && (app->get_parent() != nullptr)) {
152-
if(app->get_group() != "Subcommands") {
153-
out << app->get_group() << ':';
154-
}
155-
}
156-
157-
out << make_description(app);
158-
out << make_usage(app, name);
159-
out << make_positionals(app);
160-
out << make_groups(app, mode);
161-
out << make_subcommands(app, mode);
162-
out << '\n' << make_footer(app);
163-
164-
return out.str();
165-
}
166-
167-
inline std::string Formatter::make_subcommands(const App *app, AppFormatMode mode) const {
168-
std::stringstream out;
169-
170-
std::vector<const App *> subcommands = app->get_subcommands({});
171-
172-
// Make a list in definition order of the groups seen
173-
std::vector<std::string> subcmd_groups_seen;
174-
for(const App *com : subcommands) {
175-
if(com->get_name().empty()) {
176-
if(!com->get_group().empty()) {
177-
out << make_expanded(com);
178-
}
179-
continue;
180-
}
181-
std::string group_key = com->get_group();
182-
if(!group_key.empty() &&
183-
std::find_if(subcmd_groups_seen.begin(), subcmd_groups_seen.end(), [&group_key](std::string a) {
184-
return detail::to_lower(a) == detail::to_lower(group_key);
185-
}) == subcmd_groups_seen.end())
186-
subcmd_groups_seen.push_back(group_key);
187-
}
188-
189-
// For each group, filter out and print subcommands
190-
for(const std::string &group : subcmd_groups_seen) {
191-
out << "\n" << group << ":\n";
192-
std::vector<const App *> subcommands_group = app->get_subcommands(
193-
[&group](const App *sub_app) { return detail::to_lower(sub_app->get_group()) == detail::to_lower(group); });
194-
for(const App *new_com : subcommands_group) {
195-
if(new_com->get_name().empty())
196-
continue;
197-
if(mode != AppFormatMode::All) {
198-
out << make_subcommand(new_com);
199-
} else {
200-
out << new_com->help(new_com->get_name(), AppFormatMode::Sub);
201-
out << "\n";
202-
}
203-
}
204-
}
205-
206-
return out.str();
207-
}
208-
209-
inline std::string Formatter::make_subcommand(const App *sub) const {
210-
std::stringstream out;
211-
detail::format_help(out, sub->get_display_name(true), sub->get_description(), column_width_);
212-
return out.str();
213-
}
214-
215-
inline std::string Formatter::make_expanded(const App *sub) const {
216-
std::stringstream out;
217-
out << sub->get_display_name(true) << "\n";
218-
219-
out << make_description(sub);
220-
if(sub->get_name().empty() && !sub->get_aliases().empty()) {
221-
detail::format_aliases(out, sub->get_aliases(), column_width_ + 2);
222-
}
223-
out << make_positionals(sub);
224-
out << make_groups(sub, AppFormatMode::Sub);
225-
out << make_subcommands(sub, AppFormatMode::Sub);
226-
227-
// Drop blank spaces
228-
std::string tmp = detail::find_and_replace(out.str(), "\n\n", "\n");
229-
tmp = tmp.substr(0, tmp.size() - 1); // Remove the final '\n'
230-
231-
// Indent all but the first line (the name)
232-
return detail::find_and_replace(tmp, "\n", "\n ") + "\n";
233-
}
234-
235-
inline std::string Formatter::make_option_name(const Option *opt, bool is_positional) const {
236-
if(is_positional)
237-
return opt->get_name(true, false);
238-
239-
return opt->get_name(false, true);
240-
}
241-
242-
inline std::string Formatter::make_option_opts(const Option *opt) const {
243-
std::stringstream out;
244-
245-
if(!opt->get_option_text().empty()) {
246-
out << " " << opt->get_option_text();
247-
} else {
248-
if(opt->get_type_size() != 0) {
249-
if(!opt->get_type_name().empty())
250-
out << " " << get_label(opt->get_type_name());
251-
if(!opt->get_default_str().empty())
252-
out << " [" << opt->get_default_str() << "] ";
253-
if(opt->get_expected_max() == detail::expected_max_vector_size)
254-
out << " ...";
255-
else if(opt->get_expected_min() > 1)
256-
out << " x " << opt->get_expected();
257-
258-
if(opt->get_required())
259-
out << " " << get_label("REQUIRED");
260-
}
261-
if(!opt->get_envname().empty())
262-
out << " (" << get_label("Env") << ":" << opt->get_envname() << ")";
263-
if(!opt->get_needs().empty()) {
264-
out << " " << get_label("Needs") << ":";
265-
for(const Option *op : opt->get_needs())
266-
out << " " << op->get_name();
267-
}
268-
if(!opt->get_excludes().empty()) {
269-
out << " " << get_label("Excludes") << ":";
270-
for(const Option *op : opt->get_excludes())
271-
out << " " << op->get_name();
272-
}
273-
}
274-
return out.str();
275-
}
276-
277-
inline std::string Formatter::make_option_desc(const Option *opt) const { return opt->get_description(); }
278-
279-
inline std::string Formatter::make_option_usage(const Option *opt) const {
280-
// Note that these are positionals usages
281-
std::stringstream out;
282-
out << make_option_name(opt, true);
283-
if(opt->get_expected_max() >= detail::expected_max_vector_size)
284-
out << "...";
285-
else if(opt->get_expected_max() > 1)
286-
out << "(" << opt->get_expected() << "x)";
287-
288-
return opt->get_required() ? out.str() : "[" + out.str() + "]";
289-
}
290-
29120
// [CLI11:formatter_hpp:end]
29221
} // namespace CLI
22+
23+
#ifndef CLI11_COMPILE
24+
#include "impl/Formatter_inl.hpp"
25+
#endif

0 commit comments

Comments
 (0)