Skip to content

Commit

Permalink
Merge pull request #66 from SkyToGround/issue_65
Browse files Browse the repository at this point in the history
Writing argument description to config string (issue #65)
  • Loading branch information
henryiii authored Dec 29, 2017
2 parents 67cd2e6 + 9e18364 commit 0243fda
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 6 deletions.
24 changes: 18 additions & 6 deletions include/CLI/App.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -809,35 +809,47 @@ class App {

/// Produce a string that could be read in as a config of the current values of the App. Set default_also to include
/// default arguments. Prefix will add a string to the beginning of each option.
std::string config_to_str(bool default_also = false, std::string prefix = "") const {
std::string
config_to_str(bool default_also = false, std::string prefix = "", bool write_description = false) const {
std::stringstream out;
for(const Option_p &opt : options_) {

// Only process option with a long-name and configurable
if(!opt->lnames_.empty() && opt->get_configurable()) {
std::string name = prefix + opt->lnames_[0];
std::string value;

// Non-flags
if(opt->get_expected() != 0) {

// If the option was found on command line
if(opt->count() > 0)
out << name << "=" << detail::inijoin(opt->results()) << std::endl;
value = detail::inijoin(opt->results());

// If the option has a default and is requested by optional argument
else if(default_also && !opt->defaultval_.empty())
out << name << "=" << opt->defaultval_ << std::endl;
value = opt->defaultval_;
// Flag, one passed
} else if(opt->count() == 1) {
out << name << "=true" << std::endl;
value = "true";

// Flag, multiple passed
} else if(opt->count() > 1) {
out << name << "=" << opt->count() << std::endl;
value = std::to_string(opt->count());

// Flag, not present
} else if(opt->count() == 0 && default_also) {
out << name << "=false" << std::endl;
value = "false";
}

if(!value.empty()) {
if(write_description && opt->has_description()) {
if(static_cast<int>(out.tellp()) != 0) {
out << std::endl;
}
out << "; " << detail::fix_newlines("; ", opt->get_description()) << std::endl;
}
out << name << "=" << value << std::endl;
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions include/CLI/StringTools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,5 +187,21 @@ inline std::vector<std::string> split_up(std::string str) {
return output;
}

/// Add a leader to the beginning of all new lines (nothing is added
/// at the start of the first line). `"; "` would be for ini files
///
/// Can't use Regex, or this would be a subs.
inline std::string fix_newlines(std::string leader, std::string input) {
std::string::size_type n = 0;
while(n != std::string::npos && n < input.size()) {
n = input.find('\n', n);
if(n != std::string::npos) {
input = input.substr(0, n + 1) + leader + input.substr(n + 1);
n += leader.size();
}
}
return input;
}

} // namespace detail
} // namespace CLI
14 changes: 14 additions & 0 deletions tests/HelpersTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,17 @@ TEST(Types, LexicalCastString) {
CLI::detail::lexical_cast(input, output);
EXPECT_EQ(input, output);
}

TEST(FixNewLines, BasicCheck) {
std::string input = "one\ntwo";
std::string output = "one\n; two";
std::string result = CLI::detail::fix_newlines("; ", input);
EXPECT_EQ(result, output);
}

TEST(FixNewLines, EdgesCheck) {
std::string input = "\none\ntwo\n";
std::string output = "\n; one\n; two\n; ";
std::string result = CLI::detail::fix_newlines("; ", input);
EXPECT_EQ(result, output);
}
38 changes: 38 additions & 0 deletions tests/IniTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,44 @@ TEST_F(TApp, IniOutputNoConfigurable) {
EXPECT_EQ("simple=3\n", str);
}

TEST_F(TApp, IniOutputShortSingleDescription) {
std::string flag = "some_flag";
std::string description = "Some short description.";
app.add_flag("--" + flag, description);

run();

std::string str = app.config_to_str(true, "", true);
EXPECT_THAT(str, HasSubstr("; " + description + "\n" + flag + "=false\n"));
}

TEST_F(TApp, IniOutputShortDoubleDescription) {
std::string flag1 = "flagnr1";
std::string flag2 = "flagnr2";
std::string description1 = "First description.";
std::string description2 = "Second description.";
app.add_flag("--" + flag1, description1);
app.add_flag("--" + flag2, description2);

run();

std::string str = app.config_to_str(true, "", true);
EXPECT_EQ(str, "; " + description1 + "\n" + flag1 + "=false\n\n; " + description2 + "\n" + flag2 + "=false\n");
}

TEST_F(TApp, IniOutputMultiLineDescription) {
std::string flag = "some_flag";
std::string description = "Some short description.\nThat has lines.";
app.add_flag("--" + flag, description);

run();

std::string str = app.config_to_str(true, "", true);
EXPECT_THAT(str, HasSubstr("; Some short description.\n"));
EXPECT_THAT(str, HasSubstr("; That has lines.\n"));
EXPECT_THAT(str, HasSubstr(flag + "=false\n"));
}

TEST_F(TApp, IniOutputVector) {

std::vector<int> v;
Expand Down

0 comments on commit 0243fda

Please sign in to comment.