31 std::vector<std::string> tokens;
34 const std::string usage_owned(usage);
35 for (absl::string_view token :
36 absl::StrSplit(usage_owned,
' ', absl::SkipEmpty())) {
37 tokens.emplace_back(token);
43 std::vector<std::string> required_args;
44 absl::flat_hash_set<std::string> seen;
47 int optional_depth = 0;
48 for (
size_t i = 0; i < tokens.size(); ++i) {
49 const std::string& token = tokens[i];
51 static_cast<int>(std::count(token.begin(), token.end(),
'['));
52 const bool is_optional = optional_depth > 0;
55 if (!is_optional && cleaned.rfind(
"--", 0) == 0) {
56 std::string arg_name = cleaned.substr(2);
57 const size_t equals_pos = arg_name.find(
'=');
58 if (equals_pos != std::string::npos) {
59 arg_name = arg_name.substr(0, equals_pos);
60 }
else if (i + 1 < tokens.size()) {
62 if (next.empty() || next.front() !=
'<') {
69 if (!arg_name.empty() && seen.insert(arg_name).second) {
70 required_args.push_back(std::move(arg_name));
75 static_cast<int>(std::count(token.begin(), token.end(),
']'));
82 std::vector<std::string> flag_args;
83 absl::flat_hash_set<std::string> seen;
86 for (
size_t i = 0; i < tokens.size(); ++i) {
88 if (cleaned.rfind(
"--", 0) != 0) {
92 std::string arg_name = cleaned.substr(2);
93 if (arg_name.find(
'=') != std::string::npos) {
97 const bool has_value_token =
100 if (has_value_token) {
104 if (seen.insert(arg_name).second) {
105 flag_args.push_back(std::move(arg_name));