add flags on the formatter to disable formatting (#1150)

add flags on the formatter to disable formatting for the description and
footer to allow things like word art or custom formatting.

One possible solution for #1145

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Philip Top
2025-05-19 05:25:00 -07:00
committed by GitHub
parent 1df96c852d
commit 2c787a50ed
3 changed files with 103 additions and 10 deletions

View File

@@ -56,6 +56,10 @@ class FormatterBase {
/// The width of the footer paragraph
std::size_t footer_paragraph_width_{80};
/// options controlling formatting for footer and descriptions
bool enable_description_formatting_{true};
bool enable_footer_formatting_{true};
/// @brief The required help printout labels (user changeable)
/// Values are Needs, Excludes, etc.
std::map<std::string, std::string> labels_{};
@@ -81,7 +85,7 @@ class FormatterBase {
/// @name Setters
///@{
/// Set the "REQUIRED" label
/// Set the "REQUIRED" or other labels
void label(std::string key, std::string val) { labels_[key] = val; }
/// Set the left column width (options/flags/subcommands)
@@ -95,7 +99,10 @@ class FormatterBase {
/// Set the footer paragraph width
void footer_paragraph_width(std::size_t val) { footer_paragraph_width_ = val; }
/// enable formatting for description paragraph
void enable_description_formatting(bool value = true) { enable_description_formatting_ = value; }
/// disable formatting for footer paragraph
void enable_footer_formatting(bool value = true) { enable_footer_formatting_ = value; }
///@}
/// @name Getters
///@{
@@ -119,6 +126,12 @@ class FormatterBase {
/// Get the current footer paragraph width
CLI11_NODISCARD std::size_t get_footer_paragraph_width() const { return footer_paragraph_width_; }
/// Get the current status of description paragraph formatting
CLI11_NODISCARD bool is_description_paragraph_formatting_enabled() const { return enable_description_formatting_; }
/// Get the current status of whether footer paragraph formatting is enabled
CLI11_NODISCARD bool is_footer_paragraph_formatting_enabled() const { return enable_footer_formatting_; }
///@}
};

View File

@@ -163,14 +163,21 @@ CLI11_INLINE std::string Formatter::make_help(const App *app, std::string name,
out << app->get_group() << ':';
}
}
detail::streamOutAsParagraph(
out, make_description(app), description_paragraph_width_, ""); // Format description as paragraph
if(is_description_paragraph_formatting_enabled()) {
detail::streamOutAsParagraph(
out, make_description(app), description_paragraph_width_, ""); // Format description as paragraph
} else {
out << make_description(app) << '\n';
}
out << make_usage(app, name);
out << make_positionals(app);
out << make_groups(app, mode);
out << make_subcommands(app, mode);
detail::streamOutAsParagraph(out, make_footer(app), footer_paragraph_width_); // Format footer as paragraph
if(is_footer_paragraph_formatting_enabled()) {
detail::streamOutAsParagraph(out, make_footer(app), footer_paragraph_width_); // Format footer as paragraph
} else {
out << make_footer(app) << '\n';
}
return out.str();
}
@@ -232,8 +239,12 @@ CLI11_INLINE std::string Formatter::make_expanded(const App *sub, AppFormatMode
std::stringstream out;
out << sub->get_display_name(true) << '\n';
detail::streamOutAsParagraph(
out, make_description(sub), description_paragraph_width_, " "); // Format description as paragraph
if(is_description_paragraph_formatting_enabled()) {
detail::streamOutAsParagraph(
out, make_description(sub), description_paragraph_width_, " "); // Format description as paragraph
} else {
out << make_description(sub) << '\n';
}
if(sub->get_name().empty() && !sub->get_aliases().empty()) {
detail::format_aliases(out, sub->get_aliases(), column_width_ + 2);
@@ -242,8 +253,11 @@ CLI11_INLINE std::string Formatter::make_expanded(const App *sub, AppFormatMode
out << make_positionals(sub);
out << make_groups(sub, mode);
out << make_subcommands(sub, mode);
detail::streamOutAsParagraph(out, make_footer(sub), footer_paragraph_width_); // Format footer as paragraph
if(is_footer_paragraph_formatting_enabled()) {
detail::streamOutAsParagraph(out, make_footer(sub), footer_paragraph_width_); // Format footer as paragraph
} else {
out << make_footer(sub) << '\n';
}
out << '\n';
return out.str();
}

View File

@@ -195,3 +195,69 @@ TEST_CASE("Formatter: NamelessSubInGroup", "[formatter]") {
CHECK_THAT(help, Contains("sub2"));
CHECK(help.find("pos") == std::string::npos);
}
TEST_CASE("Formatter: Footer", "[formatter]") {
CLI::App app{"My prog"};
std::string footer_string{"this is a test of the footer "
"systemsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss to Pr e s "
" e r v e SPA C ES"};
app.footer(footer_string);
app.add_flag("--option", "MyFlag");
app.get_formatter()->footer_paragraph_width(50);
app.get_formatter()->enable_footer_formatting(false);
CHECK(!app.get_formatter()->is_footer_paragraph_formatting_enabled());
std::string help = app.help("", CLI::AppFormatMode::Normal);
CHECK_THAT(help, Contains("is a"));
CHECK_THAT(help, Contains("to Pr e s e r v e SPA C ES"));
CHECK_THAT(help, Contains(footer_string));
help = app.help("", CLI::AppFormatMode::Sub);
CHECK_THAT(help, Contains("is a"));
CHECK_THAT(help, Contains("to Pr e s e r v e SPA C ES"));
CHECK_THAT(help, Contains(footer_string));
app.get_formatter()->enable_footer_formatting(true);
CHECK(app.get_formatter()->is_footer_paragraph_formatting_enabled());
help = app.help("", CLI::AppFormatMode::Normal);
CHECK_THAT(help, !Contains("is a"));
CHECK_THAT(help, !Contains("to Pr e s e r v e SPA C ES"));
CHECK_THAT(help, !Contains(footer_string));
help = app.help("", CLI::AppFormatMode::Sub);
CHECK_THAT(help, !Contains("is a"));
CHECK_THAT(help, !Contains("to Pr e s e r v e SPA C ES"));
CHECK_THAT(help, !Contains(footer_string));
}
TEST_CASE("Formatter: Description", "[formatter]") {
CLI::App app{"My prog"};
std::string desc_string{"this is a test of the footer "
"systemsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss to Pr e s "
"e r v e SPA C ES"};
app.description(desc_string);
app.add_flag("--option", "MyFlag");
app.get_formatter()->description_paragraph_width(50);
app.get_formatter()->enable_description_formatting(false);
CHECK(!app.get_formatter()->is_description_paragraph_formatting_enabled());
std::string help = app.help("", CLI::AppFormatMode::Normal);
CHECK_THAT(help, Contains("is a"));
CHECK_THAT(help, Contains("to Pr e s e r v e SPA C ES"));
CHECK_THAT(help, Contains(desc_string));
help = app.help("", CLI::AppFormatMode::Sub);
CHECK_THAT(help, Contains("is a"));
CHECK_THAT(help, Contains("to Pr e s e r v e SPA C ES"));
CHECK_THAT(help, Contains(desc_string));
app.get_formatter()->enable_description_formatting(true);
CHECK(app.get_formatter()->is_description_paragraph_formatting_enabled());
help = app.help("", CLI::AppFormatMode::Normal);
CHECK_THAT(help, !Contains("is a"));
CHECK_THAT(help, !Contains("to Pr e s e r v e SPA C ES"));
CHECK_THAT(help, !Contains(desc_string));
help = app.help("", CLI::AppFormatMode::Sub);
CHECK_THAT(help, !Contains("is a"));
CHECK_THAT(help, !Contains("to Pr e s e r v e SPA C ES"));
CHECK_THAT(help, !Contains(desc_string));
}