aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/getopt/small/last_getopt_opt.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/getopt/small/last_getopt_opt.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/getopt/small/last_getopt_opt.h')
-rw-r--r--library/cpp/getopt/small/last_getopt_opt.h812
1 files changed, 812 insertions, 0 deletions
diff --git a/library/cpp/getopt/small/last_getopt_opt.h b/library/cpp/getopt/small/last_getopt_opt.h
new file mode 100644
index 0000000000..a8dd5adca9
--- /dev/null
+++ b/library/cpp/getopt/small/last_getopt_opt.h
@@ -0,0 +1,812 @@
+#pragma once
+
+#include "completer.h"
+#include "last_getopt_handlers.h"
+
+#include <util/string/split.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 <stdarg.h>
+
+namespace NLastGetopt {
+ enum EHasArg {
+ NO_ARGUMENT,
+ REQUIRED_ARGUMENT,
+ OPTIONAL_ARGUMENT,
+ DEFAULT_HAS_ARG = REQUIRED_ARGUMENT
+ };
+
+ /**
+ * NLastGetopt::TOpt is a storage of data about exactly one program option.
+ * The data is: parse politics and help information.
+ *
+ * The help information consists of following:
+ * hidden or visible in help information
+ * help string
+ * argument name
+ *
+ * Parse politics is determined by following parameters:
+ * argument parse politics: no/optional/required/
+ * option existence: required or optional
+ * handlers. See detailed documentation: <TODO:link>
+ * default value: if the option has argument, but the option is ommited,
+ * then the <default value> is used as the value of the argument
+ * optional value: if the option has optional-argument, the option is present in parsed string,
+ * but the argument is omitted, then <optional value is used>
+ * in case of "not given <optional value>, omited optional argument" the <default value> is used
+ * user value: allows to store arbitary pointer for handlers
+ */
+ class TOpt {
+ public:
+ typedef TVector<char> TShortNames;
+ typedef TVector<TString> TLongNames;
+
+ protected:
+ TShortNames Chars_;
+ TLongNames LongNames_;
+
+ private:
+ typedef TMaybe<TString> TdOptVal;
+ typedef TVector<TSimpleSharedPtr<IOptHandler>> TOptHandlers;
+
+ public:
+ bool Hidden_ = false; // is visible in help
+ TString ArgTitle_; // the name of argument in help output
+ TString Help_; // the help string
+ TString CompletionHelp_; // the help string that's used in completion script, a shorter version of Help_
+ TString CompletionArgHelp_; // the description of argument in completion script
+
+ EHasArg HasArg_ = DEFAULT_HAS_ARG; // the argument parsing politics
+ bool Required_ = false; // option existence politics
+
+ bool AllowMultipleCompletion_ = false; // let the completer know that this option can occur more than once
+
+ bool DisableCompletionForOptions_ = false;
+ bool DisableCompletionForFreeArgs_ = false;
+ TShortNames DisableCompletionForChar_;
+ TLongNames DisableCompletionForLongName_;
+ TVector<size_t> DisableCompletionForFreeArg_;
+ NComp::ICompleterPtr Completer_;
+
+ private:
+ //Handlers information
+ const void* UserValue_ = nullptr;
+ TdOptVal OptionalValue_;
+ TdOptVal DefaultValue_;
+ TOptHandlers Handlers_;
+
+ public:
+ /**
+ * Checks if given char can be a short name
+ * @param c char to check
+ */
+ static bool IsAllowedShortName(unsigned char c);
+
+ /**
+ * Checks if given string can be a long name
+ * @param name string to check
+ * @param c if given, the first bad charecter will be saved in c
+ */
+ static bool IsAllowedLongName(const TString& name, unsigned char* c = nullptr);
+
+ /**
+ * @return one of the expected representations of the option.
+ * If the option has short names, will return "-<char>"
+ * Otherwise will return "--<long name>"
+ */
+ TString ToShortString() const;
+
+ /**
+ * check if given string is one of the long names
+ *
+ * @param name string to check
+ */
+ bool NameIs(const TString& name) const;
+
+ /**
+ * check if given char is one of the short names
+ *
+ * @param c char to check
+ */
+ bool CharIs(char c) const;
+
+ /**
+ * If string has long names - will return one of them
+ * Otherwise will throw
+ */
+ TString GetName() const;
+
+ /**
+ * adds short alias for the option
+ *
+ * @param c new short name
+ *
+ * @return self
+ */
+ TOpt& AddShortName(unsigned char c);
+
+ /**
+ * return all short names of the option
+ */
+ const TShortNames& GetShortNames() const {
+ return Chars_;
+ }
+
+ /**
+ * adds long alias for the option
+ *
+ * @param name new long name
+ *
+ * @return self
+ */
+ TOpt& AddLongName(const TString& name);
+
+ /**
+ * return all long names of the option
+ */
+ const TLongNames& GetLongNames() const {
+ return LongNames_;
+ }
+
+ /**
+ * @return one of short names of the opt. If there is no short names exception is raised.
+ */
+ char GetChar() const;
+
+ /**
+ * @return one of short names of the opt. If there is no short names '\0' returned.
+ */
+ char GetCharOr0() const;
+
+ /**
+ * @returns argument parsing politics
+ */
+ const EHasArg& GetHasArg() const {
+ return HasArg_;
+ }
+
+ /**
+ * sets argument parsing politics
+ *
+ * Note: its better use one of RequiredArgument/NoArgument/OptionalArgument methods
+ *
+ * @param hasArg new argument parsing mode
+ * @return self
+ */
+ TOpt& HasArg(EHasArg hasArg) {
+ HasArg_ = hasArg;
+ return *this;
+ }
+
+ /**
+ * @returns argument title
+ */
+ TString GetArgTitle() const {
+ return ArgTitle_;
+ }
+
+ /**
+ * sets argument parsing politics into REQUIRED_ARGUMENT
+ *
+ * @param title the new name of argument in help output
+ * @return self
+ */
+ TOpt& RequiredArgument(const TString& title = "") {
+ ArgTitle_ = title;
+ return HasArg(REQUIRED_ARGUMENT);
+ }
+
+ /**
+ * sets argument parsing politics into NO_ARGUMENT
+ *
+ * @return self
+ */
+ TOpt& NoArgument() {
+ return HasArg(NO_ARGUMENT);
+ }
+
+ /**
+ * sets argument parsing politics into OPTIONAL_ARGUMENT
+ * for details see NLastGetopt::TOpt
+ *
+ * @param title the new name of argument in help output
+ * @return self
+ */
+ TOpt& OptionalArgument(const TString& title = "") {
+ ArgTitle_ = title;
+ return HasArg(OPTIONAL_ARGUMENT);
+ }
+
+ /**
+ * sets argument parsing politics into OPTIONAL_ARGUMENT
+ * sets the <optional value> into given
+ *
+ * for details see NLastGetopt::TOpt
+ *
+ * @param val the new <optional value>
+ * @param title the new name of argument in help output
+ * @return self
+ */
+ TOpt& OptionalValue(const TString& val, const TString& title = "") {
+ OptionalValue_ = val;
+ return OptionalArgument(title);
+ }
+
+ /**
+ * checks if "argument parsing politics" is OPTIONAL_ARGUMENT and the <optional value> is set.
+ */
+ bool HasOptionalValue() const {
+ return OPTIONAL_ARGUMENT == HasArg_ && OptionalValue_;
+ }
+
+ /**
+ * @return optional value
+ * throws exception if optional value wasn't set
+ */
+ const TString& GetOptionalValue() const {
+ return *OptionalValue_;
+ }
+
+ /**
+ * sets <default value>
+ * @return self
+ */
+ template <typename T>
+ TOpt& DefaultValue(const T& val) {
+ DefaultValue_ = ToString(val);
+ return *this;
+ }
+
+ /**
+ * checks if default value is set.
+ */
+ bool HasDefaultValue() const {
+ return DefaultValue_.Defined();
+ }
+
+ /**
+ * @return default value
+ * throws exception if <default value> wasn't set
+ */
+ const TString& GetDefaultValue() const {
+ return *DefaultValue_;
+ }
+
+ /**
+ * sets the option to be required
+ * @return self
+ */
+ TOpt& Required() {
+ Required_ = true;
+ return *this;
+ }
+
+ /**
+ * sets the option to be optional
+ * @return self
+ */
+ TOpt& Optional() {
+ Required_ = false;
+ return *this;
+ }
+
+ /**
+ * @return true if the option is required
+ */
+ bool IsRequired() const {
+ return Required_;
+ }
+
+ /**
+ * sets the option to be hidden (invisible in help)
+ * @return self
+ */
+ TOpt& Hidden() {
+ Hidden_ = true;
+ return *this;
+ }
+
+ /**
+ * @return true if the option is hidden
+ */
+ bool IsHidden() const {
+ return Hidden_;
+ }
+
+ /**
+ * sets the <user value>
+ * @return self
+ * for details see NLastGetopt::TOpt
+ */
+ TOpt& UserValue(const void* userval) {
+ UserValue_ = userval;
+ return *this;
+ }
+
+ /**
+ * @return user value
+ */
+ const void* UserValue() const {
+ return UserValue_;
+ }
+
+ /**
+ * Set help string that appears with `--help`. Unless `CompletionHelp` is given, this message will also be used
+ * in completion script. In this case, don't make it too long, don't start it with a capital letter and don't
+ * end it with a full stop.
+ *
+ * Note that `Help`, `CompletionHelp` and `CompletionArgHelp` are not the same. `Help` is printed in program
+ * usage (when you call `program --help`), `CompletionHelp` is printed when completer lists available
+ * options, and `CompletionArgHelp` is printed when completer shows available values for the option.
+ *
+ * Example of good help message:
+ *
+ * ```
+ * opts.AddLongOption('t', "timeout")
+ * .Help("specify query timeout in milliseconds")
+ * .CompletionHelp("specify query timeout")
+ * .CompletionArgHelp("query timeout (ms) [default=500]");
+ * ```
+ *
+ * Notice how `Help` and `CompletionArgHelp` have units in them, but `CompletionHelp` don't.
+ *
+ * Another good example is the help option:
+ *
+ * ```
+ * opts.AddLongOption('h', "help")
+ * .Help("print this message and exit")
+ * .CompletionHelp("print help message and exit");
+ * ```
+ *
+ * Notice how `Help` mentions 'this message', but `CompletionHelp` mentions just 'help message'.
+ *
+ * See more on completion descriptions codestyle:
+ * https://github.com/zsh-users/zsh/blob/master/Etc/completion-style-guide#L43
+ */
+ TOpt& Help(const TString& help) {
+ Help_ = help;
+ return *this;
+ }
+
+ /**
+ * Get help string.
+ */
+ const TString& GetHelp() const {
+ return Help_;
+ }
+
+ /**
+ * Set help string that appears when argument completer lists available options.
+ *
+ * See `Help` function for info on how this is different from setting `Help` and `CompletionArgHelp`.
+ *
+ * Use shorter messages for this message. Don't start them with a capital letter and don't end them
+ * with a full stop. De aware that argument name and default value will not be printed by completer.
+ *
+ * In zsh, these messages will look like this:
+ *
+ * ```
+ * $ program -<tab><tab>
+ * -- option --
+ * --help -h -- print help message and exit
+ * --timeout -t -- specify query timeout
+ * ```
+ */
+ TOpt& CompletionHelp(const TString& help) {
+ CompletionHelp_ = help;
+ return *this;
+ }
+
+ /**
+ * Get help string that appears when argument completer lists available options.
+ */
+ const TString& GetCompletionHelp() const {
+ return CompletionHelp_ ? CompletionHelp_ : Help_;
+ }
+
+ /**
+ * Set help string that appears when completer suggests available values.
+ *
+ * See `Help` function for info on how this is different from setting `Help` and `CompletionHelp`.
+ *
+ * In zsh, these messages will look like this:
+ *
+ * ```
+ * $ program --timeout <tab><tab>
+ * -- query timeout (ms) [default=500] --
+ * 50 100 250 500 1000
+ * ```
+ */
+ TOpt& CompletionArgHelp(const TString& help) {
+ CompletionArgHelp_ = help;
+ return *this;
+ }
+
+ /**
+ * @return argument help string for use in completion script.
+ */
+ const TString& GetCompletionArgHelp() const {
+ return CompletionArgHelp_ ? CompletionArgHelp_ : ArgTitle_;
+ }
+
+ /**
+ * Let the completer know that this option can occur more than once.
+ */
+ TOpt& AllowMultipleCompletion(bool allowMultipleCompletion = true) {
+ AllowMultipleCompletion_ = allowMultipleCompletion;
+ return *this;
+ }
+
+ /**
+ * @return true if completer will offer completion for this option multiple times.
+ */
+ bool MultipleCompletionAllowed() const {
+ return AllowMultipleCompletion_;
+ }
+
+ /**
+ * Tell the completer to disable further completion if this option is present.
+ * This is useful for options like `--help`.
+ *
+ * Note: this only works in zsh.
+ *
+ * @return self
+ */
+ TOpt& IfPresentDisableCompletion(bool value = true) {
+ IfPresentDisableCompletionForOptions(value);
+ IfPresentDisableCompletionForFreeArgs(value);
+ return *this;
+ }
+
+ /**
+ * Tell the completer to disable completion for all options if this option is already present in the input.
+ * Free arguments will still be completed.
+ *
+ * Note: this only works in zsh.
+ *
+ * @return self
+ */
+ TOpt& IfPresentDisableCompletionForOptions(bool value = true) {
+ DisableCompletionForOptions_ = value;
+ return *this;
+ }
+
+ /**
+ * Tell the completer to disable option `c` if this option is already present in the input.
+ * For example, if you have two options `-a` and `-r` that are mutually exclusive, disable `-r` for `-a` and
+ * disable `-a` for `-r`, like this:
+ *
+ * ```
+ * opts.AddLongOption('a', "acquire").IfPresentDisableCompletionFor('r');
+ * opts.AddLongOption('r', "release").IfPresentDisableCompletionFor('a');
+ * ```
+ *
+ * This way, if user enabled option `-a`, completer will not suggest option `-r`.
+ *
+ * Note that we don't have to disable all flags for a single option. That is, disabling `-r` in the above
+ * example disables `--release` automatically.
+ *
+ * Note: this only works in zsh.
+ *
+ * @param c char option that should be disabled when completer hits this option.
+ */
+ TOpt& IfPresentDisableCompletionFor(char c) {
+ DisableCompletionForChar_.push_back(c);
+ return *this;
+ }
+
+ /**
+ * Like `IfPresentDisableCompletionFor(char c)`, but for long options.
+ */
+ TOpt& IfPresentDisableCompletionFor(const TString& name) {
+ DisableCompletionForLongName_.push_back(name);
+ return *this;
+ }
+
+ /**
+ * Like `IfPresentDisableCompletionFor(char c)`, but for long options.
+ */
+ TOpt& IfPresentDisableCompletionFor(const TOpt& opt);
+
+ /**
+ * Tell the completer to disable completion for the given free argument if this option is present.
+ *
+ * Note: this only works in zsh.
+ *
+ * @param arg index of free arg
+ */
+ TOpt& IfPresentDisableCompletionForFreeArg(size_t index) {
+ DisableCompletionForFreeArg_.push_back(index);
+ return *this;
+ }
+
+ /**
+ * Assign a completer for this option.
+ */
+ TOpt& Completer(NComp::ICompleterPtr completer) {
+ Completer_ = std::move(completer);
+ return *this;
+ }
+
+ /**
+ * Tell the completer to disable completion for the all free arguments if this option is present.
+ *
+ * Note: this only works in zsh.
+ */
+ TOpt& IfPresentDisableCompletionForFreeArgs(bool value = true) {
+ DisableCompletionForFreeArgs_ = value;
+ return *this;
+ }
+
+ /**
+ * Run handlers for this option.
+ */
+ void FireHandlers(const TOptsParser* parser) const;
+
+ private:
+ TOpt& HandlerImpl(IOptHandler* handler) {
+ Handlers_.push_back(handler);
+ return *this;
+ }
+
+ public:
+ template <typename TpFunc>
+ TOpt& Handler0(TpFunc func) { // functor taking no parameters
+ return HandlerImpl(new NPrivate::THandlerFunctor0<TpFunc>(func));
+ }
+
+ template <typename TpFunc>
+ TOpt& Handler1(TpFunc func) { // functor taking one parameter
+ return HandlerImpl(new NPrivate::THandlerFunctor1<TpFunc>(func));
+ }
+ template <typename TpArg, typename TpFunc>
+ TOpt& Handler1T(TpFunc func) {
+ return HandlerImpl(new NPrivate::THandlerFunctor1<TpFunc, TpArg>(func));
+ }
+ template <typename TpArg, typename TpFunc>
+ TOpt& Handler1T(const TpArg& def, TpFunc func) {
+ return HandlerImpl(new NPrivate::THandlerFunctor1<TpFunc, TpArg>(func, def));
+ }
+ template <typename TpArg, typename TpArg2, typename TpFunc>
+ TOpt& Handler1T2(const TpArg2& def, TpFunc func) {
+ return HandlerImpl(new NPrivate::THandlerFunctor1<TpFunc, TpArg>(func, def));
+ }
+
+ TOpt& Handler(void (*f)()) {
+ return Handler0(f);
+ }
+ TOpt& Handler(void (*f)(const TOptsParser*)) {
+ return Handler1(f);
+ }
+
+ TOpt& Handler(TAutoPtr<IOptHandler> handler) {
+ return HandlerImpl(handler.Release());
+ }
+
+ template <typename T> // T extends IOptHandler
+ TOpt& Handler(TAutoPtr<T> handler) {
+ return HandlerImpl(handler.Release());
+ }
+
+ // Stores FromString<T>(arg) in *target
+ // T maybe anything with FromString<T>(const TStringBuf&) defined
+ template <typename TpVal, typename T>
+ TOpt& StoreResultT(T* target) {
+ return Handler1T<TpVal>(NPrivate::TStoreResultFunctor<T, TpVal>(target));
+ }
+
+ template <typename T>
+ TOpt& StoreResult(T* target) {
+ return StoreResultT<T>(target);
+ }
+
+ // Uses TMaybe<T> to store FromString<T>(arg)
+ template <typename T>
+ TOpt& StoreResult(TMaybe<T>* target) {
+ return StoreResultT<T>(target);
+ }
+
+ template <typename TpVal, typename T, typename TpDef>
+ TOpt& StoreResultT(T* target, const TpDef& def) {
+ return Handler1T<TpVal>(def, NPrivate::TStoreResultFunctor<T, TpVal>(target));
+ }
+
+ template <typename T, typename TpDef>
+ TOpt& StoreResult(T* target, const TpDef& def) {
+ return StoreResultT<T>(target, def);
+ }
+
+ template <typename T>
+ TOpt& StoreResultDef(T* target) {
+ DefaultValue_ = ToString(*target);
+ return StoreResultT<T>(target, *target);
+ }
+
+ template <typename T, typename TpDef>
+ TOpt& StoreResultDef(T* target, const TpDef& def) {
+ DefaultValue_ = ToString(def);
+ return StoreResultT<T>(target, def);
+ }
+
+ // Sugar for storing flags (option without arguments) to boolean vars
+ TOpt& SetFlag(bool* target) {
+ return DefaultValue("0").StoreResult(target, true);
+ }
+
+ // Similar to store_true in Python's argparse
+ TOpt& StoreTrue(bool* target) {
+ return NoArgument().SetFlag(target);
+ }
+
+ template <typename TpVal, typename T, typename TpFunc>
+ TOpt& StoreMappedResultT(T* target, const TpFunc& func) {
+ return Handler1T<TpVal>(NPrivate::TStoreMappedResultFunctor<T, TpFunc, TpVal>(target, func));
+ }
+
+ template <typename T, typename TpFunc>
+ TOpt& StoreMappedResult(T* target, const TpFunc& func) {
+ return StoreMappedResultT<T>(target, func);
+ }
+
+ // Stores given value in *target if the option is present.
+ // TValue must be a copyable type, constructible from TParam.
+ // T must be a copyable type, assignable from TValue.
+ template <typename TValue, typename T, typename TParam>
+ TOpt& StoreValueT(T* target, const TParam& value) {
+ return Handler1(NPrivate::TStoreValueFunctor<T, TValue>(target, value));
+ }
+
+ // save value as target type
+ template <typename T, typename TParam>
+ TOpt& StoreValue(T* target, const TParam& value) {
+ return StoreValueT<T>(target, value);
+ }
+
+ // save value as its original type (2nd template parameter)
+ template <typename T, typename TValue>
+ TOpt& StoreValue2(T* target, const TValue& value) {
+ return StoreValueT<TValue>(target, value);
+ }
+
+ // Appends FromString<T>(arg) to *target for each argument
+ template <typename T>
+ TOpt& AppendTo(TVector<T>* target) {
+ return Handler1T<T>([target](auto&& value) { target->push_back(std::move(value)); });
+ }
+
+ // Appends FromString<T>(arg) to *target for each argument
+ template <typename T>
+ TOpt& InsertTo(THashSet<T>* target) {
+ return Handler1T<T>([target](auto&& value) { target->insert(std::move(value)); });
+ }
+
+ // Emplaces TString arg to *target for each argument
+ template <typename T>
+ TOpt& EmplaceTo(TVector<T>* target) {
+ return Handler1T<TString>([target](TString arg) { target->emplace_back(std::move(arg)); } );
+ }
+
+ template <class Container>
+ TOpt& SplitHandler(Container* target, const char delim) {
+ return Handler(new NLastGetopt::TOptSplitHandler<Container>(target, delim));
+ }
+
+ template <class Container>
+ TOpt& RangeSplitHandler(Container* target, const char elementsDelim, const char rangesDelim) {
+ return Handler(new NLastGetopt::TOptRangeSplitHandler<Container>(target, elementsDelim, rangesDelim));
+ }
+
+ template <class TpFunc>
+ TOpt& KVHandler(TpFunc func, const char kvdelim = '=') {
+ return Handler(new NLastGetopt::TOptKVHandler<TpFunc>(func, kvdelim));
+ }
+ };
+
+ /**
+ * NLastGetopt::TFreeArgSpec is a storage of data about free argument.
+ * The data is help information and (maybe) linked named argument.
+ *
+ * The help information consists of following:
+ * help string
+ * argument name (title)
+ */
+ struct TFreeArgSpec {
+ TFreeArgSpec() = default;
+ TFreeArgSpec(const TString& title, const TString& help = TString(), bool optional = false)
+ : Title_(title)
+ , Help_(help)
+ , Optional_(optional)
+ {
+ }
+
+ TString Title_;
+ TString Help_;
+ TString CompletionArgHelp_;
+
+ bool Optional_ = false;
+ NComp::ICompleterPtr Completer_ = nullptr;
+
+ /**
+ * Check if this argument have default values for its title and help.
+ */
+ bool IsDefault() const {
+ return Title_.empty() && Help_.empty();
+ }
+
+ /**
+ * Set argument title.
+ */
+ TFreeArgSpec& Title(TString title) {
+ Title_ = std::move(title);
+ return *this;
+ }
+
+ /**
+ * Get argument title. If title is empty, returns a default one.
+ */
+ TStringBuf GetTitle(TStringBuf defaultTitle) const {
+ return Title_ ? TStringBuf(Title_) : defaultTitle;
+ }
+
+ /**
+ * Set help string that appears with `--help`. Unless `CompletionHelp` is given, this message will also be used
+ * in completion script. In this case, don't make it too long, don't start it with a capital letter and don't
+ * end it with a full stop.
+ *
+ * See `TOpt::Help` function for more on how `Help` and `CompletionArgHelp` differ one from another.
+ */
+ TFreeArgSpec& Help(TString help) {
+ Help_ = std::move(help);
+ return *this;
+ }
+
+ /**
+ * Get help string that appears with `--help`.
+ */
+ TStringBuf GetHelp() const {
+ return Help_;
+ }
+
+ /**
+ * Set help string that appears when completer suggests values fot this argument.
+ */
+ TFreeArgSpec& CompletionArgHelp(TString completionArgHelp) {
+ CompletionArgHelp_ = std::move(completionArgHelp);
+ return *this;
+ }
+
+ /**
+ * Get help string that appears when completer suggests values fot this argument.
+ */
+ TStringBuf GetCompletionArgHelp(TStringBuf defaultTitle) const {
+ return CompletionArgHelp_ ? TStringBuf(CompletionArgHelp_) : GetTitle(defaultTitle);
+ }
+
+ /**
+ * Mark this argument as optional. This setting only affects help printing, it doesn't affect parsing.
+ */
+ TFreeArgSpec& Optional(bool optional = true) {
+ Optional_ = optional;
+ return *this;
+ }
+
+ /**
+ * Check if this argument is optional.
+ */
+ bool IsOptional() const {
+ return Optional_;
+ }
+
+ /**
+ * Set completer for this argument.
+ */
+ TFreeArgSpec& Completer(NComp::ICompleterPtr completer) {
+ Completer_ = std::move(completer);
+ return *this;
+ }
+ };
+}