Commit c24bf7541398ffeb68e7343154b93f9a630e2147

Authored by Daniel Herrera Castro
Committed by Henry Schreiner
1 parent 003e8257

[precompile] Split Formatter.hpp

CLI11.hpp.in
@@ -72,4 +72,6 @@ namespace {namespace} {{ @@ -72,4 +72,6 @@ namespace {namespace} {{
72 72
73 {formatter_hpp} 73 {formatter_hpp}
74 74
  75 +{formatter_inl_hpp}
  76 +
75 }} // namespace {namespace} 77 }} // namespace {namespace}
include/CLI/Formatter.hpp
@@ -17,276 +17,9 @@ @@ -17,276 +17,9 @@
17 17
18 namespace CLI { 18 namespace CLI {
19 // [CLI11:formatter_hpp:verbatim] 19 // [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 -  
291 // [CLI11:formatter_hpp:end] 20 // [CLI11:formatter_hpp:end]
292 } // namespace CLI 21 } // namespace CLI
  22 +
  23 +#ifndef CLI11_COMPILE
  24 +#include "impl/Formatter_inl.hpp"
  25 +#endif
include/CLI/impl/Formatter_inl.hpp 0 → 100644
  1 +// Copyright (c) 2017-2022, University of Cincinnati, developed by Henry Schreiner
  2 +// under NSF AWARD 1414736 and by the respective contributors.
  3 +// All rights reserved.
  4 +//
  5 +// SPDX-License-Identifier: BSD-3-Clause
  6 +
  7 +#pragma once
  8 +
  9 +// This include is only needed for IDEs to discover symbols
  10 +#include <CLI/Formatter.hpp>
  11 +
  12 +// [CLI11:public_includes:set]
  13 +#include <algorithm>
  14 +#include <string>
  15 +#include <utility>
  16 +#include <vector>
  17 +// [CLI11:public_includes:end]
  18 +
  19 +namespace CLI {
  20 +// [CLI11:formatter_inl_hpp:verbatim]
  21 +CLI11_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 +CLI11_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 +CLI11_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 +CLI11_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 +CLI11_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 +CLI11_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 +CLI11_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 +CLI11_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 +CLI11_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 +CLI11_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 +CLI11_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 +CLI11_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 +CLI11_INLINE std::string Formatter::make_option_desc(const Option *opt) const { return opt->get_description(); }
  278 +
  279 +CLI11_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 +// [CLI11:formatter_inl_hpp:end]
  291 +} // namespace CLI
src/Formatter.cpp 0 → 100644
  1 +// Copyright (c) 2017-2022, University of Cincinnati, developed by Henry Schreiner
  2 +// under NSF AWARD 1414736 and by the respective contributors.
  3 +// All rights reserved.
  4 +//
  5 +// SPDX-License-Identifier: BSD-3-Clause
  6 +
  7 +#include <CLI/impl/Formatter_inl.hpp>