123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- #pragma once
- #include "last_getopt_opts.h"
- #include <util/generic/map.h>
- #include <util/generic/string.h>
- #include <util/generic/vector.h>
- #include <functional>
- //! Mode function with vector of cli arguments.
- using TMainFunctionPtrV = std::function<int(const TVector<TString>&)> ;
- using TMainFunctionRawPtrV = int (*)(const TVector<TString>& argv);
- //! Mode function with classic argc and argv arguments.
- using TMainFunctionPtr = std::function<int(int, const char**)> ;
- using TMainFunctionRawPtr = int (*)(const int argc, const char** argv);
- //! Mode class with vector of cli arguments.
- class TMainClassV {
- public:
- virtual int operator()(const TVector<TString>& argv) = 0;
- virtual ~TMainClassV() = default;
- };
- //! Mode class with classic argc and argv arguments.
- class TMainClass {
- public:
- virtual int operator()(int argc, const char** argv) = 0;
- virtual ~TMainClass() = default;
- };
- //! Function to handle '--version' parameter
- typedef void (*TVersionHandlerPtr)();
- /*! Main class for handling different modes in single tool.
- *
- * You can add modes for this class, use autogenerated help with
- * list of modes and automatically call necessary mode in run().
- *
- * In first argv element mode get joined by space tool name and
- * current mode name.
- */
- class TModChooser {
- public:
- TModChooser();
- ~TModChooser();
- public:
- void AddMode(const TString& mode, TMainFunctionRawPtr func, const TString& description, bool hidden = false, bool noCompletion = false);
- void AddMode(const TString& mode, TMainFunctionRawPtrV func, const TString& description, bool hidden = false, bool noCompletion = false);
- void AddMode(const TString& mode, TMainFunctionPtr func, const TString& description, bool hidden = false, bool noCompletion = false);
- void AddMode(const TString& mode, TMainFunctionPtrV func, const TString& description, bool hidden = false, bool noCompletion = false);
- void AddMode(const TString& mode, TMainClass* func, const TString& description, bool hidden = false, bool noCompletion = false);
- void AddMode(const TString& mode, TMainClassV* func, const TString& description, bool hidden = false, bool noCompletion = false);
- //! Hidden groups won't be displayed in 'help' block
- void AddGroupModeDescription(const TString& description, bool hidden = false, bool noCompletion = false);
- //! Set default mode (if not specified explicitly)
- void SetDefaultMode(const TString& mode);
- void AddAlias(const TString& alias, const TString& mode);
- //! Set main program description.
- void SetDescription(const TString& descr);
- //! Set modes help option name (-? is by default)
- void SetModesHelpOption(const TString& helpOption);
- //! Specify handler for '--version' parameter
- void SetVersionHandler(TVersionHandlerPtr handler);
- //! Set description show mode
- void SetSeparatedMode(bool separated = true);
- //! Set separation string
- void SetSeparationString(const TString& str);
- //! Set short command representation in Usage block
- void SetPrintShortCommandInUsage(bool printShortCommandInUsage);
- //! Help can be printed either to stdout and stderr. If set to false, then "--help" will be printed to stdout
- void SetHelpAlwaysToStdErr(bool helpAlwaysToStdErr) {
- HelpAlwaysToStdErr = helpAlwaysToStdErr;
- }
- void DisableSvnRevisionOption();
- void AddCompletions(TString progName, const TString& name = "completion", bool hidden = false, bool noCompletion = false);
- /*! Run appropriate mode.
- *
- * In this method following things happen:
- * 1) If first argument is -h/--help/-? then print short description of
- * all modes and exit with zero code.
- * 2) If first argument is -v/--version and version handler is specified,
- * then call it and exit with zero code.
- * 3) Find mode with the same name as first argument. If it's found then
- * call it and return its return code.
- * 4) If appropriate mode is not found - return non-zero code.
- */
- int Run(int argc, const char** argv) const;
- //! Run appropriate mode. Same as Run(const int, const char**)
- int Run(const TVector<TString>& argv) const;
- void PrintHelp(const TString& progName, bool toStdErr = false) const;
- struct TMode {
- TString Name;
- TMainClass* Main;
- TString Description;
- bool Hidden;
- bool NoCompletion;
- TVector<TString> Aliases;
- TMode()
- : Main(nullptr)
- {
- }
- TMode(const TString& name, TMainClass* main, const TString& descr, bool hidden, bool noCompletion);
- // Full name includes primary name and aliases. Also, will add ANSI colors.
- size_t CalculateFullNameLen() const;
- TString FormatFullName(size_t pad, const NColorizer::TColors& colors) const;
- };
- TVector<const TMode*> GetUnsortedModes() const {
- auto ret = TVector<const TMode*>(Reserve(UnsortedModes.size()));
- for (auto& mode : UnsortedModes) {
- ret.push_back(mode.Get());
- }
- return ret;
- }
- TVersionHandlerPtr GetVersionHandler() const;
- bool IsSvnRevisionOptionDisabled() const;
- private:
- //! Main program description.
- TString Description;
- //! Help option for modes.
- TString ModesHelpOption;
- //! Wrappers around all modes.
- TVector<THolder<TMainClass>> Wrappers;
- //! Modes
- TMap<TString, TMode*> Modes;
- TString DefaultMode;
- //! Handler for '--version' parameter
- TVersionHandlerPtr VersionHandler;
- //! When set to true, show descriptions unsorted and display separators
- bool ShowSeparated;
- //! When set to true, disables --svnrevision option, useful for opensource (git hosted) projects
- bool SvnRevisionOptionDisabled;
- //! When true - will print only 'mode name' in 'Usage' block
- bool PrintShortCommandInUsage;
- //! Text string used when displaying each separator
- TString SeparationString;
- //! Unsorted list of options
- TVector<THolder<TMode>> UnsortedModes;
- //! Mode that generates completions
- THolder<TMainClass> CompletionsGenerator;
- /*! Help message always output to StdErr
- *
- * If an error occurs, the help information will be printed to stderr regardless of the settings.
- * Setting below for success cases (return code == 0) like "./bin --help".
- * In this case by default help will be printed to stderr,
- * but it can be overridden by setting "HelpAlwaysToStdErr" to false see SetHelpAlwaysToStdErr() above,
- * then help message will be printed to stdout
- */
- bool HelpAlwaysToStdErr{true};
- };
- //! Mode class that allows introspecting its console arguments.
- class TMainClassArgs: public TMainClass {
- public:
- int operator()(int argc, const char** argv) final;
- public:
- //! Run this mode.
- int Run(int argc, const char** argv);
- //! Get console arguments for this mode.
- const NLastGetopt::TOpts& GetOptions();
- protected:
- //! Fill given empty `TOpts` with options.
- virtual void RegisterOptions(NLastGetopt::TOpts& opts);
- //! Actual mode logic. Takes parsed options and returns exit code.
- virtual int DoRun(NLastGetopt::TOptsParseResult&& parsedOptions) = 0;
- private:
- TMaybe<NLastGetopt::TOpts> Opts_;
- };
- //! Mode class that uses sub-modes to dispatch commands further.
- class TMainClassModes: public TMainClass {
- public:
- int operator()(int argc, const char** argv) final;
- public:
- //! Run this mode.
- int Run(int argc, const char** argv);
- //! Get sub-modes for this mode.
- const TModChooser& GetSubModes();
- protected:
- //! Fill given modchooser with sub-modes.
- virtual void RegisterModes(TModChooser& modes);
- private:
- TMaybe<TModChooser> Modes_;
- };
|