Skip to content

Commit

Permalink
Merge pull request #268 from fanurs/align_multiline_message
Browse files Browse the repository at this point in the history
Fix issue #248: Align multiline help messages
  • Loading branch information
p-ranav authored Jul 11, 2023
2 parents 557948f + e82653c commit b0930ab
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
31 changes: 30 additions & 1 deletion include/argparse/argparse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,36 @@ class Argument {
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()) {
Expand Down
45 changes: 45 additions & 0 deletions test/test_help.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

0 comments on commit b0930ab

Please sign in to comment.