Commit 822f3d67007edfcad7aac4e1f3e463bf255c7a3c

Authored by Philip Top
Committed by GitHub
1 parent a86f7fbd

fix: add an alias section to the help for subcommands (#545)

include/CLI/App.hpp
... ... @@ -1834,7 +1834,21 @@ class App {
1834 1834 }
1835 1835  
1836 1836 /// Get a display name for an app
1837   - std::string get_display_name() const { return (!name_.empty()) ? name_ : "[Option Group: " + get_group() + "]"; }
  1837 + std::string get_display_name(bool with_aliases = false) const {
  1838 + if(name_.empty()) {
  1839 + return std::string("[Option Group: ") + get_group() + "]";
  1840 + }
  1841 + if(aliases_.empty() || !with_aliases || aliases_.empty()) {
  1842 + return name_;
  1843 + }
  1844 + std::string dispname = name_;
  1845 + for(const auto &lalias : aliases_) {
  1846 + dispname.push_back(',');
  1847 + dispname.push_back(' ');
  1848 + dispname.append(lalias);
  1849 + }
  1850 + return dispname;
  1851 + }
1838 1852  
1839 1853 /// Check the name, case insensitive and underscore insensitive if set
1840 1854 bool check_name(std::string name_to_check) const {
... ...
include/CLI/Formatter.hpp
... ... @@ -205,15 +205,18 @@ inline std::string Formatter::make_subcommands(const App *app, AppFormatMode mod
205 205  
206 206 inline std::string Formatter::make_subcommand(const App *sub) const {
207 207 std::stringstream out;
208   - detail::format_help(out, sub->get_name(), sub->get_description(), column_width_);
  208 + detail::format_help(out, sub->get_display_name(true), sub->get_description(), column_width_);
209 209 return out.str();
210 210 }
211 211  
212 212 inline std::string Formatter::make_expanded(const App *sub) const {
213 213 std::stringstream out;
214   - out << sub->get_display_name() << "\n";
  214 + out << sub->get_display_name(true) << "\n";
215 215  
216 216 out << make_description(sub);
  217 + if(sub->get_name().empty() && !sub->get_aliases().empty()) {
  218 + detail::format_aliases(out, sub->get_aliases(), column_width_ + 2);
  219 + }
217 220 out << make_positionals(sub);
218 221 out << make_groups(sub, AppFormatMode::Sub);
219 222 out << make_subcommands(sub, AppFormatMode::Sub);
... ...
include/CLI/StringTools.hpp
... ... @@ -159,7 +159,7 @@ inline std::string trim_copy(const std::string &amp;str, const std::string &amp;filter)
159 159 return trim(s, filter);
160 160 }
161 161 /// Print a two part "help" string
162   -inline std::ostream &format_help(std::ostream &out, std::string name, std::string description, std::size_t wid) {
  162 +inline std::ostream &format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid) {
163 163 name = " " + name;
164 164 out << std::setw(static_cast<int>(wid)) << std::left << name;
165 165 if(!description.empty()) {
... ... @@ -176,6 +176,24 @@ inline std::ostream &amp;format_help(std::ostream &amp;out, std::string name, std::strin
176 176 return out;
177 177 }
178 178  
  179 +/// Print subcommand aliases
  180 +inline std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid) {
  181 + if(!aliases.empty()) {
  182 + out << std::setw(static_cast<int>(wid)) << " aliases: ";
  183 + bool front = true;
  184 + for(const auto &alias : aliases) {
  185 + if(!front) {
  186 + out << ", ";
  187 + } else {
  188 + front = false;
  189 + }
  190 + out << alias;
  191 + }
  192 + out << "\n";
  193 + }
  194 + return out;
  195 +}
  196 +
179 197 /// Verify the first character of an option
180 198 template <typename T> bool valid_first_char(T c) {
181 199 return std::isalnum(c, std::locale()) || c == '_' || c == '?' || c == '@';
... ...
tests/HelpTest.cpp
... ... @@ -467,6 +467,36 @@ TEST(THelp, Subcom) {
467 467 EXPECT_THAT(help, HasSubstr("Usage: ./myprogram sub2"));
468 468 }
469 469  
  470 +TEST(THelp, Subcom_alias) {
  471 + CLI::App app{"My prog"};
  472 +
  473 + auto sub1 = app.add_subcommand("sub1", "Subcommand1 description test");
  474 + sub1->alias("sub_alias1");
  475 + sub1->alias("sub_alias2");
  476 +
  477 + app.add_subcommand("sub2", "Subcommand2 description test");
  478 +
  479 + std::string help = app.help();
  480 + EXPECT_THAT(help, HasSubstr("Usage: [OPTIONS] [SUBCOMMAND]"));
  481 + EXPECT_THAT(help, HasSubstr("sub_alias1"));
  482 + EXPECT_THAT(help, HasSubstr("sub_alias2"));
  483 +}
  484 +
  485 +TEST(THelp, Subcom_alias_group) {
  486 + CLI::App app{"My prog"};
  487 +
  488 + auto sub1 = app.add_subcommand("", "Subcommand1 description test");
  489 + sub1->alias("sub_alias1");
  490 + sub1->alias("sub_alias2");
  491 +
  492 + app.add_subcommand("sub2", "Subcommand2 description test");
  493 +
  494 + std::string help = app.help();
  495 + EXPECT_THAT(help, HasSubstr("Usage: [OPTIONS] [SUBCOMMAND]"));
  496 + EXPECT_THAT(help, HasSubstr("sub_alias1"));
  497 + EXPECT_THAT(help, HasSubstr("sub_alias2"));
  498 +}
  499 +
470 500 TEST(THelp, MasterName) {
471 501 CLI::App app{"My prog", "MyRealName"};
472 502  
... ...