mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-03 14:44:40 +00:00
Add a Argument::hidden() method to prevent an argument from appearing in usage or help
This commit is contained in:
parent
cebee4bb4b
commit
d7d2326f42
16
README.md
16
README.md
@ -39,7 +39,7 @@
|
|||||||
* [Parent Parsers](#parent-parsers)
|
* [Parent Parsers](#parent-parsers)
|
||||||
* [Subcommands](#subcommands)
|
* [Subcommands](#subcommands)
|
||||||
* [Parse Known Args](#parse-known-args)
|
* [Parse Known Args](#parse-known-args)
|
||||||
* [Hidden alias](#hidden-alias)
|
* [Hidden argument and alias](#hidden-argument-alias)
|
||||||
* [ArgumentParser in bool Context](#argumentparser-in-bool-context)
|
* [ArgumentParser in bool Context](#argumentparser-in-bool-context)
|
||||||
* [Custom Prefix Characters](#custom-prefix-characters)
|
* [Custom Prefix Characters](#custom-prefix-characters)
|
||||||
* [Custom Assignment Characters](#custom-assignment-characters)
|
* [Custom Assignment Characters](#custom-assignment-characters)
|
||||||
@ -1003,7 +1003,7 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Hidden alias
|
### Hidden argument and alias
|
||||||
|
|
||||||
It is sometimes desirable to offer an alias for an argument, but without it
|
It is sometimes desirable to offer an alias for an argument, but without it
|
||||||
appearing it in the usage. For example, to phase out a deprecated wording of
|
appearing it in the usage. For example, to phase out a deprecated wording of
|
||||||
@ -1017,6 +1017,18 @@ auto &arg = program.add_argument("--suppress").flag();
|
|||||||
program.add_hidden_alias_for(arg, "--supress"); // old misspelled alias
|
program.add_hidden_alias_for(arg, "--supress"); // old misspelled alias
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The ``Argument::hidden()`` method can also be used to prevent a (generally
|
||||||
|
optional) argument from appearing in the usage or help.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
argparse::ArgumentParser program("test");
|
||||||
|
|
||||||
|
program.add_argument("--non-documented").flag().hidden();
|
||||||
|
```
|
||||||
|
|
||||||
|
This can also be used on positional arguments, but in that later case it only
|
||||||
|
makes sense in practice for the last ones.
|
||||||
|
|
||||||
### ArgumentParser in bool Context
|
### ArgumentParser in bool Context
|
||||||
|
|
||||||
An `ArgumentParser` is `false` until it (or one of its subparsers) have extracted
|
An `ArgumentParser` is `false` until it (or one of its subparsers) have extracted
|
||||||
|
@ -606,7 +606,7 @@ class Argument {
|
|||||||
: m_accepts_optional_like_value(false),
|
: m_accepts_optional_like_value(false),
|
||||||
m_is_optional((is_optional(a[I], prefix_chars) || ...)),
|
m_is_optional((is_optional(a[I], prefix_chars) || ...)),
|
||||||
m_is_required(false), m_is_repeatable(false), m_is_used(false),
|
m_is_required(false), m_is_repeatable(false), m_is_used(false),
|
||||||
m_prefix_chars(prefix_chars) {
|
m_is_hidden(false), m_prefix_chars(prefix_chars) {
|
||||||
((void)m_names.emplace_back(a[I]), ...);
|
((void)m_names.emplace_back(a[I]), ...);
|
||||||
std::sort(
|
std::sort(
|
||||||
m_names.begin(), m_names.end(), [](const auto &lhs, const auto &rhs) {
|
m_names.begin(), m_names.end(), [](const auto &lhs, const auto &rhs) {
|
||||||
@ -745,6 +745,12 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cause the argument to be invisible in usage and help
|
||||||
|
auto &hidden() {
|
||||||
|
m_is_hidden = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template <char Shape, typename T>
|
template <char Shape, typename T>
|
||||||
auto scan() -> std::enable_if_t<std::is_arithmetic_v<T>, Argument &> {
|
auto scan() -> std::enable_if_t<std::is_arithmetic_v<T>, Argument &> {
|
||||||
static_assert(!(std::is_const_v<T> || std::is_volatile_v<T>),
|
static_assert(!(std::is_const_v<T> || std::is_volatile_v<T>),
|
||||||
@ -1531,6 +1537,7 @@ private:
|
|||||||
bool m_is_required : 1;
|
bool m_is_required : 1;
|
||||||
bool m_is_repeatable : 1;
|
bool m_is_repeatable : 1;
|
||||||
bool m_is_used : 1;
|
bool m_is_used : 1;
|
||||||
|
bool m_is_hidden : 1; // if set, does not appear in usage or help
|
||||||
std::string_view m_prefix_chars; // ArgumentParser has the prefix_chars
|
std::string_view m_prefix_chars; // ArgumentParser has the prefix_chars
|
||||||
int m_usage_newline_counter = 0;
|
int m_usage_newline_counter = 0;
|
||||||
std::size_t m_group_idx = 0;
|
std::size_t m_group_idx = 0;
|
||||||
@ -1910,22 +1917,30 @@ public:
|
|||||||
stream << parser.m_description << "\n\n";
|
stream << parser.m_description << "\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parser.m_positional_arguments.empty()) {
|
const bool has_visible_positional_args = std::find_if(
|
||||||
|
parser.m_positional_arguments.begin(),
|
||||||
|
parser.m_positional_arguments.end(),
|
||||||
|
[](const auto &argument) {
|
||||||
|
return !argument.m_is_hidden; }) !=
|
||||||
|
parser.m_positional_arguments.end();
|
||||||
|
if (has_visible_positional_args) {
|
||||||
stream << "Positional arguments:\n";
|
stream << "Positional arguments:\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &argument : parser.m_positional_arguments) {
|
for (const auto &argument : parser.m_positional_arguments) {
|
||||||
stream.width(static_cast<std::streamsize>(longest_arg_length));
|
if (!argument.m_is_hidden) {
|
||||||
stream << argument;
|
stream.width(static_cast<std::streamsize>(longest_arg_length));
|
||||||
|
stream << argument;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parser.m_optional_arguments.empty()) {
|
if (!parser.m_optional_arguments.empty()) {
|
||||||
stream << (parser.m_positional_arguments.empty() ? "" : "\n")
|
stream << (!has_visible_positional_args ? "" : "\n")
|
||||||
<< "Optional arguments:\n";
|
<< "Optional arguments:\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &argument : parser.m_optional_arguments) {
|
for (const auto &argument : parser.m_optional_arguments) {
|
||||||
if (argument.m_group_idx == 0) {
|
if (argument.m_group_idx == 0 && !argument.m_is_hidden) {
|
||||||
stream.width(static_cast<std::streamsize>(longest_arg_length));
|
stream.width(static_cast<std::streamsize>(longest_arg_length));
|
||||||
stream << argument;
|
stream << argument;
|
||||||
}
|
}
|
||||||
@ -1934,7 +1949,7 @@ public:
|
|||||||
for (size_t i_group = 0; i_group < parser.m_group_names.size(); ++i_group) {
|
for (size_t i_group = 0; i_group < parser.m_group_names.size(); ++i_group) {
|
||||||
stream << "\n" << parser.m_group_names[i_group] << " (detailed usage):\n";
|
stream << "\n" << parser.m_group_names[i_group] << " (detailed usage):\n";
|
||||||
for (const auto &argument : parser.m_optional_arguments) {
|
for (const auto &argument : parser.m_optional_arguments) {
|
||||||
if (argument.m_group_idx == i_group + 1) {
|
if (argument.m_group_idx == i_group + 1 && !argument.m_is_hidden) {
|
||||||
stream.width(static_cast<std::streamsize>(longest_arg_length));
|
stream.width(static_cast<std::streamsize>(longest_arg_length));
|
||||||
stream << argument;
|
stream << argument;
|
||||||
}
|
}
|
||||||
@ -2006,6 +2021,9 @@ public:
|
|||||||
const MutuallyExclusiveGroup *cur_mutex = nullptr;
|
const MutuallyExclusiveGroup *cur_mutex = nullptr;
|
||||||
int usage_newline_counter = -1;
|
int usage_newline_counter = -1;
|
||||||
for (const auto &argument : this->m_optional_arguments) {
|
for (const auto &argument : this->m_optional_arguments) {
|
||||||
|
if (argument.m_is_hidden) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (multiline_usage) {
|
if (multiline_usage) {
|
||||||
if (argument.m_group_idx != group_idx) {
|
if (argument.m_group_idx != group_idx) {
|
||||||
continue;
|
continue;
|
||||||
@ -2078,6 +2096,9 @@ public:
|
|||||||
}
|
}
|
||||||
// Put positional arguments after the optionals
|
// Put positional arguments after the optionals
|
||||||
for (const auto &argument : this->m_positional_arguments) {
|
for (const auto &argument : this->m_positional_arguments) {
|
||||||
|
if (argument.m_is_hidden) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const std::string pos_arg = !argument.m_metavar.empty()
|
const std::string pos_arg = !argument.m_metavar.empty()
|
||||||
? argument.m_metavar
|
? argument.m_metavar
|
||||||
: argument.m_names.front();
|
: argument.m_names.front();
|
||||||
|
@ -37,6 +37,8 @@ file(GLOB ARGPARSE_TEST_SOURCES
|
|||||||
test_error_reporting.cpp
|
test_error_reporting.cpp
|
||||||
test_get.cpp
|
test_get.cpp
|
||||||
test_help.cpp
|
test_help.cpp
|
||||||
|
test_hidden_alias.cpp
|
||||||
|
test_hidden_argument.cpp
|
||||||
test_invalid_arguments.cpp
|
test_invalid_arguments.cpp
|
||||||
test_is_used.cpp
|
test_is_used.cpp
|
||||||
test_issue_37.cpp
|
test_issue_37.cpp
|
||||||
@ -56,7 +58,6 @@ file(GLOB ARGPARSE_TEST_SOURCES
|
|||||||
test_parse_known_args.cpp
|
test_parse_known_args.cpp
|
||||||
test_equals_form.cpp
|
test_equals_form.cpp
|
||||||
test_prefix_chars.cpp
|
test_prefix_chars.cpp
|
||||||
test_hidden_alias.cpp
|
|
||||||
)
|
)
|
||||||
set_source_files_properties(main.cpp
|
set_source_files_properties(main.cpp
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
36
test/test_hidden_argument.cpp
Normal file
36
test/test_hidden_argument.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifdef WITH_MODULE
|
||||||
|
import argparse;
|
||||||
|
#else
|
||||||
|
#include <argparse/argparse.hpp>
|
||||||
|
#endif
|
||||||
|
#include <doctest.hpp>
|
||||||
|
|
||||||
|
using doctest::test_suite;
|
||||||
|
|
||||||
|
TEST_CASE("Test setting a hidden argument" * test_suite("hidden_argument")) {
|
||||||
|
argparse::ArgumentParser program("program");
|
||||||
|
program.add_argument("--hidden").flag().hidden();
|
||||||
|
program.add_argument("--regular").flag();
|
||||||
|
program.add_argument("regular_positional");
|
||||||
|
// only makes sense if last and optional...
|
||||||
|
program.add_argument("hidden_positional").nargs(0, 1).hidden();
|
||||||
|
|
||||||
|
program.parse_args({"./test.exe", "--hidden", "--regular",
|
||||||
|
"regular_positional_val", "hidden_positional_val"});
|
||||||
|
REQUIRE(program.get<bool>("--hidden") == true);
|
||||||
|
REQUIRE(program.get<bool>("--regular") == true);
|
||||||
|
REQUIRE(program.get<std::string>("regular_positional") ==
|
||||||
|
"regular_positional_val");
|
||||||
|
REQUIRE(program.get<std::string>("hidden_positional") ==
|
||||||
|
"hidden_positional_val");
|
||||||
|
|
||||||
|
REQUIRE(program.usage() ==
|
||||||
|
"Usage: program [--help] [--version] [--regular] regular_positional");
|
||||||
|
|
||||||
|
std::ostringstream s;
|
||||||
|
s << program;
|
||||||
|
// std::cout << "DEBUG:" << s.str() << std::endl;
|
||||||
|
REQUIRE(s.str().find("hidden") == std::string::npos);
|
||||||
|
REQUIRE(s.str().find("--regular") != std::string::npos);
|
||||||
|
REQUIRE(s.str().find("regular_positional") != std::string::npos);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user