Simplify support for unchecked options in OptionParser.

GitOrigin-RevId: 5a913944b5a6cfecdfb96287e2c670be8ca18547
This commit is contained in:
levlam 2020-06-19 04:44:38 +03:00
parent 0877d7f716
commit 5aa609535e
4 changed files with 46 additions and 55 deletions

View File

@ -4330,10 +4330,7 @@ void main(int argc, char **argv) {
td::OptionParser options; td::OptionParser options;
options.set_description("TDLib test client"); options.set_description("TDLib test client");
options.add_option('\0', "test", "Use test DC", [&] { options.add_option('\0', "test", "Use test DC", [&] { use_test_dc = true; });
use_test_dc = true;
return Status::OK();
});
options.add_option('v', "verbosity", "Set verbosity level", [&](Slice level) { options.add_option('v', "verbosity", "Set verbosity level", [&](Slice level) {
int new_verbosity = 1; int new_verbosity = 1;
while (begins_with(level, "v")) { while (begins_with(level, "v")) {
@ -4344,39 +4341,21 @@ void main(int argc, char **argv) {
new_verbosity += to_integer<int>(level) - (new_verbosity == 1); new_verbosity += to_integer<int>(level) - (new_verbosity == 1);
} }
new_verbosity_level = VERBOSITY_NAME(FATAL) + new_verbosity; new_verbosity_level = VERBOSITY_NAME(FATAL) + new_verbosity;
return Status::OK();
}); });
options.add_option('l', "log", "Log to file", [&](Slice file_name) { options.add_option('l', "log", "Log to file", [&](Slice file_name) {
if (file_log.init(file_name.str()).is_ok() && file_log.init(file_name.str()).is_ok() && if (file_log.init(file_name.str()).is_ok() && file_log.init(file_name.str()).is_ok() &&
file_log.init(file_name.str(), 1000 << 20).is_ok()) { file_log.init(file_name.str(), 1000 << 20).is_ok()) {
log_interface = &ts_log; log_interface = &ts_log;
} }
return Status::OK();
});
options.add_option('W', "", "Preload chat list", [&] {
get_chat_list = true;
return Status::OK();
});
options.add_option('n', "disable-network", "Disable network", [&] {
disable_network = true;
return Status::OK();
});
options.add_option('\0', "api-id", "Set Telegram API ID", [&](Slice parameter) {
api_id = to_integer<int32>(parameter);
return Status::OK();
});
options.add_option('\0', "api_id", "Set Telegram API ID", [&](Slice parameter) {
api_id = to_integer<int32>(parameter);
return Status::OK();
});
options.add_option('\0', "api-hash", "Set Telegram API hash", [&](Slice parameter) {
api_hash = parameter.str();
return Status::OK();
});
options.add_option('\0', "api_hash", "Set Telegram API hash", [&](Slice parameter) {
api_hash = parameter.str();
return Status::OK();
}); });
options.add_option('W', "", "Preload chat list", [&] { get_chat_list = true; });
options.add_option('n', "disable-network", "Disable network", [&] { disable_network = true; });
options.add_option('\0', "api-id", "Set Telegram API ID",
[&](Slice parameter) { api_id = to_integer<int32>(parameter); });
options.add_option('\0', "api_id", "Set Telegram API ID",
[&](Slice parameter) { api_id = to_integer<int32>(parameter); });
options.add_option('\0', "api-hash", "Set Telegram API hash", [&](Slice parameter) { api_hash = parameter.str(); });
options.add_option('\0', "api_hash", "Set Telegram API hash", [&](Slice parameter) { api_hash = parameter.str(); });
auto res = options.run(argc, argv); auto res = options.run(argc, argv);
if (res.is_error()) { if (res.is_error()) {
LOG(PLAIN) << "tg_cli: " << res.error().message(); LOG(PLAIN) << "tg_cli: " << res.error().message();

View File

@ -22,16 +22,29 @@ void OptionParser::add_option(Option::Type type, char short_key, Slice long_key,
options_.push_back(Option{type, short_key, long_key.str(), description.str(), std::move(callback)}); options_.push_back(Option{type, short_key, long_key.str(), description.str(), std::move(callback)});
} }
void OptionParser::add_option(char short_key, Slice long_key, Slice description, void OptionParser::add_checked_option(char short_key, Slice long_key, Slice description,
std::function<Status(Slice)> callback) { std::function<Status(Slice)> callback) {
add_option(Option::Type::Arg, short_key, long_key, description, std::move(callback)); add_option(Option::Type::Arg, short_key, long_key, description, std::move(callback));
} }
void OptionParser::add_option(char short_key, Slice long_key, Slice description, std::function<Status(void)> callback) { void OptionParser::add_checked_option(char short_key, Slice long_key, Slice description,
// Ouch. There must be some better way std::function<Status(void)> callback) {
add_option(Option::Type::NoArg, short_key, long_key, description, add_option(Option::Type::NoArg, short_key, long_key, description,
std::bind([](std::function<Status(void)> &func, Slice) { return func(); }, std::move(callback), [callback = std::move(callback)](Slice) { return callback(); });
std::placeholders::_1)); }
void OptionParser::add_option(char short_key, Slice long_key, Slice description, std::function<void(Slice)> callback) {
add_option(Option::Type::Arg, short_key, long_key, description, [callback = std::move(callback)](Slice parameter) {
callback(parameter);
return Status::OK();
});
}
void OptionParser::add_option(char short_key, Slice long_key, Slice description, std::function<void(void)> callback) {
add_option(Option::Type::NoArg, short_key, long_key, description, [callback = std::move(callback)](Slice) {
callback();
return Status::OK();
});
} }
Result<vector<char *>> OptionParser::run(int argc, char *argv[]) { Result<vector<char *>> OptionParser::run(int argc, char *argv[]) {
@ -64,11 +77,11 @@ Result<vector<char *>> OptionParser::run(int argc, char *argv[]) {
if (arg[1] == '-') { if (arg[1] == '-') {
// long option // long option
Slice long_arg(arg + 2, std::strlen(arg + 2)); Slice long_arg(arg + 2, std::strlen(arg + 2));
Slice param; Slice parameter;
auto equal_pos = long_arg.find('='); auto equal_pos = long_arg.find('=');
bool has_equal = equal_pos != Slice::npos; bool has_equal = equal_pos != Slice::npos;
if (has_equal) { if (has_equal) {
param = long_arg.substr(equal_pos + 1); parameter = long_arg.substr(equal_pos + 1);
long_arg = long_arg.substr(0, equal_pos); long_arg = long_arg.substr(0, equal_pos);
} }
@ -89,14 +102,14 @@ Result<vector<char *>> OptionParser::run(int argc, char *argv[]) {
if (++arg_pos == argc) { if (++arg_pos == argc) {
return Status::Error(PSLICE() << "Option " << long_arg << " must have argument"); return Status::Error(PSLICE() << "Option " << long_arg << " must have argument");
} }
param = Slice(argv[arg_pos], std::strlen(argv[arg_pos])); parameter = Slice(argv[arg_pos], std::strlen(argv[arg_pos]));
} }
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
TRY_STATUS(option->arg_callback(param)); TRY_STATUS(option->arg_callback(parameter));
continue; continue;
} }
@ -107,7 +120,7 @@ Result<vector<char *>> OptionParser::run(int argc, char *argv[]) {
} }
auto option = it->second; auto option = it->second;
Slice param; Slice parameter;
switch (option->type) { switch (option->type) {
case Option::Type::NoArg: case Option::Type::NoArg:
// nothing to do // nothing to do
@ -117,17 +130,17 @@ Result<vector<char *>> OptionParser::run(int argc, char *argv[]) {
if (++arg_pos == argc) { if (++arg_pos == argc) {
return Status::Error(PSLICE() << "Option " << arg[opt_pos] << " must have argument"); return Status::Error(PSLICE() << "Option " << arg[opt_pos] << " must have argument");
} }
param = Slice(argv[arg_pos], std::strlen(argv[arg_pos])); parameter = Slice(argv[arg_pos], std::strlen(argv[arg_pos]));
} else { } else {
param = Slice(arg + opt_pos + 1, std::strlen(arg + opt_pos + 1)); parameter = Slice(arg + opt_pos + 1, std::strlen(arg + opt_pos + 1));
opt_pos += param.size(); opt_pos += parameter.size();
} }
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
TRY_STATUS(option->arg_callback(param)); TRY_STATUS(option->arg_callback(parameter));
} }
} }

View File

@ -32,9 +32,13 @@ class OptionParser {
public: public:
void set_description(string description); void set_description(string description);
void add_option(char short_key, Slice long_key, Slice description, std::function<Status(Slice)> callback); void add_checked_option(char short_key, Slice long_key, Slice description, std::function<Status(Slice)> callback);
void add_option(char short_key, Slice long_key, Slice description, std::function<Status(void)> callback); void add_checked_option(char short_key, Slice long_key, Slice description, std::function<Status(void)> callback);
void add_option(char short_key, Slice long_key, Slice description, std::function<void(Slice)> callback);
void add_option(char short_key, Slice long_key, Slice description, std::function<void(void)> callback);
// returns found non-option parameters // returns found non-option parameters
Result<vector<char *>> run(int argc, char *argv[]) TD_WARN_UNUSED_RESULT; Result<vector<char *>> run(int argc, char *argv[]) TD_WARN_UNUSED_RESULT;

View File

@ -26,14 +26,9 @@ int main(int argc, char **argv) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
td::OptionParser options; td::OptionParser options;
options.add_option('\0', "filter", "Run only specified tests", [&](td::Slice filter) { options.add_option('\0', "filter", "Run only specified tests",
runner.add_substr_filter(filter.str()); [&](td::Slice filter) { runner.add_substr_filter(filter.str()); });
return td::Status::OK(); options.add_option('\0', "stress", "Run tests infinitely", [&] { runner.set_stress_flag(true); });
});
options.add_option('\0', "stress", "Run tests infinitely", [&] {
runner.set_stress_flag(true);
return td::Status::OK();
});
auto result = options.run(argc, argv); auto result = options.run(argc, argv);
if (result.is_error() || !result.ok().empty()) { if (result.is_error() || !result.ok().empty()) {
LOG(PLAIN) << options; LOG(PLAIN) << options;