From c59e0c132cd955a11d77a83e4929f094a0bcd833 Mon Sep 17 00:00:00 2001 From: Long Deng <37360259+ldeng-ustc@users.noreply.github.com> Date: Wed, 11 May 2022 15:44:25 +0800 Subject: [PATCH] Solve arguments() showing empty keys when only short-only option exists (#318) * Solve `arguments()` showing empty keys when there is only a short option. --- include/cxxopts.hpp | 11 +++++++-- test/options.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/include/cxxopts.hpp b/include/cxxopts.hpp index b957956b..a3359175 100644 --- a/include/cxxopts.hpp +++ b/include/cxxopts.hpp @@ -1287,6 +1287,13 @@ namespace cxxopts return m_long; } + CXXOPTS_NODISCARD + const std::string& + essential_name() const + { + return m_long.empty() ? m_short : m_long; + } + size_t hash() const { @@ -2152,7 +2159,7 @@ OptionParser::parse_default(const std::shared_ptr& details) // TODO: remove the duplicate code here auto& store = m_parsed[details->hash()]; store.parse_default(details); - m_defaults.emplace_back(details->long_name(), details->value().get_default_value()); + m_defaults.emplace_back(details->essential_name(), details->value().get_default_value()); } inline @@ -2176,7 +2183,7 @@ OptionParser::parse_option auto& result = m_parsed[hash]; result.parse(value, arg); - m_sequential.emplace_back(value->long_name(), arg); + m_sequential.emplace_back(value->essential_name(), arg); } inline diff --git a/test/options.cpp b/test/options.cpp index 3398b70a..eea08538 100644 --- a/test/options.cpp +++ b/test/options.cpp @@ -116,6 +116,11 @@ TEST_CASE("Short options", "[options]") CHECK(result.count("a") == 1); CHECK(result["a"].as() == "value"); + auto& arguments = result.arguments(); + REQUIRE(arguments.size() == 1); + CHECK(arguments[0].key() == "a"); + CHECK(arguments[0].value() == "value"); + REQUIRE_THROWS_AS(options.add_options()("", "nothing option"), cxxopts::invalid_option_format_error&); } @@ -832,3 +837,54 @@ TEST_CASE("Parameter follow option", "[parameter]") { CHECK(job_values[2] == 10); CHECK(job_values[3] == 5); } + +TEST_CASE("Iterator", "[iterator]") { + cxxopts::Options options("tester", " - test iterating over parse result"); + + options.add_options() + ("long", "a long option") + ("s,short", "a short option") + ("a", "a short-only option") + ("value", "an option with a value", cxxopts::value()) + ("default", "an option with default value", cxxopts::value()->default_value("42")) + ("nothing", "won't exist", cxxopts::value()) + ; + + Argv argv({ + "tester", + "--long", + "-s", + "-a", + "--value", + "value", + }); + + auto** actual_argv = argv.argv(); + auto argc = argv.argc(); + + auto result = options.parse(argc, actual_argv); + + auto iter = result.begin(); + + REQUIRE(iter != result.end()); + CHECK(iter->key() == "long"); + CHECK(iter->value() == "true"); + + REQUIRE(++iter != result.end()); + CHECK(iter->key() == "short"); + CHECK(iter->value() == "true"); + + REQUIRE(++iter != result.end()); + CHECK(iter->key() == "a"); + CHECK(iter->value() == "true"); + + REQUIRE(++iter != result.end()); + CHECK(iter->key() == "value"); + CHECK(iter->value() == "value"); + + REQUIRE(++iter != result.end()); + CHECK(iter->key() == "default"); + CHECK(iter->value() == "42"); + + REQUIRE(++iter == result.end()); +}