| 149 | } |
| 150 | |
| 151 | Result<Void> ArgumentsParser::parse(Arguments& arguments) { |
| 152 | while (arguments.hasNext()) { |
| 153 | auto argumentKey = arguments.next(); |
| 154 | auto argument = getArgument(argumentKey); |
| 155 | if (argument == nullptr) { |
| 156 | return Error(STRING_FORMAT("Unrecognized argument '{}'", argumentKey)); |
| 157 | } |
| 158 | |
| 159 | if (argument->isRemainder()) { |
| 160 | while (arguments.hasNext()) { |
| 161 | argument->appendValue(arguments.next()); |
| 162 | } |
| 163 | } else if (argument->isFlag()) { |
| 164 | if (!argument->hasValue()) { |
| 165 | argument->appendValue(STRING_LITERAL("true")); |
| 166 | } |
| 167 | } else { |
| 168 | if (!arguments.hasNext()) { |
| 169 | return Error(STRING_FORMAT("Missing value after argument '{}'", argument->getFullDescription())); |
| 170 | } |
| 171 | |
| 172 | auto argumentValue = arguments.next(); |
| 173 | |
| 174 | if (argument->hasValue() && !argument->allowsMultipleValues()) { |
| 175 | return Error(STRING_FORMAT("Argument '{}' can only accept one value", argument->getFullDescription())); |
| 176 | } |
| 177 | |
| 178 | argument->appendValue(argumentValue); |
| 179 | |
| 180 | if (argument->hasChoices()) { |
| 181 | std::optional<size_t> choiceIndex; |
| 182 | |
| 183 | for (size_t i = 0; i < argument->getChoices().size(); i++) { |
| 184 | const auto& choice = argument->getChoices()[i]; |
| 185 | if (choice == argumentValue) { |
| 186 | choiceIndex = {i}; |
| 187 | break; |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | if (choiceIndex) { |
| 192 | argument->setChoiceIndex(choiceIndex.value()); |
| 193 | } else { |
| 194 | std::vector<StringBox> debugChoices; |
| 195 | for (const auto& choice : argument->getChoices()) { |
| 196 | debugChoices.emplace_back(STRING_FORMAT("'{}'", choice)); |
| 197 | } |
| 198 | return Error(STRING_FORMAT("Argument '{}' must be one of ", |
| 199 | argument->getFullDescription(), |
| 200 | StringBox::join(debugChoices, ", "))); |
| 201 | } |
| 202 | } |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | for (const auto& argument : _arguments) { |
| 207 | if (!argument->hasValue() && argument->isRequired()) { |
| 208 | return Error( |
no test coverage detected