| 55 | } |
| 56 | |
| 57 | std::optional<int> CommandLine::process(const std::wstring& line) |
| 58 | { |
| 59 | try { |
| 60 | auto args = po::split_winmain(line); |
| 61 | if (!args.empty()) { |
| 62 | // remove program name |
| 63 | args.erase(args.begin()); |
| 64 | } |
| 65 | |
| 66 | // parsing the first part of the command line, including global options and |
| 67 | // command name, but not the rest, which will be collected below |
| 68 | |
| 69 | auto parsed = po::wcommand_line_parser(args) |
| 70 | .options(m_allOptions) |
| 71 | .positional(m_positional) |
| 72 | .allow_unregistered() |
| 73 | .run(); |
| 74 | |
| 75 | po::store(parsed, m_vm); |
| 76 | po::notify(m_vm); |
| 77 | |
| 78 | // collect options past the command name |
| 79 | auto opts = po::collect_unrecognized(parsed.options, po::include_positional); |
| 80 | |
| 81 | if (m_vm.count("command")) { |
| 82 | // there's a word as the first argument; this may be a command name or |
| 83 | // an old style exe name/binary |
| 84 | |
| 85 | const auto commandName = m_vm["command"].as<std::string>(); |
| 86 | |
| 87 | // look for the command by name first |
| 88 | for (auto&& c : m_commands) { |
| 89 | if (c->name() == commandName) { |
| 90 | // this is a command |
| 91 | |
| 92 | // remove the command name itself |
| 93 | opts.erase(opts.begin()); |
| 94 | |
| 95 | try { |
| 96 | // legacy commands handle their own parsing, such as 'launch'; don't |
| 97 | // attempt to parse anything here |
| 98 | if (!c->legacy()) { |
| 99 | // parse the the remainder of the command line according to the |
| 100 | // command's options |
| 101 | po::wcommand_line_parser parser(opts); |
| 102 | |
| 103 | auto co = c->allOptions(); |
| 104 | parser.options(co); |
| 105 | |
| 106 | auto pos = c->positional(); |
| 107 | parser.positional(pos); |
| 108 | |
| 109 | parsed = parser.run(); |
| 110 | |
| 111 | po::store(parsed, m_vm); |
| 112 | |
| 113 | if (m_vm.count("help")) { |
| 114 | env::Console console; |
no test coverage detected