123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652 |
- #pragma once
- #include "last_getopt_opt.h"
- #include <library/cpp/colorizer/fwd.h>
- #include <util/generic/map.h>
- namespace NLastGetopt {
- enum EArgPermutation {
- REQUIRE_ORDER,
- PERMUTE,
- RETURN_IN_ORDER,
- DEFAULT_ARG_PERMUTATION = PERMUTE
- };
- /**
- * NLastGetopt::TOpts is a storage of program options' parse rules.
- * It contains information about all options, free args, some parsing options
- * and rules about interaction between options.
- *
- * The main point for defining program options.
- *
- * The parsing rules determined by the following parts:
- * - Arguments permutation. It is expected free args be after named args.
- * This point adjusts how to treat breaking this expectation.
- * if REQUIRE_ORDER is choosen, the exception during parsing will be raised,
- * the special string " -- " will be treated as end of named
- * options: all options after it will be parsed as free args
- * if PERMUTE is choosen, arguments will be rearranged in correct order,
- * if RETURN_IN_ORDER is choosen, all free args will be ommited (TODO: looks very strange)
- * - Using '+' as a prefix instead '--' for long names
- * - Using "-" as a prefix for both short and long names
- * - Allowing unknown options
- *
- */
- class TOpts {
- friend class TOptsParseResult;
- friend class TOptsParser;
- public:
- static constexpr const ui32 UNLIMITED_ARGS = Max<ui32>();
- typedef TVector<TSimpleSharedPtr<TOpt>> TOptsVector;
- TOptsVector Opts_; // infomation about named (short and long) options
- TVector<std::function<void(TStringBuf)>> ArgBindings_;
- EArgPermutation ArgPermutation_ = DEFAULT_ARG_PERMUTATION; // determines how to parse positions of named and free options. See information below.
- bool AllowSingleDashForLong_ = false; //
- bool AllowPlusForLong_ = false; // using '+' instead '--' for long options
- //Allows unknwon options:
- bool AllowUnknownCharOptions_ = false;
- bool AllowUnknownLongOptions_ = false;
- ui32 Wrap_ = 80;
- bool CheckUserTypos_ = false;
- private:
- ui32 FreeArgsMin_; // minimal number of free args
- ui32 FreeArgsMax_; // maximal number of free args
- TMap<ui32, TFreeArgSpec> FreeArgSpecs_; // mapping [free arg position] -> [free arg specification]
- TFreeArgSpec TrailingArgSpec_; // spec for the trailing argument (when arguments are unlimited)
- TString DefaultFreeArgTitle_ = "ARG"; // title that's used for free args without a title
- TString Title; // title of the help string
- TString CustomCmdLineDescr; // user defined help string
- TString CustomUsage; // user defined usage string
- TVector<std::pair<TString, TString>> Sections; // additional help entries to print after usage
- public:
- /**
- * Constructs TOpts from string as in getopt(3)
- */
- TOpts(const TStringBuf& optstring = TStringBuf());
- /**
- * Constructs TOpts from string as in getopt(3) and
- * additionally adds help option (for '?') and svn-verstion option (for 'V')
- */
- static TOpts Default(const TStringBuf& optstring = TStringBuf()) {
- TOpts opts(optstring);
- opts.AddHelpOption();
- opts.AddVersionOption();
- return opts;
- }
- /**
- * Checks correctness of options' descriptions.
- * Throws TConfException if validation failed.
- * Check consist of:
- * -not intersecting of names
- * -compability of settings, that responsable for freeArgs parsing
- */
- void Validate() const;
- /**
- * Search for the option with given long name
- * @param name long name for search
- * @return ptr on result (nullptr if not found)
- */
- const TOpt* FindLongOption(const TStringBuf& name) const;
- /**
- * Search for the option with given short name
- * @param c short name for search
- * @return ptr on result (nullptr if not found)
- */
- const TOpt* FindCharOption(char c) const;
- /**
- * Search for the option with given long name
- * @param name long name for search
- * @return ptr on result (nullptr if not found)
- */
- TOpt* FindLongOption(const TStringBuf& name);
- /**
- * Search for the option with given short name
- * @param c short name for search
- * @return ptr on result (nullptr if not found)
- */
- TOpt* FindCharOption(char c);
- /**
- * Search for the option with given name
- * @param name name for search
- * @return ptr on result (nullptr if not found)
- */
- /// @{
- const TOpt* FindOption(const TStringBuf& name) const {
- return FindLongOption(name);
- }
- TOpt* FindOption(const TStringBuf& name) {
- return FindLongOption(name);
- }
- const TOpt* FindOption(char c) const {
- return FindCharOption(c);
- }
- TOpt* FindOption(char c) {
- return FindCharOption(c);
- }
- /// @}
- /**
- * Sets title of the help string
- * @param title title to set
- */
- void SetTitle(const TString& title) {
- Title = title;
- }
- /**
- * @return true if there is an option with given long name
- *
- * @param name long name for search
- */
- bool HasLongOption(const TString& name) const {
- return FindLongOption(name) != nullptr;
- }
- /**
- * @return true if there is an option with given short name
- *
- * @param char short name for search
- */
- bool HasCharOption(char c) const {
- return FindCharOption(c) != nullptr;
- }
- /**
- * Search for the option with given long name
- * @param name long name for search
- * @return ref on result (throw exception if not found)
- */
- const TOpt& GetLongOption(const TStringBuf& name) const;
- /**
- * Search for the option with given long name
- * @param name long name for search
- * @return ref on result (throw exception if not found)
- */
- TOpt& GetLongOption(const TStringBuf& name);
- /**
- * Search for the option with given short name
- * @param c short name for search
- * @return ref on result (throw exception if not found)
- */
- const TOpt& GetCharOption(char c) const;
- /**
- * Search for the option with given short name
- * @param c short name for search
- * @return ref on result (throw exception if not found)
- */
- TOpt& GetCharOption(char c);
- /**
- * Search for the option with given name
- * @param name name for search
- * @return ref on result (throw exception if not found)
- */
- /// @{
- const TOpt& GetOption(const TStringBuf& name) const {
- return GetLongOption(name);
- }
- TOpt& GetOption(const TStringBuf& name) {
- return GetLongOption(name);
- }
- const TOpt& GetOption(char c) const {
- return GetCharOption(c);
- }
- TOpt& GetOption(char c) {
- return GetCharOption(c);
- }
- /// @}
- /**
- * @return true if short options exist
- */
- bool HasAnyShortOption() const;
- /**
- * @return true if long options exist
- */
- bool HasAnyLongOption() const;
- /**
- * Creates new [option description (TOpt)] as a copy of given one
- * @param option source
- * @return reference for created option
- */
- TOpt& AddOption(const TOpt& option);
- /**
- * Creates new free argument handling
- * @param name name of free arg to show in help
- * @param target variable address to store parsing result into
- * @param help help string to show in help
- */
- template <typename T>
- void AddFreeArgBinding(const TString& name, T& target, const TString& help = "") {
- ArgBindings_.emplace_back([&target](TStringBuf value) {
- target = FromString<T>(value);
- });
- FreeArgsMax_ = Max<ui32>(FreeArgsMax_, ArgBindings_.size());
- SetFreeArgTitle(ArgBindings_.size() - 1, name, help);
- }
- /**
- * Creates options list from string as in getopt(3)
- *
- * @param optstring source
- */
- void AddCharOptions(const TStringBuf& optstring);
- /**
- * Creates new [option description (TOpt)] with given short name and given help string
- *
- * @param c short name
- * @param help help string
- * @return reference for created option
- */
- TOpt& AddCharOption(char c, const TString& help = "") {
- return AddCharOption(c, DEFAULT_HAS_ARG, help);
- }
- /**
- * Creates new [option description (TOpt)] with given short name and given help string
- *
- * @param c short name
- * @param help help string
- * @return reference for created option
- */
- TOpt& AddCharOption(char c, EHasArg hasArg, const TString& help = "") {
- TOpt option;
- option.AddShortName(c);
- option.Help(help);
- option.HasArg(hasArg);
- return AddOption(option);
- }
- /**
- * Creates new [option description (TOpt)] with given long name and given help string
- *
- * @param name long name
- * @param help help string
- * @return reference for created option
- */
- TOpt& AddLongOption(const TString& name, const TString& help = "") {
- return AddLongOption(0, name, help);
- }
- /**
- * Creates new [option description (TOpt)] with given long and short names and given help string
- *
- * @param c short name
- * @param name long name
- * @param help help string
- * @return reference for created option
- */
- TOpt& AddLongOption(char c, const TString& name, const TString& help = "") {
- TOpt option;
- if (c != 0)
- option.AddShortName(c);
- option.AddLongName(name);
- option.Help(help);
- return AddOption(option);
- }
- /**
- * Creates new [option description (TOpt)] for help printing,
- * adds appropriate handler for it
- * If "help" option already exist, will add given short name to it.
- *
- * @param c new short name for help option
- */
- TOpt& AddHelpOption(char c = '?') {
- if (TOpt* o = FindLongOption("help")) {
- if (!o->CharIs(c))
- o->AddShortName(c);
- return *o;
- }
- return AddLongOption(c, "help", "print usage")
- .HasArg(NO_ARGUMENT)
- .IfPresentDisableCompletion()
- .Handler(&PrintUsageAndExit);
- }
- /**
- * Set check user typos or not
- * @param check bool flag for chosing
- */
- void SetCheckUserTypos(bool check = true) {
- CheckUserTypos_ = check;
- }
- /**
- * Creates new [option description (TOpt)] for svn-revision printing,
- * adds appropriate handler for it.
- * If "svnversion" option already exist, will add given short name to it.
- *
- * @param c new short name for "svnversion" option
- */
- TOpt& AddVersionOption(char c = 'V') {
- if (TOpt* o = FindLongOption("svnrevision")) {
- if (!o->CharIs(c))
- o->AddShortName(c);
- return *o;
- }
- return AddLongOption(c, "svnrevision", "print svn version")
- .HasArg(NO_ARGUMENT)
- .IfPresentDisableCompletion()
- .Handler(&PrintVersionAndExit);
- }
- /**
- * Creates new option for generating completion shell scripts.
- *
- * @param command name of command that should be completed (typically corresponds to the executable name).
- */
- TOpt& AddCompletionOption(TString command, TString longName = "completion");
- /**
- * Creates or finds option with given short name
- *
- * @param c new short name for search/create
- */
- TOpt& CharOption(char c) {
- const TOpt* opt = FindCharOption(c);
- if (opt != nullptr) {
- return const_cast<TOpt&>(*opt);
- } else {
- AddCharOption(c);
- return const_cast<TOpt&>(GetCharOption(c));
- }
- }
- /**
- * Indicate that some options can't appear together.
- *
- * Note: this is not transitive.
- *
- * Note: don't use this on options with default values. If option with default value wasn't specified,
- * parser will run handlers for default value, thus triggering a false-positive exclusivity check.
- */
- template <typename T1, typename T2>
- void MutuallyExclusive(T1&& opt1, T2&& opt2) {
- MutuallyExclusiveOpt(GetOption(std::forward<T1>(opt1)), GetOption(std::forward<T2>(opt2)));
- }
- /**
- * Like `MutuallyExclusive`, but accepts `TOpt`s instead of option names.
- */
- void MutuallyExclusiveOpt(TOpt& opt1, TOpt& opt2);
- /**
- * @return index of option
- *
- * @param opt pointer of option to search
- */
- size_t IndexOf(const TOpt* opt) const;
- /**
- * Replace help string with given
- *
- * @param decr new help string
- */
- void SetCmdLineDescr(const TString& descr) {
- CustomCmdLineDescr = descr;
- }
- /**
- * Replace usage string with given
- *
- * @param usage new usage string
- */
- void SetCustomUsage(const TString& usage) {
- CustomUsage = usage;
- }
- /**
- * Add a section to print after the main usage spec.
- */
- void AddSection(TString title, TString text) {
- Sections.emplace_back(std::move(title), std::move(text));
- }
- /**
- * Add section with examples.
- *
- * @param examples text of this section
- */
- void SetExamples(TString examples) {
- AddSection("Examples", std::move(examples));
- }
- /**
- * Set minimal number of free args
- *
- * @param min new value
- */
- void SetFreeArgsMin(size_t min) {
- FreeArgsMin_ = ui32(min);
- }
- /**
- * Get current minimal number of free args
- */
- ui32 GetFreeArgsMin() const {
- return FreeArgsMin_;
- }
- /**
- * Set maximal number of free args
- *
- * @param max new value
- */
- void SetFreeArgsMax(size_t max) {
- FreeArgsMax_ = ui32(max);
- FreeArgsMax_ = Max<ui32>(FreeArgsMax_, ArgBindings_.size());
- }
- /**
- * Get current maximal number of free args
- */
- ui32 GetFreeArgsMax() const {
- return FreeArgsMax_;
- }
- /**
- * Get mapping for free args
- */
- const TMap<ui32, TFreeArgSpec>& GetFreeArgSpecs() const {
- return FreeArgSpecs_;
- }
- /**
- * Set exact expected number of free args
- *
- * @param count new value
- */
- void SetFreeArgsNum(size_t count) {
- FreeArgsMin_ = ui32(count);
- FreeArgsMax_ = ui32(count);
- }
- /**
- * Set minimal and maximal number of free args
- *
- * @param min new value for minimal
- * @param max new value for maximal
- */
- void SetFreeArgsNum(size_t min, size_t max) {
- FreeArgsMin_ = ui32(min);
- FreeArgsMax_ = ui32(max);
- }
- /**
- * Set title and help string of free argument
- *
- * @param pos index of argument
- * @param title new value for argument title
- * @param help new value for help string
- * @param optional indicates that the flag's help string should be rendered as for optional flag;
- * does not affect actual flags parsing
- */
- void SetFreeArgTitle(size_t pos, const TString& title, const TString& help = TString(), bool optional = false);
- /**
- * Get free argument's spec for further modification.
- */
- TFreeArgSpec& GetFreeArgSpec(size_t pos);
- /**
- * Legacy, don't use. Same as `SetTrailingArgTitle`.
- * Older versions of lastgetopt didn't have destinction between default title and title
- * for the trailing argument.
- */
- void SetFreeArgDefaultTitle(const TString& title, const TString& help = TString()) {
- SetTrailingArgTitle(title, help);
- }
- /**
- * Set default title that will be used for all arguments that have no title.
- */
- void SetDefaultFreeArgTitle(TString title) {
- DefaultFreeArgTitle_ = std::move(title);
- }
- /**
- * Set default title that will be used for all arguments that have no title.
- */
- const TString& GetDefaultFreeArgTitle() const {
- return DefaultFreeArgTitle_;
- }
- /**
- * Set title and help for the trailing argument.
- *
- * This title and help are used to render the last repeated argument when max number of arguments is unlimited.
- */
- /// @{
- void SetTrailingArgTitle(TString title) {
- TrailingArgSpec_.Title(std::move(title));
- }
- void SetTrailingArgTitle(TString title, TString help) {
- TrailingArgSpec_.Title(std::move(title));
- TrailingArgSpec_.Help(std::move(help));
- }
- /// @}
- /**
- * Get spec for the trailing argument.
- *
- * This spec is used to render the last repeated argument when max number of arguments is unlimited.
- */
- /// @{
- TFreeArgSpec& GetTrailingArgSpec() {
- return TrailingArgSpec_;
- }
- const TFreeArgSpec& GetTrailingArgSpec() const {
- return TrailingArgSpec_;
- }
- /// @}
- /**
- * Set the rule of parsing single dash as prefix of long names
- *
- * @param value new value of the option
- */
- void SetAllowSingleDashForLong(bool value) {
- AllowSingleDashForLong_ = value;
- }
- /**
- * Wrap help text at this number of characters. 0 to disable wrapping.
- */
- void SetWrap(ui32 wrap = 80) {
- Wrap_ = wrap;
- }
- /**
- * Print usage string
- *
- * @param program prefix of result (path to the program)
- * @param os destination stream
- * @param colors colorizer
- */
- void PrintUsage(const TStringBuf& program, IOutputStream& os, const NColorizer::TColors& colors) const;
- /**
- * Print usage string
- *
- * @param program prefix of result (path to the program)
- * @param os destination stream
- */
- void PrintUsage(const TStringBuf& program, IOutputStream& os = Cout) const;
- /**
- * Get list of options in order of definition.
- */
- TVector<const TOpt*> GetOpts() const {
- auto ret = TVector<const TOpt*>(Reserve(Opts_.size()));
- for (auto& opt : Opts_) {
- ret.push_back(opt.Get());
- }
- return ret;
- }
- private:
- /**
- * @return argument title of a free argument
- *
- * @param pos position of the argument
- */
- TStringBuf GetFreeArgTitle(size_t pos) const;
- /**
- * Print usage helper
- *
- * @param program prefix of result (path to the program)
- * @param os destination stream
- * @param colors colorizer
- */
- void PrintCmdLine(const TStringBuf& program, IOutputStream& os, const NColorizer::TColors& colors) const;
- /**
- * Print usage helper
- *
- * @param os destination stream
- * @param colors colorizer
- */
- void PrintFreeArgsDesc(IOutputStream& os, const NColorizer::TColors& colors) const;
- };
- }
|