8000 docopt.cpp/docopt.cpp at master · OSVR/docopt.cpp · GitHub
[go: up one dir, main page]

Skip to content
{"payload":{"allShortcutsEnabled":false,"fileTree":{"":{"items":[{"name":"examples","path":"examples","contentType":"directory"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":".travis.yml","path":".travis.yml","contentType":"file"},{"name":"CMakeLists.txt","path":"CMakeLists.txt","contentType":"file"},{"name":"LICENSE-Boost-1.0","path":"LICENSE-Boost-1.0","contentType":"file"},{"name":"LICENSE-MIT","path":"LICENSE-MIT","contentType":"file"},{"name":"README.rst","path":"README.rst","contentType":"file"},{"name":"docopt-config.cmake","path":"docopt-config.cmake","contentType":"file"},{"name":"docopt.cpp","path":"docopt.cpp","contentType":"file"},{"name":"docopt.h","path":"docopt.h","contentType":"file"},{"name":"docopt_private.h","path":"docopt_private.h","contentType":"file"},{"name":"docopt_util.h","path":"docopt_util.h","contentType":"file"},{"name":"docopt_value.h","path":"docopt_value.h","contentType":"file"},{"name":"main.cpp","path":"main.cpp","contentType":"file"},{"name":"run_testcase.cpp","path":"run_testcase.cpp","contentType":"file"},{"name":"run_tests.py","path":"run_tests.py","contentType":"file"},{"name":"testcases.docopt","path":"testcases.docopt","contentType":"file"}],"totalCount":17}},"fileTreeProcessingTime":7.7655140000000005,"foldersToFetch":[],"incompleteFileTree":false,"repo":{"id":66108518,"defaultBranch":"master","name":"docopt.cpp","ownerLogin":"OSVR","currentUserCanPush":false,"isFork":true,"isEmpty":false,"createdAt":"2016-08-19T19:53:10.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/10343613?v=4","public":true,"private":false,"isOrgOwned":true},"codeLineWrapEnabled":false,"symbolsExpanded":false,"treeExpanded":true,"refInfo":{"name":"master","listCacheKey":"v0:1471637709.0","canEdit":false,"refType":"branch","currentOid":"0237c9adc88b1165d77b8303b1fb70d676d4d11e"},"path":"docopt.cpp","currentUser":null,"blob":{"rawLines":["//","// docopt.cpp","// docopt","//","// Created by Jared Grubb on 2013-11-03.","// Copyright (c) 2013 Jared Grubb. All rights reserved.","//","","#include \"docopt.h\"","#include \"docopt_util.h\"","#include \"docopt_private.h\"","","#include \"docopt_value.h\"","","#include \u003cvector\u003e","#include \u003cunordered_set\u003e","#include \u003cunordered_map\u003e","#include \u003cmap\u003e","#include \u003cstring\u003e","#include \u003ciostream\u003e","#include \u003ccassert\u003e","#include \u003ccstddef\u003e","","using namespace docopt;","","DOCOPT_INLINE","std::ostream\u0026 docopt::operator\u003c\u003c(std::ostream\u0026 os, value const\u0026 val)","{","\tif (val.isBool()) {","\t\tbool b = val.asBool();","\t\tos \u003c\u003c (b ? \"true\" : \"false\");","\t} else if (val.isLong()) {","\t\tlong v = val.asLong();","\t\tos \u003c\u003c v;","\t} else if (val.isString()) {","\t\tstd::string const\u0026 str = val.asString();","\t\tos \u003c\u003c '\"' \u003c\u003c str \u003c\u003c '\"';","\t} else if (val.isStringList()) {","\t\tauto const\u0026 list = val.asStringList();","\t\tos \u003c\u003c \"[\";","\t\tbool first = true;","\t\tfor(auto const\u0026 el : list) {","\t\t\tif (first) {","\t\t\t\tfirst = false;","\t\t\t} else {","\t\t\t\tos \u003c\u003c \", \";","\t\t\t}","\t\t\tos \u003c\u003c '\"' \u003c\u003c el \u003c\u003c '\"';","\t\t}","\t\tos \u003c\u003c \"]\";","\t} else {","\t\tos \u003c\u003c \"null\";","\t}","\treturn os;","}","","#pragma mark -","#pragma mark Parsing stuff","","class Tokens {","public:","\tTokens(std::vector\u003cstd::string\u003e tokens, bool isParsingArgv = true)","\t: fTokens(std::move(tokens)),","\t fIsParsingArgv(isParsingArgv)","\t{}","","\texplicit operator bool() const {","\t\treturn fIndex \u003c fTokens.size();","\t}","","\tstatic Tokens from_pattern(std::string const\u0026 source) {","\t\tstatic const std::regex re_separators {","\t\t\t\"(?:\\\\s*)\" // any spaces (non-matching subgroup)","\t\t\t\"(\"","\t\t\t\"[\\\\[\\\\]\\\\(\\\\)\\\\|]\" // one character of brackets or parens or pipe character","\t\t\t\"|\"","\t\t\t\"\\\\.\\\\.\\\\.\" // elipsis","\t\t\t\")\" };","","\t\tstatic const std::regex re_strings {","\t\t\t\"(?:\\\\s*)\" // any spaces (non-matching subgroup)","\t\t\t\"(\"","\t\t\t\"\\\\S*\u003c.*?\u003e\" // strings, but make sure to keep \"\u003c \u003e\" strings together","\t\t\t\"|\"","\t\t\t\"[^\u003c\u003e\\\\s]+\" // string without \u003c\u003e","\t\t\t\")\" };","","\t\t// We do two stages of regex matching. The '[]()' and '...' are strong delimeters","\t\t// and need to be split out anywhere they occur (even at the end of a token). We","\t\t// first split on those, and then parse the stuff between them to find the string","\t\t// tokens. This is a little harder than the python version, since they have regex.split","\t\t// and we dont have anything like that.","","\t\tstd::vector\u003cstd::string\u003e tokens;","\t\tstd::for_each(std::sregex_iterator{ source.begin(), source.end(), re_separators },","\t\t\t std::sregex_iterator{},","\t\t\t [\u0026](std::smatch const\u0026 match)","\t\t\t {","\t\t\t\t // handle anything before the separator (this is the \"stuff\" between the delimeters)","\t\t\t\t if (match.prefix().matched) {","\t\t\t\t\t std::for_each(std::sregex_iterator{match.prefix().first, match.prefix().second, re_strings},","\t\t\t\t\t\t\t std::sregex_iterator{},","\t\t\t\t\t\t\t [\u0026](std::smatch const\u0026 m)","\t\t\t\t\t\t\t {","\t\t\t\t\t\t\t\t tokens.push_back(m[1].str());","\t\t\t\t\t\t\t });","\t\t\t\t }","","\t\t\t\t // handle the delimter token itself","\t\t\t\t if (match[1].matched) {","\t\t\t\t\t tokens.push_back(match[1].str());","\t\t\t\t }","\t\t\t });","","\t\treturn Tokens(tokens, false);","\t}","","\tstd::string const\u0026 current() const {","\t\tif (*this)","\t\t\treturn fTokens[fIndex];","","\t\tstatic std::string const empty;","\t\treturn empty;","\t}","","\tstd::string the_rest() const {","\t\tif (!*this)","\t\t\treturn {};","\t\treturn join(fTokens.begin()+static_cast\u003cstd::ptrdiff_t\u003e(fIndex),","\t\t\t fTokens.end(),","\t\t\t \" \");","\t}","","\tstd::string pop() {","\t\treturn std::move(fTokens.at(fIndex++));","\t}","","\tbool isParsingArgv() const { return fIsParsingArgv; }","","\tstruct OptionError : std::runtime_error { using runtime_error::runtime_error; };","","private:","\tstd::vector\u003cstd::string\u003e fTokens;","\tsize_t fIndex = 0;","\tbool fIsParsingArgv;","};","","// Get all instances of 'T' from the pattern","template \u003ctypename T\u003e","std::vector\u003cT*\u003e flat_filter(Pattern\u0026 pattern) {","\tstd::vector\u003cPattern*\u003e flattened = pattern.flat([](Pattern const* p) -\u003e bool {","\t\treturn dynamic_cast\u003cT const*\u003e(p) != nullptr;","\t});","","\t// now, we're guaranteed to have T*'s, so just use static_cast","\tstd::vector\u003cT*\u003e ret;","\tstd::transform(flattened.begin(), flattened.end(), std::back_inserter(ret), [](Pattern* p) {","\t\treturn static_cast\u003cT*\u003e(p);","\t});","\treturn ret;","}","","static std::vector\u003cstd::string\u003e parse_section(std::string const\u0026 name, std::string const\u0026 source) {","\t// ECMAScript regex only has \"?=\" for a non-matching lookahead. In order to make sure we always have","\t// a newline to anchor our matching, we have to avoid matching the final newline of each grouping.","\t// Therefore, our regex is adjusted from the docopt Python one to use ?= to match the newlines before","\t// the following lines, rather than after.","\tstd::regex const re_section_pattern {","\t\t\"(?:^|\\\\n)\" // anchored at a linebreak (or start of string)","\t\t\"(\"","\t\t \"[^\\\\n]*\" + name + \"[^\\\\n]*(?=\\\\n?)\" // a line that contains the name","\t\t \"(?:\\\\n[ \\\\t].*?(?=\\\\n|$))*\" // followed by any number of lines that are indented","\t\t\")\",","\t\tstd::regex::icase","\t};","","\tstd::vector\u003cstd::string\u003e ret;","\tstd::for_each(std::sregex_iterator(source.begin(), source.end(), re_section_pattern),","\t\t std::sregex_iterator(),","\t\t [\u0026](std::smatch const\u0026 match)","\t{","\t\tret.push_back(trim(match[1].str()));","\t});","","\treturn ret;","}","","static bool is_argument_spec(std::string const\u0026 token) {","\tif (token.empty())","\t\treturn false;","","\tif (token[0]=='\u003c' \u0026\u0026 token[token.size()-1]=='\u003e')","\t\treturn true;","","\tif (std::all_of(token.begin(), token.end(), \u0026::isupper))","\t\treturn true;","","\treturn false;","}","","template \u003ctypename I\u003e","std::vector\u003cstd::string\u003e longOptions(I iter, I end) {","\tstd::vector\u003cstd::string\u003e ret;","\tstd::transform(iter, end,","\t\t std::back_inserter(ret),","\t\t [](typename I::reference opt) { return opt-\u003elongOption(); });","\treturn ret;","}","","static PatternList parse_long(Tokens\u0026 tokens, std::vector\u003cOption\u003e\u0026 options)","{","\t// long ::= '--' chars [ ( ' ' | '=' ) chars ] ;","\tstd::string longOpt, equal;","\tvalue val;","\tstd::tie(longOpt, equal, val) = partition(tokens.pop(), \"=\");","","\tassert(starts_with(longOpt, \"--\"));","","\tif (equal.empty()) {","\t\tval = value{};","\t}","","\t// detect with options match this long option","\tstd::vector\u003cOption const*\u003e similar;","\tfor(auto const\u0026 option : options) {","\t\tif (option.longOption()==longOpt)","\t\t\tsimilar.push_back(\u0026option);","\t}","","\t// maybe allow similar options that match by prefix","\tif (tokens.isParsingArgv() \u0026\u0026 similar.empty()) {","\t\tfor(auto const\u0026 option : options) {","\t\t\tif (option.longOption().empty())","\t\t\t\tcontinue;","\t\t\tif (starts_with(option.longOption(), longOpt))","\t\t\t\tsimilar.push_back(\u0026option);","\t\t}","\t}","","\tPatternList ret;","","\tif (similar.size() \u003e 1) { // might be simply specified ambiguously 2+ times?","\t\tstd::vector\u003cstd::string\u003e prefixes = longOptions(similar.begin(), similar.end());","\t\tstd::string error = \"'\" + longOpt + \"' is not a unique prefix: \";","\t\terror.append(join(prefixes.begin(), prefixes.end(), \", \"));","\t\tthrow Tokens::OptionError(std::move(error));","\t} else if (similar.empty()) {","\t\tint argcount = equal.empty() ? 0 : 1;","\t\toptions.emplace_back(\"\", longOpt, argcount);","","\t\tauto o = std::make_shared\u003cOption\u003e(options.back());","\t\tif (tokens.isParsingArgv()) {","\t\t\to-\u003esetValue(argcount ? value{val} : value{true});","\t\t}","\t\tret.push_back(o);","\t} else {","\t\tauto o = std::make_shared\u003cOption\u003e(*similar[0]);","\t\tif (o-\u003eargCount() == 0) {","\t\t\tif (val) {","\t\t\t\tstd::string error = o-\u003elongOption() + \" must not have an argument\";","\t\t\t\tthrow Tokens::OptionError(std::move(error));","\t\t\t}","\t\t} else {","\t\t\tif (!val) {","\t\t\t\tauto const\u0026 token = tokens.current();","\t\t\t\tif (token.empty() || token==\"--\") {","\t\t\t\t\tstd::string error = o-\u003elongOption() + \" requires an argument\";","\t\t\t\t\tthrow Tokens::OptionError(std::move(error));","\t\t\t\t}","\t\t\t\tval = tokens.pop();","\t\t\t}","\t\t}","\t\tif (tokens.isParsingArgv()) {","\t\t\to-\u003esetValue(val ? std::move(val) : value{true});","\t\t}","\t\tret.push_back(o);","\t}","","\treturn ret;","}","","static PatternList parse_short(Tokens\u0026 tokens, std::vector\u003cOption\u003e\u0026 options)","{","\t// shorts ::= '-' ( chars )* [ [ ' ' ] chars ] ;","","\tauto token = tokens.pop();","","\tassert(starts_with(token, \"-\"));","\tassert(!starts_with(token, \"--\"));","","\tauto i = token.begin();","\t++i; // skip the leading '-'","","\tPatternList ret;","\twhile (i != token.end()) {","\t\tstd::string shortOpt = { '-', *i };","\t\t++i;","","\t\tstd::vector\u003cOption const*\u003e similar;","\t\tfor(auto const\u0026 option : options) {","\t\t\tif (option.shortOption()==shortOpt)","\t\t\t\tsimilar.push_back(\u0026option);","\t\t}","","\t\tif (similar.size() \u003e 1) {","\t\t\tstd::string error = shortOpt + \" is specified ambiguously \"","\t\t\t+ std::to_string(similar.size()) + \" times\";","\t\t\tthrow Tokens::OptionError(std::move(error));","\t\t} else if (similar.empty()) {","\t\t\toptions.emplace_back(shortOpt, \"\", 0);","","\t\t\tauto o = std::make_shared\u003cOption\u003e(options.back());","\t\t\tif (tokens.isParsingArgv()) {","\t\t\t\to-\u003esetValue(value{true});","\t\t\t}","\t\t\tret.push_back(o);","\t\t} else {","\t\t\tauto o = std::make_shared\u003cOption\u003e(*similar[0]);","\t\t\tvalue val;","\t\t\tif (o-\u003eargCount()) {","\t\t\t\tif (i == token.end()) {","\t\t\t\t\t// consume the next token","\t\t\t\t\tauto const\u0026 ttoken = tokens.current();","\t\t\t\t\tif (ttoken.empty() || ttoken==\"--\") {","\t\t\t\t\t\tstd::string error = shortOpt + \" requires an argument\";","\t\t\t\t\t\tthrow Tokens::OptionError(std::move(error));","\t\t\t\t\t}","\t\t\t\t\tval = tokens.pop();","\t\t\t\t} else {","\t\t\t\t\t// consume all the rest","\t\t\t\t\tval = std::string{i, token.end()};","\t\t\t\t\ti = token.end();","\t\t\t\t}","\t\t\t}","","\t\t\tif (tokens.isParsingArgv()) {","\t\t\t\to-\u003esetValue(val ? std::move(val) : value{true});","\t\t\t}","\t\t\tret.push_back(o);","\t\t}","\t}","","\treturn ret;","}","","static PatternList parse_expr(Tokens\u0026 tokens, std::vector\u003cOption\u003e\u0026 options);","","static PatternList parse_atom(Tokens\u0026 tokens, std::vector\u003cOption\u003e\u0026 options)","{","\t// atom ::= '(' expr ')' | '[' expr ']' | 'options'","\t// | long | shorts | argument | command ;","","\tstd::string const\u0026 token = tokens.current();","","\tPatternList ret;","","\tif (token == \"[\") {","\t\ttokens.pop();","","\t\tauto expr = parse_expr(tokens, options);","","\t\tauto trailing = tokens.pop();","\t\tif (trailing != \"]\") {","\t\t\tthrow DocoptLanguageError(\"Mismatched '['\");","\t\t}","","\t\tret.emplace_back(std::make_shared\u003cOptional\u003e(std::move(expr)));","\t} else if (token==\"(\") {","\t\ttokens.pop();","","\t\tauto expr = parse_expr(tokens, options);","","\t\tauto trailing = tokens.pop();","\t\tif (trailing != \")\") {","\t\t\tthrow DocoptLanguageError(\"Mismatched '('\");","\t\t}","","\t\tret.emplace_back(std::make_shared\u003cRequired\u003e(std::move(expr)));","\t} else if (token == \"options\") {","\t\ttokens.pop();","\t\tret.emplace_back(std::make_shared\u003cOptionsShortcut\u003e());","\t} else if (starts_with(token, \"--\") \u0026\u0026 token != \"--\") {","\t\tret = parse_long(tokens, options);","\t} else if (starts_with(token, \"-\") \u0026\u0026 token != \"-\" \u0026\u0026 token != \"--\") {","\t\tret = parse_short(tokens, options);","\t} else if (is_argument_spec(token)) {","\t\tret.emplace_back(std::make_shared\u003cArgument\u003e(tokens.pop()));","\t} else {","\t\tret.emplace_back(std::make_shared\u003cCommand\u003e(tokens.pop()));","\t}","","\treturn ret;","}","","static PatternList parse_seq(Tokens\u0026 tokens, std::vector\u003cOption\u003e\u0026 options)","{","\t// seq ::= ( atom [ '...' ] )* ;\"\"\"","","\tPatternList ret;","","\twhile (tokens) {","\t\tauto const\u0026 token = tokens.current();","","\t\tif (token==\"]\" || token==\")\" || token==\"|\")","\t\t\tbreak;","","\t\tauto atom = parse_atom(tokens, options);","\t\tif (tokens.current() == \"...\") {","\t\t\tret.emplace_back(std::make_shared\u003cOneOrMore\u003e(std::move(atom)));","\t\t\ttokens.pop();","\t\t} else {","\t\t\tstd::move(atom.begin(), atom.end(), std::back_inserter(ret));","\t\t}","\t}","","\treturn ret;","}","","static std::shared_ptr\u003cPattern\u003e maybe_collapse_to_required(PatternList\u0026\u0026 seq)","{","\tif (seq.size()==1) {","\t\treturn std::move(seq[0]);","\t}","\treturn std::make_shared\u003cRequired\u003e(std::move(seq));","}","","static std::shared_ptr\u003cPattern\u003e maybe_collapse_to_either(PatternList\u0026\u0026 seq)","{","\tif (seq.size()==1) {","\t\treturn std::move(seq[0]);","\t}","\treturn std::make_shared\u003cEither\u003e(std::move(seq));","}","","PatternList parse_expr(Tokens\u0026 tokens, std::vector\u003cOption\u003e\u0026 options)","{","\t// expr ::= seq ( '|' seq )* ;","","\tauto seq = parse_seq(tokens, options);","","\tif (tokens.current() != \"|\")","\t\treturn seq;","","\tPatternList ret;","\tret.emplace_back(maybe_collapse_to_required(std::move(seq)));","","\twhile (tokens.current() == \"|\") {","\t\ttokens.pop();","\t\tseq = parse_seq(tokens, options);","\t\tret.emplace_back(maybe_collapse_to_required(std::move(seq)));","\t}","","\treturn { maybe_collapse_to_either(std::move(ret)) };","}","","static Required parse_pattern(std::string const\u0026 source, std::vector\u003cOption\u003e\u0026 options)","{","\tauto tokens = Tokens::from_pattern(source);","\tauto result = parse_expr(tokens, options);","","\tif (tokens)","\t\tthrow DocoptLanguageError(\"Unexpected ending: '\" + tokens.the_rest() + \"'\");","","\tassert(result.size() == 1 \u0026\u0026 \"top level is always one big\");","\treturn Required{ std::move(result) };","}","","","static std::string formal_usage(std::string const\u0026 section) {","\tstd::string ret = \"(\";","","\tauto i = section.find(':')+1; // skip past \"usage:\"","\tauto parts = split(section, i);","\tfor(size_t ii = 1; ii \u003c parts.size(); ++ii) {","\t\tif (parts[ii] == parts[0]) {","\t\t\tret += \" ) | (\";","\t\t} else {","\t\t\tret.push_back(' ');","\t\t\tret += parts[ii];","\t\t}","\t}","","\tret += \" )\";","\treturn ret;","}","","static PatternList parse_argv(Tokens tokens, std::vector\u003cOption\u003e\u0026 options, bool options_first)","{","\t// Parse command-line argument vector.","\t//","\t// If options_first:","\t// argv ::= [ long | shorts ]* [ argument ]* [ '--' [ argument ]* ] ;","\t// else:","\t// argv ::= [ long | shorts | argument ]* [ '--' [ argument ]* ] ;","","\tPatternList ret;","\twhile (tokens) {","\t\tauto const\u0026 token = tokens.current();","","\t\tif (token==\"--\") {","\t\t\t// option list is done; convert all the rest to arguments","\t\t\twhile (tokens) {","\t\t\t\tret.emplace_back(std::make_shared\u003cArgument\u003e(\"\", tokens.pop()));","\t\t\t}","\t\t} else if (starts_with(token, \"--\")) {","\t\t\tauto\u0026\u0026 parsed = parse_long(tokens, options);","\t\t\tstd::move(parsed.begin(), parsed.end(), std::back_inserter(ret));","\t\t} else if (token[0]=='-' \u0026\u0026 token != \"-\") {","\t\t\tauto\u0026\u0026 parsed = parse_short(tokens, options);","\t\t\tstd::move(parsed.begin(), parsed.end(), std::back_inserter(ret));","\t\t} else if (options_first) {","\t\t\t// option list is done; convert all the rest to arguments","\t\t\twhile (tokens) {","\t\t\t\tret.emplace_back(std::make_shared\u003cArgument\u003e(\"\", tokens.pop()));","\t\t\t}","\t\t} else {","\t\t\tret.emplace_back(std::make_shared\u003cArgument\u003e(\"\", tokens.pop()));","\t\t}","\t}","","\treturn ret;","}","","std::vector\u003cOption\u003e parse_defaults(std::string const\u0026 doc) {","\t// This pattern is a delimiter by which we split the options.","\t// The delimiter is a new line followed by a whitespace(s) followed by one or two hyphens.","\tstatic std::regex const re_delimiter{","\t\t\"(?:^|\\\\n)[ \\\\t]*\" // a new line with leading whitespace","\t\t\"(?=-{1,2})\" // [split happens here] (positive lookahead) ... and followed by one or two hyphes","\t};","","\tstd::vector\u003cOption\u003e defaults;","\tfor (auto s : parse_section(\"options:\", doc)) {","\t\ts.erase(s.begin(), s.begin() + static_cast\u003cstd::ptrdiff_t\u003e(s.find(':')) + 1); // get rid of \"options:\"","","\t\tfor (const auto\u0026 opt : regex_split(s, re_delimiter)) {","\t\t\tif (starts_with(opt, \"-\")) {","\t\t\t\tdefaults.emplace_back(Option::parse(opt));","\t\t\t}","\t\t}","\t}","","\treturn defaults;","}","","static bool isOptionSet(PatternList const\u0026 options, std::string const\u0026 opt1, std::string const\u0026 opt2 = \"\") {","\treturn std::any_of(options.begin(), options.end(), [\u0026](std::shared_ptr\u003cPattern const\u003e const\u0026 opt) -\u003e bool {","\t\tauto const\u0026 name = opt-\u003ename();","\t\tif (name==opt1 || (!opt2.empty() \u0026\u0026 name==opt2)) {","\t\t\treturn opt-\u003ehasValue();","\t\t}","\t\treturn false;","\t});","}","","static void extras(bool help, bool version, PatternList const\u0026 options) {","\tif (help \u0026\u0026 isOptionSet(options, \"-h\", \"--help\")) {","\t\tthrow DocoptExitHelp();","\t}","","\tif (version \u0026\u0026 isOptionSet(options, \"--version\")) {","\t\tthrow DocoptExitVersion();","\t}","}","","// Parse the doc string and generate the Pattern tree","static std::pair\u003cRequired, std::vector\u003cOption\u003e\u003e create_pattern_tree(std::string const\u0026 doc)","{","\tauto usage_sections = parse_section(\"usage:\", doc);","\tif (usage_sections.empty()) {","\t\tthrow DocoptLanguageError(\"'usage:' (case-insensitive) not found.\");","\t}","\tif (usage_sections.size() \u003e 1) {","\t\tthrow DocoptLanguageError(\"More than one 'usage:' (case-insensitive).\");","\t}","","\tstd::vector\u003cOption\u003e options = parse_defaults(doc);","\tRequired pattern = parse_pattern(formal_usage(usage_sections[0]), options);","","\tstd::vector\u003cOption const*\u003e pattern_options = flat_filter\u003cOption const\u003e(pattern);","","\tusing UniqueOptions = std::unordered_set\u003cOption const*, PatternHasher, PatternPointerEquality\u003e;","\tUniqueOptions const uniq_pattern_options { pattern_options.begin(), pattern_options.end() };","","\t// Fix up any \"[options]\" shortcuts with the actual option tree","\tfor(auto\u0026 options_shortcut : flat_filter\u003cOptionsShortcut\u003e(pattern)) {","\t\tstd::vector\u003cOption\u003e doc_options = parse_defaults(doc);","","\t\t// set(doc_options) - set(pattern_options)","\t\tUniqueOptions uniq_doc_options;","\t\tfor(auto const\u0026 opt : doc_options) {","\t\t\tif (uniq_pattern_options.count(\u0026opt))","\t\t\t\tcontinue;","\t\t\tuniq_doc_options.insert(\u0026opt);","\t\t}","","\t\t// turn into shared_ptr's and set as children","\t\tPatternList children;","\t\tstd::transform(uniq_doc_options.begin(), uniq_doc_options.end(),","\t\t\t std::back_inserter(children), [](Option const* opt) {","\t\t\t\t return std::make_shared\u003cOption\u003e(*opt);","\t\t\t });","\t\toptions_shortcut-\u003esetChildren(std::move(children));","\t}","","\treturn { std::move(pattern), std::move(options) };","}","","DOCOPT_INLINE","std::map\u003cstd::string, value\u003e","docopt::docopt_parse(std::string const\u0026 doc,","\t\t std::vector\u003cstd::string\u003e const\u0026 argv,","\t\t bool help,","\t\t bool version,","\t\t bool options_first)","{","\tRequired pattern;","\tstd::vector\u003cOption\u003e options;","\ttry {","\t\tstd::tie(pattern, options) = create_pattern_tree(doc);","\t} catch (Tokens::OptionError const\u0026 error) {","\t\tthrow DocoptLanguageError(error.what());","\t}","","\tPatternList argv_patterns;","\ttry {","\t\targv_patterns = parse_argv(Tokens(argv), options, options_first);","\t} catch (Tokens::OptionError const\u0026 error) {","\t\tthrow DocoptArgumentError(error.what());","\t}","","\textras(help, version, argv_patterns);","","\tstd::vector\u003cstd::shared_ptr\u003cLeafPattern\u003e\u003e collected;","\tbool matched = pattern.fix().match(argv_patterns, collected);","\tif (matched \u0026\u0026 argv_patterns.empty()) {","\t\tstd::map\u003cstd::string, value\u003e ret;","","\t\t// (a.name, a.value) for a in (pattern.flat() + collected)","\t\tfor (auto* p : pattern.leaves()) {","\t\t\tret[p-\u003ename()] = p-\u003egetValue();","\t\t}","","\t\tfor (auto const\u0026 p : collected) {","\t\t\tret[p-\u003ename()] = p-\u003egetValue();","\t\t}","","\t\treturn ret;","\t}","","\tif (matched) {","\t\tstd::string leftover = join(argv.begin(), argv.end(), \", \");","\t\tthrow DocoptArgumentError(\"Unexpected argument: \" + leftover);","\t}","","\tthrow DocoptArgumentError(\"Arguments did not match expected patterns\"); // BLEH. Bad error.","}","","DOCOPT_INLINE","std::map\u003cstd::string, value\u003e","docopt::docopt(std::string const\u0026 doc,","\t std::vector\u003cstd::string\u003e const\u0026 argv,","\t bool help,","\t std::string const\u0026 version,","\t bool options_first) noexcept","{","\ttry {","\t\treturn docopt_parse(doc, argv, help, !version.empty(), options_first);","\t} catch (DocoptExitHelp const\u0026) {","\t\tstd::cout \u003c\u003c doc \u003c\u003c std::endl;","\t\tstd::exit(0);","\t} catch (DocoptExitVersion const\u0026) {","\t\tstd::cout \u003c\u003c version \u003c\u003c std::endl;","\t\tstd::exit(0);","\t} catch (DocoptLanguageError const\u0026 error) {","\t\tstd::cerr \u003c\u003c \"Docopt usage string could not be parsed\" \u003c\u003c std::endl;","\t\tstd::cerr \u003c\u003c error.what() \u003c\u003c std::endl;","\t\tstd::exit(-1);","\t} catch (DocoptArgumentError const\u0026 error) {","\t\tstd::cerr \u003c\u003c error.what();","\t\tstd::cout \u003c\u003c std::endl;","\t\tstd::cout \u003c\u003c doc \u003c\u003c std::endl;","\t\tstd::exit(-1);","\t} /* Any other exception is unexpected: let std::terminate grab it */","}"],"stylingDirectives":null,"colorizedLines":null,"csv":null,"csvError":null,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/OSVR/docopt.cpp/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"docopt.cpp","displayUrl":"https://github.com/OSVR/docopt.cpp/blob/master/docopt.cpp?raw=true","headerInfo":{"blobSize":"18.6 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"e875d2f","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2FOSVR%2Fdocopt.cpp%2Fblob%2Fmaster%2Fdocopt.cpp","isCSV":false,"isRichtext":false,"toc":null,"lineInfo":{"truncatedLoc":"685","truncatedSloc":"573"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"issueTemplate":null,"discussionTemplate":null,"language":"C++","languageID":43,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/OSVR/docopt.cpp/blob/master/docopt.cpp","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/OSVR/docopt.cpp/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/OSVR/docopt.cpp/raw/refs/heads/master/docopt.cpp","renderImageOrRaw":false,"richText":null,"renderedFileInfo":null,"shortPath":null,"symbolsEnabled":true,"tabSize":8,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":null,"showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null,"symbols":null},"copilotInfo":null,"copilotAccessAllowed":false,"modelsAccessAllowed":false,"modelsRepoIntegrationEnabled":false,"csrf_tokens":{"/OSVR/docopt.cpp/branches":{"post":"BPb6m_izitDJLyZXbjS_Pay-yh1yA1WzUlY3gYV6CShxzUWUlDv1K6QNqqGWKKvBCAYjhgxhkBu41yVseizwbQ"},"/repos/preferences":{"post":"_gTuvyQefwVaco0_SP0AsGJJsJbK7-9bacdyUNdqBpFeEP21nVqxDo_rBdlW0Y8I-IThuWDpyrLS8j9JTWkhvw"}}},"title":"docopt.cpp/docopt.cpp at master · OSVR/docopt.cpp","appPayload":{"helpUrl":"https://docs.github.com","findFileWorkerPath":"/assets-cdn/worker/find-file-worker-263cab1760dd.js","findInFileWorkerPath":"/assets-cdn/worker/find-in-file-worker-b84e9496fc59.js","githubDevUrl":null,"enabled_features":{"code_nav_ui_events":false,"react_blob_overlay":false,"accessible_code_button":true}}}
0