diff options
Diffstat (limited to 'absl/flags/internal')
-rw-r--r-- | absl/flags/internal/commandlineflag.cc | 2 | ||||
-rw-r--r-- | absl/flags/internal/flag.cc | 4 | ||||
-rw-r--r-- | absl/flags/internal/flag.h | 31 | ||||
-rw-r--r-- | absl/flags/internal/flag_msvc.inc | 2 | ||||
-rw-r--r-- | absl/flags/internal/parse.h | 17 | ||||
-rw-r--r-- | absl/flags/internal/usage.cc | 52 | ||||
-rw-r--r-- | absl/flags/internal/usage.h | 42 | ||||
-rw-r--r-- | absl/flags/internal/usage_test.cc | 94 |
8 files changed, 159 insertions, 85 deletions
diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc index 4482955c..3c114d10 100644 --- a/absl/flags/internal/commandlineflag.cc +++ b/absl/flags/internal/commandlineflag.cc @@ -19,7 +19,7 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace flags_internal { -FlagStateInterface::~FlagStateInterface() {} +FlagStateInterface::~FlagStateInterface() = default; } // namespace flags_internal ABSL_NAMESPACE_END diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc index cc656f9d..65d0e58f 100644 --- a/absl/flags/internal/flag.cc +++ b/absl/flags/internal/flag.cc @@ -197,7 +197,7 @@ void FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id, FlagFastTypeId lhs_type_id = flags_internal::FastTypeId(op_); // `rhs_type_id` is the fast type id corresponding to the declaration - // visibile at the call site. `lhs_type_id` is the fast type id + // visible at the call site. `lhs_type_id` is the fast type id // corresponding to the type specified in flag definition. They must match // for this operation to be well-defined. if (ABSL_PREDICT_TRUE(lhs_type_id == rhs_type_id)) return; @@ -238,7 +238,7 @@ void FlagImpl::StoreValue(const void* src) { switch (ValueStorageKind()) { case FlagValueStorageKind::kValueAndInitBit: case FlagValueStorageKind::kOneWordAtomic: { - // Load the current value to avoid setting 'init' bit manualy. + // Load the current value to avoid setting 'init' bit manually. int64_t one_word_val = OneWordValue().load(std::memory_order_acquire); std::memcpy(&one_word_val, src, Sizeof(op_)); OneWordValue().store(one_word_val, std::memory_order_release); diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index 6154638c..b41f9a69 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -121,7 +121,7 @@ inline void* Clone(FlagOpFn op, const void* obj) { flags_internal::CopyConstruct(op, obj, res); return res; } -// Returns true if parsing of input text is successfull. +// Returns true if parsing of input text is successful. inline bool Parse(FlagOpFn op, absl::string_view text, void* dst, std::string* error) { return op(FlagOp::kParse, &text, dst, error) != nullptr; @@ -139,12 +139,12 @@ inline size_t Sizeof(FlagOpFn op) { return static_cast<size_t>(reinterpret_cast<intptr_t>( op(FlagOp::kSizeof, nullptr, nullptr, nullptr))); } -// Returns fast type id coresponding to the value type. +// Returns fast type id corresponding to the value type. inline FlagFastTypeId FastTypeId(FlagOpFn op) { return reinterpret_cast<FlagFastTypeId>( op(FlagOp::kFastTypeId, nullptr, nullptr, nullptr)); } -// Returns fast type id coresponding to the value type. +// Returns fast type id corresponding to the value type. inline const std::type_info* RuntimeTypeId(FlagOpFn op) { return reinterpret_cast<const std::type_info*>( op(FlagOp::kRuntimeTypeId, nullptr, nullptr, nullptr)); @@ -223,12 +223,12 @@ extern const char kStrippedFlagHelp[]; // first overload if possible. If help message is evaluatable on constexpr // context We'll be able to make FixedCharArray out of it and we'll choose first // overload. In this case the help message expression is immediately evaluated -// and is used to construct the absl::Flag. No additionl code is generated by +// and is used to construct the absl::Flag. No additional code is generated by // ABSL_FLAG Otherwise SFINAE kicks in and first overload is dropped from the // consideration, in which case the second overload will be used. The second // overload does not attempt to evaluate the help message expression -// immediately and instead delays the evaluation by returing the function -// pointer (&T::NonConst) genering the help message when necessary. This is +// immediately and instead delays the evaluation by returning the function +// pointer (&T::NonConst) generating the help message when necessary. This is // evaluatable in constexpr context, but the cost is an extra function being // generated in the ABSL_FLAG code. template <typename Gen, size_t N> @@ -308,19 +308,20 @@ constexpr int64_t UninitializedFlagValue() { } template <typename T> -using FlagUseValueAndInitBitStorage = std::integral_constant< - bool, absl::type_traits_internal::is_trivially_copyable<T>::value && - std::is_default_constructible<T>::value && (sizeof(T) < 8)>; +using FlagUseValueAndInitBitStorage = + std::integral_constant<bool, std::is_trivially_copyable<T>::value && + std::is_default_constructible<T>::value && + (sizeof(T) < 8)>; template <typename T> -using FlagUseOneWordStorage = std::integral_constant< - bool, absl::type_traits_internal::is_trivially_copyable<T>::value && - (sizeof(T) <= 8)>; +using FlagUseOneWordStorage = + std::integral_constant<bool, std::is_trivially_copyable<T>::value && + (sizeof(T) <= 8)>; template <class T> -using FlagUseSequenceLockStorage = std::integral_constant< - bool, absl::type_traits_internal::is_trivially_copyable<T>::value && - (sizeof(T) > 8)>; +using FlagUseSequenceLockStorage = + std::integral_constant<bool, std::is_trivially_copyable<T>::value && + (sizeof(T) > 8)>; enum class FlagValueStorageKind : uint8_t { kValueAndInitBit = 0, diff --git a/absl/flags/internal/flag_msvc.inc b/absl/flags/internal/flag_msvc.inc index c31bd27f..614d09fd 100644 --- a/absl/flags/internal/flag_msvc.inc +++ b/absl/flags/internal/flag_msvc.inc @@ -29,7 +29,7 @@ // second level of protection is a global Mutex, so if two threads attempt to // construct the flag concurrently only one wins. // -// This solution is based on a recomendation here: +// This solution is based on a recommendation here: // https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html?childToView=648454#comment-648454 namespace flags_internal { diff --git a/absl/flags/internal/parse.h b/absl/flags/internal/parse.h index 0a7012fc..10c531b8 100644 --- a/absl/flags/internal/parse.h +++ b/absl/flags/internal/parse.h @@ -16,11 +16,14 @@ #ifndef ABSL_FLAGS_INTERNAL_PARSE_H_ #define ABSL_FLAGS_INTERNAL_PARSE_H_ +#include <iostream> +#include <ostream> #include <string> #include <vector> #include "absl/base/config.h" #include "absl/flags/declare.h" +#include "absl/flags/internal/usage.h" #include "absl/strings/string_view.h" ABSL_DECLARE_FLAG(std::vector<std::string>, flagfile); @@ -32,7 +35,6 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace flags_internal { -enum class ArgvListAction { kRemoveParsedArgs, kKeepParsedArgs }; enum class UsageFlagsAction { kHandleUsage, kIgnoreUsage }; enum class OnUndefinedFlag { kIgnoreUndefined, @@ -40,10 +42,15 @@ enum class OnUndefinedFlag { kAbortIfUndefined }; -std::vector<char*> ParseCommandLineImpl(int argc, char* argv[], - ArgvListAction arg_list_act, - UsageFlagsAction usage_flag_act, - OnUndefinedFlag on_undef_flag); +// This is not a public interface. This interface exists to expose the ability +// to change help output stream in case of parsing errors. This is used by +// internal unit tests to validate expected outputs. +// When this was written, `EXPECT_EXIT` only supported matchers on stderr, +// but not on stdout. +std::vector<char*> ParseCommandLineImpl( + int argc, char* argv[], UsageFlagsAction usage_flag_action, + OnUndefinedFlag undef_flag_action, + std::ostream& error_help_output = std::cout); // -------------------------------------------------------------------- // Inspect original command line diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc index 5efc7b07..13852e14 100644 --- a/absl/flags/internal/usage.cc +++ b/absl/flags/internal/usage.cc @@ -18,6 +18,7 @@ #include <stdint.h> #include <algorithm> +#include <cstdlib> #include <functional> #include <iterator> #include <map> @@ -91,8 +92,16 @@ class XMLElement { case '>': out << ">"; break; + case '\n': + case '\v': + case '\f': + case '\t': + out << " "; + break; default: - out << c; + if (IsValidXmlCharacter(static_cast<unsigned char>(c))) { + out << c; + } break; } } @@ -101,6 +110,7 @@ class XMLElement { } private: + static bool IsValidXmlCharacter(unsigned char c) { return c >= 0x20; } absl::string_view tag_; absl::string_view txt_; }; @@ -130,7 +140,7 @@ class FlagHelpPrettyPrinter { for (auto line : absl::StrSplit(str, absl::ByAnyChar("\n\r"))) { if (!tokens.empty()) { // Keep line separators in the input string. - tokens.push_back("\n"); + tokens.emplace_back("\n"); } for (auto token : absl::StrSplit(line, absl::ByAnyChar(" \t"), absl::SkipEmpty())) { @@ -354,8 +364,8 @@ void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format, // -------------------------------------------------------------------- // Checks all the 'usage' command line flags to see if any have been set. // If so, handles them appropriately. -int HandleUsageFlags(std::ostream& out, - absl::string_view program_usage_message) { +HelpMode HandleUsageFlags(std::ostream& out, + absl::string_view program_usage_message) { switch (GetFlagsHelpMode()) { case HelpMode::kNone: break; @@ -363,25 +373,24 @@ int HandleUsageFlags(std::ostream& out, flags_internal::FlagsHelpImpl( out, flags_internal::GetUsageConfig().contains_help_flags, GetFlagsHelpFormat(), program_usage_message); - return 1; + break; case HelpMode::kShort: flags_internal::FlagsHelpImpl( out, flags_internal::GetUsageConfig().contains_helpshort_flags, GetFlagsHelpFormat(), program_usage_message); - return 1; + break; case HelpMode::kFull: flags_internal::FlagsHelp(out, "", GetFlagsHelpFormat(), program_usage_message); - return 1; + break; case HelpMode::kPackage: flags_internal::FlagsHelpImpl( out, flags_internal::GetUsageConfig().contains_helppackage_flags, GetFlagsHelpFormat(), program_usage_message); - - return 1; + break; case HelpMode::kMatch: { std::string substr = GetFlagsHelpMatchSubstr(); @@ -400,20 +409,19 @@ int HandleUsageFlags(std::ostream& out, flags_internal::FlagsHelpImpl( out, filter_cb, HelpFormat::kHumanReadable, program_usage_message); } - - return 1; + break; } case HelpMode::kVersion: if (flags_internal::GetUsageConfig().version_string) out << flags_internal::GetUsageConfig().version_string(); // Unlike help, we may be asking for version in a script, so return 0 - return 0; + break; case HelpMode::kOnlyCheckArgs: - return 0; + break; } - return -1; + return GetFlagsHelpMode(); } // -------------------------------------------------------------------- @@ -521,6 +529,22 @@ bool DeduceUsageFlags(absl::string_view name, absl::string_view value) { return false; } +// -------------------------------------------------------------------- + +void MaybeExit(HelpMode mode) { + switch (mode) { + case flags_internal::HelpMode::kNone: + return; + case flags_internal::HelpMode::kOnlyCheckArgs: + case flags_internal::HelpMode::kVersion: + std::exit(0); + default: // For all the other modes we exit with 1 + std::exit(1); + } +} + +// -------------------------------------------------------------------- + } // namespace flags_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/internal/usage.h b/absl/flags/internal/usage.h index c0bcac57..a96cbf38 100644 --- a/absl/flags/internal/usage.h +++ b/absl/flags/internal/usage.h @@ -17,11 +17,11 @@ #define ABSL_FLAGS_INTERNAL_USAGE_H_ #include <iosfwd> +#include <ostream> #include <string> #include "absl/base/config.h" #include "absl/flags/commandlineflag.h" -#include "absl/flags/declare.h" #include "absl/strings/string_view.h" // -------------------------------------------------------------------- @@ -36,6 +36,18 @@ enum class HelpFormat { kHumanReadable, }; +// The kind of usage help requested. +enum class HelpMode { + kNone, + kImportant, + kShort, + kFull, + kPackage, + kMatch, + kVersion, + kOnlyCheckArgs +}; + // Streams the help message describing `flag` to `out`. // The default value for `flag` is included in the output. void FlagHelp(std::ostream& out, const CommandLineFlag& flag, @@ -57,28 +69,18 @@ void FlagsHelp(std::ostream& out, absl::string_view filter, // If any of the 'usage' related command line flags (listed on the bottom of // this file) has been set this routine produces corresponding help message in -// the specified output stream and returns: -// 0 - if "version" or "only_check_flags" flags were set and handled. -// 1 - if some other 'usage' related flag was set and handled. -// -1 - if no usage flags were set on a commmand line. -// Non negative return values are expected to be used as an exit code for a -// binary. -int HandleUsageFlags(std::ostream& out, - absl::string_view program_usage_message); +// the specified output stream and returns HelpMode that was handled. Otherwise +// it returns HelpMode::kNone. +HelpMode HandleUsageFlags(std::ostream& out, + absl::string_view program_usage_message); // -------------------------------------------------------------------- -// Globals representing usage reporting flags +// Encapsulates the logic of exiting the binary depending on handled help mode. -enum class HelpMode { - kNone, - kImportant, - kShort, - kFull, - kPackage, - kMatch, - kVersion, - kOnlyCheckArgs -}; +void MaybeExit(HelpMode mode); + +// -------------------------------------------------------------------- +// Globals representing usage reporting flags // Returns substring to filter help output (--help=substr argument) std::string GetFlagsHelpMatchSubstr(); diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc index 209a7be9..6847386f 100644 --- a/absl/flags/internal/usage_test.cc +++ b/absl/flags/internal/usage_test.cc @@ -24,7 +24,6 @@ #include "gtest/gtest.h" #include "absl/flags/flag.h" #include "absl/flags/internal/parse.h" -#include "absl/flags/internal/path_util.h" #include "absl/flags/internal/program_name.h" #include "absl/flags/reflection.h" #include "absl/flags/usage.h" @@ -40,6 +39,8 @@ ABSL_FLAG(double, usage_reporting_test_flag_03, 1.03, "usage_reporting_test_flag_03 help message"); ABSL_FLAG(int64_t, usage_reporting_test_flag_04, 1000000000000004L, "usage_reporting_test_flag_04 help message"); +ABSL_FLAG(std::string, usage_reporting_test_flag_07, "\r\n\f\v\a\b\t ", + "usage_reporting_test_flag_07 help \r\n\f\v\a\b\t "); static const char kTestUsageMessage[] = "Custom usage message"; @@ -204,8 +205,12 @@ TEST_F(UsageReportingTest, TestFlagsHelpHRF) { Some more help. Even more long long long long long long long long long long long long help - message.); default: ""; + message.); default: "";)" + + "\n --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 " + "help\n\n \f\v\a\b ); default: \"\r\n\f\v\a\b\t \";\n" + R"( Try --helpfull to get a list of all flags or --help=substring shows help for flags which include specified substring in either in the name, or description or path. @@ -256,7 +261,8 @@ path. TEST_F(UsageReportingTest, TestNoUsageFlags) { std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), -1); + EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), + flags::HelpMode::kNone); } // -------------------------------------------------------------------- @@ -265,9 +271,11 @@ TEST_F(UsageReportingTest, TestUsageFlag_helpshort) { flags::SetFlagsHelpMode(flags::HelpMode::kShort); std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); - EXPECT_EQ(test_buf.str(), - R"(usage_test: Custom usage message + EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), + flags::HelpMode::kShort); + EXPECT_EQ( + test_buf.str(), + R"(usage_test: Custom usage message Flags from absl/flags/internal/usage_test.cc: --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); @@ -284,8 +292,12 @@ TEST_F(UsageReportingTest, TestUsageFlag_helpshort) { Some more help. Even more long long long long long long long long long long long long help - message.); default: ""; + message.); default: "";)" + + "\n --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 " + "help\n\n \f\v\a\b ); default: \"\r\n\f\v\a\b\t \";\n" + R"( Try --helpfull to get a list of all flags or --help=substring shows help for flags which include specified substring in either in the name, or description or path. @@ -298,9 +310,11 @@ TEST_F(UsageReportingTest, TestUsageFlag_help_simple) { flags::SetFlagsHelpMode(flags::HelpMode::kImportant); std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); - EXPECT_EQ(test_buf.str(), - R"(usage_test: Custom usage message + EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), + flags::HelpMode::kImportant); + EXPECT_EQ( + test_buf.str(), + R"(usage_test: Custom usage message Flags from absl/flags/internal/usage_test.cc: --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); @@ -317,8 +331,12 @@ TEST_F(UsageReportingTest, TestUsageFlag_help_simple) { Some more help. Even more long long long long long long long long long long long long help - message.); default: ""; + message.); default: "";)" + + "\n --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 " + "help\n\n \f\v\a\b ); default: \"\r\n\f\v\a\b\t \";\n" + R"( Try --helpfull to get a list of all flags or --help=substring shows help for flags which include specified substring in either in the name, or description or path. @@ -332,7 +350,8 @@ TEST_F(UsageReportingTest, TestUsageFlag_help_one_flag) { flags::SetFlagsHelpMatchSubstr("usage_reporting_test_flag_06"); std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); + EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), + flags::HelpMode::kMatch); EXPECT_EQ(test_buf.str(), R"(usage_test: Custom usage message @@ -356,9 +375,11 @@ TEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) { flags::SetFlagsHelpMatchSubstr("test_flag"); std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); - EXPECT_EQ(test_buf.str(), - R"(usage_test: Custom usage message + EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), + flags::HelpMode::kMatch); + EXPECT_EQ( + test_buf.str(), + R"(usage_test: Custom usage message Flags from absl/flags/internal/usage_test.cc: --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); @@ -375,8 +396,12 @@ TEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) { Some more help. Even more long long long long long long long long long long long long help - message.); default: ""; + message.); default: "";)" + + "\n --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 " + "help\n\n \f\v\a\b ); default: \"\r\n\f\v\a\b\t \";\n" + R"( Try --helpfull to get a list of all flags or --help=substring shows help for flags which include specified substring in either in the name, or description or path. @@ -389,9 +414,11 @@ TEST_F(UsageReportingTest, TestUsageFlag_helppackage) { flags::SetFlagsHelpMode(flags::HelpMode::kPackage); std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1); - EXPECT_EQ(test_buf.str(), - R"(usage_test: Custom usage message + EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), + flags::HelpMode::kPackage); + EXPECT_EQ( + test_buf.str(), + R"(usage_test: Custom usage message Flags from absl/flags/internal/usage_test.cc: --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); @@ -408,8 +435,12 @@ TEST_F(UsageReportingTest, TestUsageFlag_helppackage) { Some more help. Even more long long long long long long long long long long long long help - message.); default: ""; + message.); default: "";)" + "\n --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 " + "help\n\n \f\v\a\b ); default: \"\r\n\f\v\a\b\t \";\n" + + R"( Try --helpfull to get a list of all flags or --help=substring shows help for flags which include specified substring in either in the name, or description or path. @@ -422,7 +453,8 @@ TEST_F(UsageReportingTest, TestUsageFlag_version) { flags::SetFlagsHelpMode(flags::HelpMode::kVersion); std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0); + EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), + flags::HelpMode::kVersion); #ifndef NDEBUG EXPECT_EQ(test_buf.str(), "usage_test\nDebug build (NDEBUG not #defined)\n"); #else @@ -436,7 +468,8 @@ TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) { flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs); std::stringstream test_buf; - EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0); + EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), + flags::HelpMode::kOnlyCheckArgs); EXPECT_EQ(test_buf.str(), ""); } @@ -447,7 +480,8 @@ TEST_F(UsageReportingTest, TestUsageFlag_helpon) { flags::SetFlagsHelpMatchSubstr("/bla-bla."); std::stringstream test_buf_01; - EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), 1); + EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), + flags::HelpMode::kMatch); EXPECT_EQ(test_buf_01.str(), R"(usage_test: Custom usage message @@ -461,9 +495,11 @@ path. flags::SetFlagsHelpMatchSubstr("/usage_test."); std::stringstream test_buf_02; - EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), 1); - EXPECT_EQ(test_buf_02.str(), - R"(usage_test: Custom usage message + EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), + flags::HelpMode::kMatch); + EXPECT_EQ( + test_buf_02.str(), + R"(usage_test: Custom usage message Flags from absl/flags/internal/usage_test.cc: --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message); @@ -480,8 +516,12 @@ path. Some more help. Even more long long long long long long long long long long long long help - message.); default: ""; + message.); default: "";)" + + "\n --usage_reporting_test_flag_07 (usage_reporting_test_flag_07 " + "help\n\n \f\v\a\b ); default: \"\r\n\f\v\a\b\t \";\n" + R"( Try --helpfull to get a list of all flags or --help=substring shows help for flags which include specified substring in either in the name, or description or path. |