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)
|
||||
* [Subcommands](#subcommands)
|
||||
* [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)
|
||||
* [Custom Prefix Characters](#custom-prefix-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
|
||||
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
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
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_is_optional((is_optional(a[I], prefix_chars) || ...)),
|
||||
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]), ...);
|
||||
std::sort(
|
||||
m_names.begin(), m_names.end(), [](const auto &lhs, const auto &rhs) {
|
||||
@ -745,6 +745,12 @@ public:
|
||||
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>
|
||||
auto scan() -> std::enable_if_t<std::is_arithmetic_v<T>, Argument &> {
|
||||
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_repeatable : 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
|
||||
int m_usage_newline_counter = 0;
|
||||
std::size_t m_group_idx = 0;
|
||||
@ -1910,22 +1917,30 @@ public:
|
||||
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";
|
||||
}
|
||||
|
||||
for (const auto &argument : parser.m_positional_arguments) {
|
||||
if (!argument.m_is_hidden) {
|
||||
stream.width(static_cast<std::streamsize>(longest_arg_length));
|
||||
stream << argument;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parser.m_optional_arguments.empty()) {
|
||||
stream << (parser.m_positional_arguments.empty() ? "" : "\n")
|
||||
stream << (!has_visible_positional_args ? "" : "\n")
|
||||
<< "Optional arguments:\n";
|
||||
}
|
||||
|
||||
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 << argument;
|
||||
}
|
||||
@ -1934,7 +1949,7 @@ public:
|
||||
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";
|
||||
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 << argument;
|
||||
}
|
||||
@ -2006,6 +2021,9 @@ public:
|
||||
const MutuallyExclusiveGroup *cur_mutex = nullptr;
|
||||
int usage_newline_counter = -1;
|
||||
for (const auto &argument : this->m_optional_arguments) {
|
||||
if (argument.m_is_hidden) {
|
||||
continue;
|
||||
}
|
||||
if (multiline_usage) {
|
||||
if (argument.m_group_idx != group_idx) {
|
||||
continue;
|
||||
@ -2078,6 +2096,9 @@ public:
|
||||
}
|
||||
// Put positional arguments after the optionals
|
||||
for (const auto &argument : this->m_positional_arguments) {
|
||||
if (argument.m_is_hidden) {
|
||||
continue;
|
||||
}
|
||||
const std::string pos_arg = !argument.m_metavar.empty()
|
||||
? argument.m_metavar
|
||||
: argument.m_names.front();
|
||||
|
@ -37,6 +37,8 @@ file(GLOB ARGPARSE_TEST_SOURCES
|
||||
test_error_reporting.cpp
|
||||
test_get.cpp
|
||||
test_help.cpp
|
||||
test_hidden_alias.cpp
|
||||
test_hidden_argument.cpp
|
||||
test_invalid_arguments.cpp
|
||||
test_is_used.cpp
|
||||
test_issue_37.cpp
|
||||
@ -56,7 +58,6 @@ file(GLOB ARGPARSE_TEST_SOURCES
|
||||
test_parse_known_args.cpp
|
||||
test_equals_form.cpp
|
||||
test_prefix_chars.cpp
|
||||
test_hidden_alias.cpp
|
||||
)
|
||||
set_source_files_properties(main.cpp
|
||||
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