Skip to content

Commit

Permalink
[FIX] flags setting value to false
Browse files Browse the repository at this point in the history
  • Loading branch information
eseiler committed Feb 21, 2024
1 parent 31d3207 commit 5c9e2f9
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 1 deletion.
4 changes: 3 additions & 1 deletion include/sharg/detail/format_parse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,9 @@ class format_parse : public format_base
*/
void get_flag(bool & value, char const short_id, std::string const & long_id)
{
value = flag_is_set(short_id) || flag_is_set(long_id);
// `|| value` is needed to keep the value if it was set before.
// It must be last because `flag_is_set` removes the flag from the arguments.
value = flag_is_set(short_id) || flag_is_set(long_id) || value;
}

/*!\brief Handles command line positional option retrieval.
Expand Down
76 changes: 76 additions & 0 deletions test/unit/parser/format_parse_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -881,3 +881,79 @@ TEST_F(format_parse_test, executable_name)
EXPECT_EQ(executable_name[0], "parser_test");
EXPECT_EQ(executable_name[1], "build");
}

TEST_F(format_parse_test, flag_independence)
{
bool flag_value{false};

auto parser = get_parser("-a", "-z");
parser.add_flag(flag_value, sharg::config{.short_id = 'a'});
parser.add_flag(flag_value, sharg::config{.short_id = 'z'});
EXPECT_NO_THROW(parser.parse());
EXPECT_EQ(flag_value, true);

flag_value = false;

parser = get_parser("-a");
parser.add_flag(flag_value, sharg::config{.short_id = 'a'});
parser.add_flag(flag_value, sharg::config{.short_id = 'z'});
EXPECT_NO_THROW(parser.parse());
EXPECT_EQ(flag_value, true);

flag_value = false;

parser = get_parser("-z");
parser.add_flag(flag_value, sharg::config{.short_id = 'a'});
parser.add_flag(flag_value, sharg::config{.short_id = 'z'});
EXPECT_NO_THROW(parser.parse());
EXPECT_EQ(flag_value, true);
}

TEST_F(format_parse_test, parse_order_example)
{
bool flag_value{false};

// Flags are evaluated after options
auto parser = get_parser("-f", "-o", "false");

EXPECT_NO_THROW(parser.add_option(flag_value, sharg::config{.short_id = 'o'}));
EXPECT_NO_THROW(parser.add_flag(flag_value, sharg::config{.short_id = 'f'}));
EXPECT_EQ(flag_value, false);
EXPECT_NO_THROW(parser.parse());
EXPECT_EQ(flag_value, true); // option sets to false, but flag sets to true

flag_value = false;

// Because this option syntax is also allowed
parser = get_parser("-otrue");

EXPECT_NO_THROW(parser.add_option(flag_value, sharg::config{.short_id = 'o'}));
EXPECT_EQ(flag_value, false);
EXPECT_NO_THROW(parser.parse());
EXPECT_EQ(flag_value, true);

flag_value = false;

// And this flag syntax is allowed
parser = get_parser("-otrue");
std::array<bool, 5> flag_values{false, false, false, false, false};

EXPECT_NO_THROW(parser.add_flag(flag_values[0], sharg::config{.short_id = 'o'}));
EXPECT_NO_THROW(parser.add_flag(flag_values[1], sharg::config{.short_id = 't'}));
EXPECT_NO_THROW(parser.add_flag(flag_values[2], sharg::config{.short_id = 'r'}));
EXPECT_NO_THROW(parser.add_flag(flag_values[3], sharg::config{.short_id = 'u'}));
EXPECT_NO_THROW(parser.add_flag(flag_values[4], sharg::config{.short_id = 'e'}));
EXPECT_TRUE(std::ranges::none_of(flag_values, std::identity{})); // All false
EXPECT_NO_THROW(parser.parse());
EXPECT_TRUE(std::ranges::all_of(flag_values, std::identity{})); // All true

// Positional options are evaluated last
parser = get_parser("false", "-o", "true", "-f");

EXPECT_NO_THROW(parser.add_option(flag_value, sharg::config{.short_id = 'o'}));
EXPECT_NO_THROW(parser.add_flag(flag_value, sharg::config{.short_id = 'f'}));
EXPECT_NO_THROW(parser.add_positional_option(flag_value, sharg::config{}));
EXPECT_EQ(flag_value, false);
EXPECT_NO_THROW(parser.parse());
EXPECT_EQ(flag_value, false);
}

0 comments on commit 5c9e2f9

Please sign in to comment.