duplicate footer (#1200)

fix an issue with duplicate footers being printed with help_all

Fixes #1183

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Philip Top
2025-08-29 12:38:46 -07:00
committed by GitHub
parent f7e4695ed8
commit 1ab8646760
2 changed files with 52 additions and 4 deletions

View File

@@ -172,10 +172,12 @@ CLI11_INLINE std::string Formatter::make_help(const App *app, std::string name,
out << make_positionals(app);
out << make_groups(app, mode);
out << make_subcommands(app, mode);
std::string footer_string = make_footer(app);
if(is_footer_paragraph_formatting_enabled()) {
detail::streamOutAsParagraph(out, make_footer(app), footer_paragraph_width_); // Format footer as paragraph
detail::streamOutAsParagraph(out, footer_string, footer_paragraph_width_); // Format footer as paragraph
} else {
out << make_footer(app) << '\n';
out << footer_string << '\n';
}
return out.str();
@@ -252,10 +254,19 @@ 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);
std::string footer_string = make_footer(sub);
if(mode == AppFormatMode::Sub && !footer_string.empty()) {
const auto *parent = sub->get_parent();
std::string parent_footer = (parent != nullptr) ? make_footer(sub->get_parent()) : std::string{};
if(footer_string == parent_footer) {
footer_string = "";
}
}
if(is_footer_paragraph_formatting_enabled()) {
detail::streamOutAsParagraph(out, make_footer(sub), footer_paragraph_width_); // Format footer as paragraph
detail::streamOutAsParagraph(out, footer_string, footer_paragraph_width_); // Format footer as paragraph
} else {
out << make_footer(sub) << '\n';
out << footer_string << '\n';
}
out << '\n';
return out.str();

View File

@@ -104,6 +104,43 @@ TEST_CASE("THelp: FooterOptionGroup", "[help]") {
CHECK(footer_loc2 == std::string::npos);
}
/// @brief from github issue #1183
TEST_CASE("THelp: FooterSubcommandHelpAll", "[help]") {
CLI::App app{"My prog"};
app.footer("Report bugs to bugs@example.com");
app.set_help_all_flag("--help-all", "All options of subcommands");
app.add_subcommand("Subcommand1", "Desc1");
app.add_subcommand("Subcommand2", "Desc2");
CHECK_THROWS_AS(app.parse("--help-all"), CLI::CallForAllHelp);
std::string help = app.help("", CLI::AppFormatMode::All);
auto footer_loc = help.find("bugs@example.com");
auto footer_loc2 = help.find("bugs@example.com", footer_loc + 10);
CHECK(footer_loc != std::string::npos);
// should only see the footer once
CHECK(footer_loc2 == std::string::npos);
}
TEST_CASE("THelp: FooterSubcommandHelp", "[help]") {
CLI::App app{"My prog"};
app.footer("Report bugs to bugs@example.com");
app.add_subcommand("Subcommand1", "Desc1");
app.add_subcommand("Subcommand2", "Desc2");
CHECK_THROWS_AS(app.parse("Subcommand1 Subcommand2 --help"), CLI::CallForHelp);
std::string help = app.help();
auto footer_loc = help.find("bugs@example.com");
auto footer_loc2 = help.find("bugs@example.com", footer_loc + 10);
CHECK(footer_loc != std::string::npos);
// should only see the footer once
CHECK(footer_loc2 == std::string::npos);
}
TEST_CASE("THelp: OptionalPositional", "[help]") {
CLI::App app{"My prog", "program"};