/* * Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved. * * This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit). * * Use of this source code is governed by MIT license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #ifndef SRC_UTIL_CMD_H_ #define SRC_UTIL_CMD_H_ #include #include #include #include #include #include #include #include "mini.h" namespace toolkit{ class Option { public: using OptionHandler = std::function &stream, const std::string &arg)>; enum ArgType { ArgNone = 0,//no_argument, ArgRequired = 1,//required_argument, ArgOptional = 2,//optional_argument }; Option() = default; Option(char short_opt, const char *long_opt, enum ArgType type, const char *default_value, bool must_exist, const char *des, const OptionHandler &cb) { _short_opt = short_opt; _long_opt = long_opt; _type = type; if (type != ArgNone) { if (default_value) { _default_value = std::make_shared(default_value); } if (!_default_value && must_exist) { _must_exist = true; } } _des = des; _cb = cb; } bool operator()(const std::shared_ptr &stream, const std::string &arg) { return _cb ? _cb(stream, arg) : true; } private: friend class OptionParser; bool _must_exist = false; char _short_opt; enum ArgType _type; std::string _des; std::string _long_opt; OptionHandler _cb; std::shared_ptr _default_value; }; class OptionParser { public: using OptionCompleted = std::function &, mINI &)>; OptionParser(const OptionCompleted &cb = nullptr, bool enable_empty_args = true) { _on_completed = cb; _enable_empty_args = enable_empty_args; _helper = Option('h', "help", Option::ArgNone, nullptr, false, "打印此信息", [this](const std::shared_ptr &stream,const std::string &arg)->bool { static const char *argsType[] = {"无参", "有参", "选参"}; static const char *mustExist[] = {"选填", "必填"}; static std::string defaultPrefix = "默认:"; static std::string defaultNull = "null"; std::stringstream printer; size_t maxLen_longOpt = 0; auto maxLen_default = defaultNull.size(); for (auto &pr : _map_options) { auto &opt = pr.second; if (opt._long_opt.size() > maxLen_longOpt) { maxLen_longOpt = opt._long_opt.size(); } if (opt._default_value) { if (opt._default_value->size() > maxLen_default) { maxLen_default = opt._default_value->size(); } } } for (auto &pr : _map_options) { auto &opt = pr.second; //打印短参和长参名 if (opt._short_opt) { printer << " -" << opt._short_opt << " --" << opt._long_opt; } else { printer << " " << " " << " --" << opt._long_opt; } for (size_t i = 0; i < maxLen_longOpt - opt._long_opt.size(); ++i) { printer << " "; } //打印是否有参 printer << " " << argsType[opt._type]; //打印默认参数 std::string defaultValue = defaultNull; if (opt._default_value) { defaultValue = *opt._default_value; } printer << " " << defaultPrefix << defaultValue; for (size_t i = 0; i < maxLen_default - defaultValue.size(); ++i) { printer << " "; } //打印是否必填参数 printer << " " << mustExist[opt._must_exist]; //打印描述 printer << " " << opt._des << std::endl; } throw std::invalid_argument(printer.str()); }); (*this) << _helper; } OptionParser &operator<<(Option &&option) { int index = 0xFF + (int) _map_options.size(); if (option._short_opt) { _map_char_index.emplace(option._short_opt, index); } _map_options.emplace(index, std::forward