Skip to content

Instantly share code, notes, and snippets.

@02JanDal
Created July 25, 2015 12:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 02JanDal/1a9c3eb27ea6acab6d98 to your computer and use it in GitHub Desktop.
Save 02JanDal/1a9c3eb27ea6acab6d98 to your computer and use it in GitHub Desktop.
for (int i = 1; i < argc; ++i)
{
const std::string arg = argv[i];
if (expectedArgument && arg[0] != '-')
{
items.back().hasArgument = true;
}
else
{
if (arg[0] == '-' && !noMoreOptions)
{
if (arg.size() == 2 && arg[1] == '-')
{
// -- means no more options. only positional arguments from now on
noMoreOptions = true;
}
else if (arg.size() > 1 && arg[1] == '-')
{
// --long-argument
const size_t pos = arg.find('=');
const std::string name = arg.substr(2, pos == std::string::npos ? std::string::npos : pos - 2);
const auto option = options.find(name);
if (option == options.end())
{
throw CmdParserException(std::string("Unknown option --") + name);
}
else
{
const std::string argument = pos == std::string::npos ? std::string() : arg.substr(pos + 1);
items.emplace_back(name, argument, pos != std::string::npos);
expectedArgument = pos == std::string::npos && (*option).second.argument.size() != 0;
}
}
else if (arg.size() > 1 && arg[1] != '-')
{
// -abc short argument
for (auto it = ++arg.begin(); it != arg.end(); ++it)
{
const auto option = options.find(std::string({*it}));
if (option == options.end())
{
throw CmdParserException(std::string("Unknown option -") + *it);
}
else
{
items.emplace_back(std::string({*it}), std::string(), false);
expectedArgument = (*option).second.argument.size() != 0;
}
}
}
else // arg.size() == 1
{
// single - is a positional argument. used to mean stdin and similar
positional.push_back(arg);
noMoreOptions = true; // we do not allow any more options after the first positional argument
}
}
else
{
auto cmdIt = std::find_if(currentCommand.commands.begin(), currentCommand.commands.end(), [arg](const CmdSubcommand &cmd)
{
return std::find(cmd.names.begin(), cmd.names.end(), arg) != cmd.names.end();
});
if (!noMoreOptions && cmdIt != currentCommand.commands.end())
{
commands.push_back(*cmdIt);
currentCommand = *cmdIt;
const auto newOptions = currentCommand.mappedOptions();
options.insert(newOptions.begin(), newOptions.end());
}
else
{
positional.push_back(arg);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment