last_getopt_parse_result.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include "last_getopt_parse_result.h"
  2. namespace NLastGetopt {
  3. const TOptParseResult* TOptsParseResult::FindParseResult(const TdVec& vec, const TOpt* opt) {
  4. for (const auto& r : vec) {
  5. if (r.OptPtr() == opt)
  6. return &r;
  7. }
  8. return nullptr;
  9. }
  10. const TOptParseResult* TOptsParseResult::FindOptParseResult(const TOpt* opt, bool includeDefault) const {
  11. const TOptParseResult* r = FindParseResult(Opts_, opt);
  12. if (nullptr == r && includeDefault)
  13. r = FindParseResult(OptsDef_, opt);
  14. return r;
  15. }
  16. const TOptParseResult* TOptsParseResult::FindLongOptParseResult(const TString& name, bool includeDefault) const {
  17. return FindOptParseResult(&Parser_->Opts_->GetLongOption(name), includeDefault);
  18. }
  19. const TOptParseResult* TOptsParseResult::FindCharOptParseResult(char c, bool includeDefault) const {
  20. return FindOptParseResult(&Parser_->Opts_->GetCharOption(c), includeDefault);
  21. }
  22. bool TOptsParseResult::Has(const TOpt* opt, bool includeDefault) const {
  23. Y_ASSERT(opt);
  24. return FindOptParseResult(opt, includeDefault) != nullptr;
  25. }
  26. bool TOptsParseResult::Has(const TString& name, bool includeDefault) const {
  27. return FindLongOptParseResult(name, includeDefault) != nullptr;
  28. }
  29. bool TOptsParseResult::Has(char c, bool includeDefault) const {
  30. return FindCharOptParseResult(c, includeDefault) != nullptr;
  31. }
  32. const char* TOptsParseResult::Get(const TOpt* opt, bool includeDefault) const {
  33. Y_ASSERT(opt);
  34. const TOptParseResult* r = FindOptParseResult(opt, includeDefault);
  35. if (!r || r->Empty()) {
  36. try {
  37. throw TUsageException() << "option " << opt->ToShortString() << " is unspecified";
  38. } catch (...) {
  39. HandleError();
  40. // unreachable
  41. throw;
  42. }
  43. } else {
  44. return r->Back();
  45. }
  46. }
  47. const char* TOptsParseResult::GetOrElse(const TOpt* opt, const char* defaultValue) const {
  48. Y_ASSERT(opt);
  49. const TOptParseResult* r = FindOptParseResult(opt);
  50. if (!r || r->Empty()) {
  51. return defaultValue;
  52. } else {
  53. return r->Back();
  54. }
  55. }
  56. const char* TOptsParseResult::Get(const TString& name, bool includeDefault) const {
  57. return Get(&Parser_->Opts_->GetLongOption(name), includeDefault);
  58. }
  59. const char* TOptsParseResult::Get(char c, bool includeDefault) const {
  60. return Get(&Parser_->Opts_->GetCharOption(c), includeDefault);
  61. }
  62. const char* TOptsParseResult::GetOrElse(const TString& name, const char* defaultValue) const {
  63. if (!Has(name))
  64. return defaultValue;
  65. return Get(name);
  66. }
  67. const char* TOptsParseResult::GetOrElse(char c, const char* defaultValue) const {
  68. if (!Has(c))
  69. return defaultValue;
  70. return Get(c);
  71. }
  72. TOptParseResult& TOptsParseResult::OptParseResult() {
  73. const TOpt* opt = Parser_->CurOpt();
  74. Y_ASSERT(opt);
  75. TdVec& opts = Parser_->IsExplicit() ? Opts_ : OptsDef_;
  76. if (Parser_->IsExplicit()) // default options won't appear twice
  77. for (auto& it : opts)
  78. if (it.OptPtr() == opt)
  79. return it;
  80. opts.push_back(TOptParseResult(opt));
  81. return opts.back();
  82. }
  83. TString TOptsParseResult::GetProgramName() const {
  84. return Parser_->ProgramName_;
  85. }
  86. void TOptsParseResult::PrintUsage(IOutputStream& os) const {
  87. Parser_->Opts_->PrintUsage(Parser_->ProgramName_, os);
  88. }
  89. size_t TOptsParseResult::GetFreeArgsPos() const {
  90. return Parser_->Pos_;
  91. }
  92. TVector<TString> TOptsParseResult::GetFreeArgs() const {
  93. TVector<TString> v;
  94. for (size_t i = GetFreeArgsPos(); i < Parser_->Argc_; ++i) {
  95. v.push_back(Parser_->Argv_[i]);
  96. }
  97. return v;
  98. }
  99. size_t TOptsParseResult::GetFreeArgCount() const {
  100. return Parser_->Argc_ - GetFreeArgsPos();
  101. }
  102. void FindUserTypos(const TString& arg, const TOpts* options) {
  103. if (arg.size() < 4 || !arg.StartsWith("-")) {
  104. return;
  105. }
  106. for (auto opt: options->Opts_) {
  107. for (auto name: opt->GetLongNames()) {
  108. if ("-" + name == arg) {
  109. throw TUsageException() << "did you mean `-" << arg << "` (with two dashes)?";
  110. }
  111. }
  112. }
  113. }
  114. void TOptsParseResult::Init(const TOpts* options, int argc, const char** argv) {
  115. try {
  116. Parser_.Reset(new TOptsParser(options, argc, argv));
  117. while (Parser_->Next()) {
  118. TOptParseResult& r = OptParseResult();
  119. r.AddValue(Parser_->CurValOrOpt().data());
  120. }
  121. Y_ENSURE(options);
  122. const auto freeArgs = GetFreeArgs();
  123. for (size_t i = 0; i < freeArgs.size(); ++i) {
  124. if (i >= options->ArgBindings_.size()) {
  125. break;
  126. }
  127. options->ArgBindings_[i](freeArgs[i]);
  128. }
  129. if (options->CheckUserTypos_) {
  130. for (auto arg: TVector<TString>(argv, std::next(argv, argc))) {
  131. FindUserTypos(arg, options);
  132. }
  133. }
  134. } catch (...) {
  135. HandleError();
  136. }
  137. }
  138. void TOptsParseResult::HandleError() const {
  139. Cerr << CurrentExceptionMessage() << Endl;
  140. if (Parser_.Get()) { // parser initializing can fail (and we get here, see Init)
  141. if (Parser_->Opts_->FindLongOption("help") != nullptr) {
  142. Cerr << "Try '" << Parser_->ProgramName_ << " --help' for more information." << Endl;
  143. } else {
  144. PrintUsage();
  145. }
  146. }
  147. exit(1);
  148. }
  149. void TOptsParseResultException::HandleError() const {
  150. throw;
  151. }
  152. }