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

This commit is contained in:
Philip Top 2020-12-28 08:02:18 -08:00 committed by GitHub
parent a86f7fbd5e
commit 822f3d6700
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 4 deletions

View File

@ -1834,7 +1834,21 @@ class App {
}
/// Get a display name for an app
std::string get_display_name() const { return (!name_.empty()) ? name_ : "[Option Group: " + get_group() + "]"; }
std::string get_display_name(bool with_aliases = false) const {
if(name_.empty()) {
return std::string("[Option Group: ") + get_group() + "]";
}
if(aliases_.empty() || !with_aliases || aliases_.empty()) {
return name_;
}
std::string dispname = name_;
for(const auto &lalias : aliases_) {
dispname.push_back(',');
dispname.push_back(' ');
dispname.append(lalias);
}
return dispname;
}
/// Check the name, case insensitive and underscore insensitive if set
bool check_name(std::string name_to_check) const {

View File

@ -205,15 +205,18 @@ inline std::string Formatter::make_subcommands(const App *app, AppFormatMode mod
inline std::string Formatter::make_subcommand(const App *sub) const {
std::stringstream out;
detail::format_help(out, sub->get_name(), sub->get_description(), column_width_);
detail::format_help(out, sub->get_display_name(true), sub->get_description(), column_width_);
return out.str();
}
inline std::string Formatter::make_expanded(const App *sub) const {
std::stringstream out;
out << sub->get_display_name() << "\n";
out << sub->get_display_name(true) << "\n";
out << make_description(sub);
if(sub->get_name().empty() && !sub->get_aliases().empty()) {
detail::format_aliases(out, sub->get_aliases(), column_width_ + 2);
}
out << make_positionals(sub);
out << make_groups(sub, AppFormatMode::Sub);
out << make_subcommands(sub, AppFormatMode::Sub);

View File

@ -159,7 +159,7 @@ inline std::string trim_copy(const std::string &str, const std::string &filter)
return trim(s, filter);
}
/// Print a two part "help" string
inline std::ostream &format_help(std::ostream &out, std::string name, std::string description, std::size_t wid) {
inline std::ostream &format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid) {
name = " " + name;
out << std::setw(static_cast<int>(wid)) << std::left << name;
if(!description.empty()) {
@ -176,6 +176,24 @@ inline std::ostream &format_help(std::ostream &out, std::string name, std::strin
return out;
}
/// Print subcommand aliases
inline std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid) {
if(!aliases.empty()) {
out << std::setw(static_cast<int>(wid)) << " aliases: ";
bool front = true;
for(const auto &alias : aliases) {
if(!front) {
out << ", ";
} else {
front = false;
}
out << alias;
}
out << "\n";
}
return out;
}
/// Verify the first character of an option
template <typename T> bool valid_first_char(T c) {
return std::isalnum(c, std::locale()) || c == '_' || c == '?' || c == '@';

View File

@ -467,6 +467,36 @@ TEST(THelp, Subcom) {
EXPECT_THAT(help, HasSubstr("Usage: ./myprogram sub2"));
}
TEST(THelp, Subcom_alias) {
CLI::App app{"My prog"};
auto sub1 = app.add_subcommand("sub1", "Subcommand1 description test");
sub1->alias("sub_alias1");
sub1->alias("sub_alias2");
app.add_subcommand("sub2", "Subcommand2 description test");
std::string help = app.help();
EXPECT_THAT(help, HasSubstr("Usage: [OPTIONS] [SUBCOMMAND]"));
EXPECT_THAT(help, HasSubstr("sub_alias1"));
EXPECT_THAT(help, HasSubstr("sub_alias2"));
}
TEST(THelp, Subcom_alias_group) {
CLI::App app{"My prog"};
auto sub1 = app.add_subcommand("", "Subcommand1 description test");
sub1->alias("sub_alias1");
sub1->alias("sub_alias2");
app.add_subcommand("sub2", "Subcommand2 description test");
std::string help = app.help();
EXPECT_THAT(help, HasSubstr("Usage: [OPTIONS] [SUBCOMMAND]"));
EXPECT_THAT(help, HasSubstr("sub_alias1"));
EXPECT_THAT(help, HasSubstr("sub_alias2"));
}
TEST(THelp, MasterName) {
CLI::App app{"My prog", "MyRealName"};