aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhitsedesen <hitsedesen@yandex-team.com>2023-09-07 09:14:47 +0300
committerhitsedesen <hitsedesen@yandex-team.com>2023-09-07 10:21:52 +0300
commit3cd71626b58f2e1958655ea8969d6878ddba51df (patch)
tree86be15b1e67219f4e0439cbbaafce441d3e7747f
parent8662052579e525caf2a824dac5f7589de99ef10c (diff)
downloadydb-3cd71626b58f2e1958655ea8969d6878ddba51df.tar.gz
Add choices to getopt options
-rw-r--r--library/cpp/getopt/last_getopt_demo/demo.cpp21
-rw-r--r--library/cpp/getopt/small/last_getopt_opt.h42
-rw-r--r--library/cpp/getopt/small/last_getopt_opts.cpp8
3 files changed, 60 insertions, 11 deletions
diff --git a/library/cpp/getopt/last_getopt_demo/demo.cpp b/library/cpp/getopt/last_getopt_demo/demo.cpp
index 79426a9cc9..a0e82a936c 100644
--- a/library/cpp/getopt/last_getopt_demo/demo.cpp
+++ b/library/cpp/getopt/last_getopt_demo/demo.cpp
@@ -81,17 +81,16 @@ protected:
.Help("specify HTTP method")
.CompletionArgHelp("http method")
.StoreResult(&ExplicitMethod_)
- .Completer(
- NLastGetopt::NComp::Choice(
- {{"GET", "request representation of the specified resource"},
- {"HEAD", "request response identical to that of GET, but without response body"},
- {"POST", "submit an entry to the specified resource"},
- {"PUT", "replace representation of the specified resource with the request body"},
- {"DELETE", "delete the specified resource"},
- {"CONNECT", "establish a tunnel to the server identified by the target resource"},
- {"OPTIONS", "describe the communication options for the target resource"},
- {"TRACE", "perform a message loop-back test"},
- {"PATCH", "apply partial modifications to the specified resource"}}));
+ .ChoicesWithCompletion({
+ {"GET", "request representation of the specified resource"},
+ {"HEAD", "request response identical to that of GET, but without response body"},
+ {"POST", "submit an entry to the specified resource"},
+ {"PUT", "replace representation of the specified resource with the request body"},
+ {"DELETE", "delete the specified resource"},
+ {"CONNECT", "establish a tunnel to the server identified by the target resource"},
+ {"OPTIONS", "describe the communication options for the target resource"},
+ {"TRACE", "perform a message loop-back test"},
+ {"PATCH", "apply partial modifications to the specified resource"}});
opts.AddLongOption('U', "user-agent")
.RequiredArgument("agent-string")
diff --git a/library/cpp/getopt/small/last_getopt_opt.h b/library/cpp/getopt/small/last_getopt_opt.h
index 4ffdfc394a..32afcb0437 100644
--- a/library/cpp/getopt/small/last_getopt_opt.h
+++ b/library/cpp/getopt/small/last_getopt_opt.h
@@ -4,11 +4,13 @@
#include "last_getopt_handlers.h"
#include <util/string/split.h>
+#include <util/generic/hash_set.h>
#include <util/generic/ptr.h>
#include <util/generic/string.h>
#include <util/generic/maybe.h>
#include <util/generic/vector.h>
#include <util/string/cast.h>
+#include <util/string/join.h>
#include <optional>
#include <stdarg.h>
@@ -80,6 +82,7 @@ namespace NLastGetopt {
TdOptVal OptionalValue_;
TdOptVal DefaultValue_;
TOptHandlers Handlers_;
+ THashSet<TString> Choices_;
public:
/**
@@ -398,6 +401,10 @@ namespace NLastGetopt {
return Help_;
}
+ TString GetChoicesHelp() const {
+ return JoinSeq(", ", Choices_);
+ }
+
/**
* Set help string that appears when argument completer lists available options.
*
@@ -728,6 +735,41 @@ namespace NLastGetopt {
TOpt& KVHandler(TpFunc func, const char kvdelim = '=') {
return Handler(new NLastGetopt::TOptKVHandler<TpFunc>(func, kvdelim));
}
+
+ template <typename TIterator>
+ TOpt& Choices(TIterator begin, TIterator end) {
+ return Choices(THashSet<typename TIterator::value_type>{begin, end});
+ }
+
+ template <typename TValue>
+ TOpt& Choices(THashSet<TValue> choices) {
+ Choices_ = std::move(choices);
+ return Handler1T<TValue>(
+ [this] (const TValue& arg) {
+ if (!Choices_.contains(arg)) {
+ throw TUsageException() << " value '" << arg
+ << "' is not allowed for option '" << GetName() << "'";
+ }
+ });
+ }
+
+ TOpt& Choices(TVector<TString> choices) {
+ return Choices(
+ THashSet<TString>{
+ std::make_move_iterator(choices.begin()),
+ std::make_move_iterator(choices.end())
+ });
+ }
+
+ TOpt& ChoicesWithCompletion(TVector<NComp::TChoice> choices) {
+ Completer(NComp::Choice(choices));
+ THashSet<TString> choicesSet;
+ choicesSet.reserve(choices.size());
+ for (const auto& choice : choices) {
+ choicesSet.insert(choice.Choice);
+ }
+ return Choices(std::move(choicesSet));
+ }
};
/**
diff --git a/library/cpp/getopt/small/last_getopt_opts.cpp b/library/cpp/getopt/small/last_getopt_opts.cpp
index 03c432849f..939d5d59d2 100644
--- a/library/cpp/getopt/small/last_getopt_opts.cpp
+++ b/library/cpp/getopt/small/last_getopt_opts.cpp
@@ -427,6 +427,14 @@ namespace NLastGetopt {
os << Wrap(Wrap_, help, SPad + leftPadding + " ", &lastLineLength, &helpHasParagraphs);
}
+ auto choicesHelp = opt->GetChoicesHelp();
+ if (!choicesHelp.empty()) {
+ if (help) {
+ os << Endl << SPad << leftPadding << " ";
+ }
+ os << "(values: " << choicesHelp << ")";
+ }
+
if (opt->HasDefaultValue()) {
auto quotedDef = QuoteForHelp(opt->GetDefaultValue());
if (helpHasParagraphs) {