mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-04 15:14:39 +00:00
Merge pull request #203 from p-ranav/feature/option_equals_value
Allow --option=value form of arguments (Refactored #185)
This commit is contained in:
commit
1ebaccc350
37
README.md
37
README.md
@ -42,6 +42,7 @@
|
|||||||
* [Construct a JSON object from a filename argument](#construct-a-json-object-from-a-filename-argument)
|
* [Construct a JSON object from a filename argument](#construct-a-json-object-from-a-filename-argument)
|
||||||
* [Positional Arguments with Compound Toggle Arguments](#positional-arguments-with-compound-toggle-arguments)
|
* [Positional Arguments with Compound Toggle Arguments](#positional-arguments-with-compound-toggle-arguments)
|
||||||
* [Restricting the set of values for an argument](#restricting-the-set-of-values-for-an-argument)
|
* [Restricting the set of values for an argument](#restricting-the-set-of-values-for-an-argument)
|
||||||
|
* [Using `option=value` syntax](#using-optionvalue-syntax)
|
||||||
* [CMake Integration](#cmake-integration)
|
* [CMake Integration](#cmake-integration)
|
||||||
* [Supported Toolchains](#supported-toolchains)
|
* [Supported Toolchains](#supported-toolchains)
|
||||||
* [Contributing](#contributing)
|
* [Contributing](#contributing)
|
||||||
@ -934,6 +935,42 @@ foo@bar:/home/dev/$ ./main fex
|
|||||||
baz
|
baz
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Using `option=value` syntax
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "argparse.hpp"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
argparse::ArgumentParser program("test");
|
||||||
|
program.add_argument("--foo").implicit_value(true).default_value(false);
|
||||||
|
program.add_argument("--bar");
|
||||||
|
|
||||||
|
try {
|
||||||
|
program.parse_args(argc, argv);
|
||||||
|
}
|
||||||
|
catch (const std::runtime_error& err) {
|
||||||
|
std::cerr << err.what() << std::endl;
|
||||||
|
std::cerr << program;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (program.is_used("--foo")) {
|
||||||
|
std::cout << "--foo: " << std::boolalpha << program.get<bool>("--foo") << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (program.is_used("--bar")) {
|
||||||
|
std::cout << "--bar: " << program.get("--bar") << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```console
|
||||||
|
foo@bar:/home/dev/$ ./test --bar=BAR --foo
|
||||||
|
--foo: true
|
||||||
|
--bar: BAR
|
||||||
|
```
|
||||||
|
|
||||||
## CMake Integration
|
## CMake Integration
|
||||||
|
|
||||||
Use the latest argparse in your CMake project without copying any content.
|
Use the latest argparse in your CMake project without copying any content.
|
||||||
|
@ -1226,10 +1226,42 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*
|
||||||
|
* Pre-process this argument list. Anything starting with "--", that
|
||||||
|
* contains an =, where the prefix before the = has an entry in the
|
||||||
|
* options table, should be split.
|
||||||
|
*/
|
||||||
|
std::vector<std::string>
|
||||||
|
preprocess_arguments(const std::vector<std::string> &raw_arguments) {
|
||||||
|
std::vector<std::string> arguments;
|
||||||
|
for (const auto &arg : raw_arguments) {
|
||||||
|
// Check that:
|
||||||
|
// - We don't have an argument named exactly this
|
||||||
|
// - The argument starts with "--"
|
||||||
|
// - The argument contains a "="
|
||||||
|
std::size_t eqpos = arg.find("=");
|
||||||
|
if (m_argument_map.find(arg) == m_argument_map.end() &&
|
||||||
|
arg.rfind("--", 0) == 0 && eqpos != std::string::npos) {
|
||||||
|
// Get the name of the potential option, and check it exists
|
||||||
|
std::string opt_name = arg.substr(0, eqpos);
|
||||||
|
if (m_argument_map.find(opt_name) != m_argument_map.end()) {
|
||||||
|
// This is the name of an option! Split it into two parts
|
||||||
|
arguments.push_back(std::move(opt_name));
|
||||||
|
arguments.push_back(arg.substr(eqpos + 1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we've fallen through to here, then it's a standard argument
|
||||||
|
arguments.push_back(arg);
|
||||||
|
}
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @throws std::runtime_error in case of any invalid argument
|
* @throws std::runtime_error in case of any invalid argument
|
||||||
*/
|
*/
|
||||||
void parse_args_internal(const std::vector<std::string> &arguments) {
|
void parse_args_internal(const std::vector<std::string> &raw_arguments) {
|
||||||
|
auto arguments = preprocess_arguments(raw_arguments);
|
||||||
if (m_program_name.empty() && !arguments.empty()) {
|
if (m_program_name.empty() && !arguments.empty()) {
|
||||||
m_program_name = arguments.front();
|
m_program_name = arguments.front();
|
||||||
}
|
}
|
||||||
@ -1294,7 +1326,8 @@ private:
|
|||||||
* Like parse_args_internal but collects unused args into a vector<string>
|
* Like parse_args_internal but collects unused args into a vector<string>
|
||||||
*/
|
*/
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
parse_known_args_internal(const std::vector<std::string> &arguments) {
|
parse_known_args_internal(const std::vector<std::string> &raw_arguments) {
|
||||||
|
auto arguments = preprocess_arguments(raw_arguments);
|
||||||
|
|
||||||
std::vector<std::string> unknown_arguments{};
|
std::vector<std::string> unknown_arguments{};
|
||||||
|
|
||||||
|
Binary file not shown.
@ -1,15 +0,0 @@
|
|||||||
#include "argparse.hpp"
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
argparse::ArgumentParser program("test");
|
|
||||||
program.add_argument("--foo").implicit_value(true).default_value(false);
|
|
||||||
program.add_argument("bar");
|
|
||||||
|
|
||||||
auto unknown_args =
|
|
||||||
program.parse_known_args({"test", "--foo", "--badger", "BAR", "spam"});
|
|
||||||
|
|
||||||
assert(program.get<bool>("--foo") == true);
|
|
||||||
assert(program.get<std::string>("bar") == std::string{"BAR"});
|
|
||||||
assert((unknown_args == std::vector<std::string>{"--badger", "spam"}));
|
|
||||||
}
|
|
@ -48,6 +48,7 @@ file(GLOB ARGPARSE_TEST_SOURCES
|
|||||||
test_version.cpp
|
test_version.cpp
|
||||||
test_subparsers.cpp
|
test_subparsers.cpp
|
||||||
test_parse_known_args.cpp
|
test_parse_known_args.cpp
|
||||||
|
test_equals_form.cpp
|
||||||
)
|
)
|
||||||
set_source_files_properties(main.cpp
|
set_source_files_properties(main.cpp
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
39
test/test_equals_form.cpp
Normal file
39
test/test_equals_form.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include <argparse/argparse.hpp>
|
||||||
|
#include <doctest.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
using doctest::test_suite;
|
||||||
|
|
||||||
|
TEST_CASE("Basic --value=value" * test_suite("equals_form")) {
|
||||||
|
argparse::ArgumentParser parser("test");
|
||||||
|
parser.add_argument("--long");
|
||||||
|
parser.parse_args({"test", "--long=value"});
|
||||||
|
std::string result{parser.get("--long")};
|
||||||
|
REQUIRE(result == "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Fallback = in regular option name" * test_suite("equals_form")) {
|
||||||
|
argparse::ArgumentParser parser("test");
|
||||||
|
parser.add_argument("--long=mislead");
|
||||||
|
parser.parse_args({"test", "--long=mislead", "value"});
|
||||||
|
std::string result{parser.get("--long=mislead")};
|
||||||
|
REQUIRE(result == "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Duplicate =-named and standard" * test_suite("equals_form")) {
|
||||||
|
argparse::ArgumentParser parser("test");
|
||||||
|
parser.add_argument("--long=mislead");
|
||||||
|
parser.add_argument("--long").default_value(std::string{"NO_VALUE"});
|
||||||
|
parser.parse_args({"test", "--long=mislead", "value"});
|
||||||
|
std::string result{parser.get("--long=mislead")};
|
||||||
|
REQUIRE(result == "value");
|
||||||
|
std::string result2{parser.get("--long")};
|
||||||
|
REQUIRE(result2 == "NO_VALUE");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Basic --value=value with nargs(2)" * test_suite("equals_form")) {
|
||||||
|
argparse::ArgumentParser parser("test");
|
||||||
|
parser.add_argument("--long").nargs(2);
|
||||||
|
parser.parse_args({"test", "--long=value1", "value2"});
|
||||||
|
REQUIRE((parser.get<std::vector<std::string>>("--long") ==
|
||||||
|
std::vector<std::string>{"value1", "value2"}));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user