Merge pull request #268 from fanurs/align_multiline_message

Fix issue #248: Align multiline help messages
This commit is contained in:
Pranav 2023-07-11 08:15:12 -05:00 committed by GitHub
commit b0930ab028
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 1 deletions

View File

@ -673,7 +673,36 @@ public:
name_stream << " " << argument.m_metavar;
}
}
stream << name_stream.str() << "\t" << argument.m_help;
// align multiline help message
auto stream_width = stream.width();
auto name_padding = std::string(name_stream.str().size(), ' ');
auto pos = 0;
auto prev = 0;
auto first_line = true;
auto hspace = " "; // minimal space between name and help message
stream << name_stream.str();
std::string_view help_view(argument.m_help);
while ((pos = argument.m_help.find('\n', prev)) != std::string::npos) {
auto line = help_view.substr(prev, pos - prev + 1);
if (first_line) {
stream << hspace << line;
first_line = false;
} else {
stream.width(stream_width);
stream << name_padding << hspace << line;
}
prev += pos - prev + 1;
}
if (first_line) {
stream << hspace << argument.m_help;
} else {
auto leftover = help_view.substr(prev, argument.m_help.size() - prev);
if (!leftover.empty()) {
stream.width(stream_width);
stream << name_padding << hspace << leftover;
}
}
// print nargs spec
if (!argument.m_help.empty()) {

View File

@ -73,3 +73,48 @@ TEST_CASE("Users can replace default -h/--help" * test_suite("help")) {
program.parse_args({"test", "--help"});
REQUIRE_FALSE(buffer.str().empty());
}
TEST_CASE("Multiline help message alignment") {
// '#' is used at the beginning of each help message line to simplify testing.
// It is important to ensure that this character doesn't appear elsewhere in the test case.
// Default arguments (e.g., -h/--help, -v/--version) are not included in this test.
argparse::ArgumentParser program("program");
program.add_argument("INPUT1")
.help(
"#This is the first line of help message.\n"
"#And this is the second line of help message."
);
program.add_argument("program_input2")
.help("#There is only one line.");
program.add_argument("-p", "--prog_input3")
.help(
R"(#Lorem ipsum dolor sit amet, consectetur adipiscing elit.
#Sed ut perspiciatis unde omnis iste natus error sit voluptatem
#accusantium doloremque laudantium, totam rem aperiam...)"
);
program.add_argument("--verbose").default_value(false).implicit_value(true);
std::ostringstream stream;
stream << program;
std::istringstream iss(stream.str());
int help_message_start = -1;
std::string line;
while (std::getline(iss, line)) {
// Find the position of '#', which indicates the start of the help message line
auto pos = line.find('#');
if (pos == std::string::npos) {
continue;
}
if (help_message_start == -1) {
help_message_start = pos;
} else {
REQUIRE(pos == help_message_start);
}
}
// Make sure we have at least one help message
REQUIRE(help_message_start != -1);
}