📄 cmdline.cpp
字号:
option& opt = result[i]; if (opt.position_key != -1) { if (position >= m_positional->max_total_count()) { throw too_many_positional_options_error( "too many positional options"); } opt.string_key = m_positional->name_for_position(position); ++position; } } } return result; } void cmdline::finish_option(option& opt, vector<string>& other_tokens) { if (opt.string_key.empty()) return; // First check that the option is valid, and get its description. // TODO: case-sensitivity. const option_description* xd = m_desc->find_nothrow(opt.string_key, (m_style & allow_guessing) ? true : false); if (!xd) { if (m_allow_unregistered) { opt.unregistered = true; return; } else { boost::throw_exception(unknown_option(opt.string_key)); } } const option_description& d = *xd; // Canonize the name opt.string_key = d.key(opt.string_key); // We check that the min/max number of tokens for the option // agrees with the number of tokens we have. The 'adjacent_value' // (the value in --foo=1) counts as a separate token, and if present // must be consumed. The following tokens on the command line may be // left unconsumed. // We don't check if those tokens look like option, or not! unsigned min_tokens = d.semantic()->min_tokens(); unsigned max_tokens = d.semantic()->max_tokens(); unsigned present_tokens = opt.value.size() + other_tokens.size(); if (present_tokens >= min_tokens) { if (!opt.value.empty() && max_tokens == 0) { throw invalid_command_line_syntax(opt.string_key, invalid_command_line_syntax::extra_parameter); } max_tokens -= opt.value.size(); // A value is optional if min_tokens == 0, but max_tokens > 0. // If a value is optional, it must appear in opt.value (because // it was 'adjacent'. Otherwise, remove the expectation of a // non-adjacent value. (For now, we just check max_tokens == 1, // as there is no current support for max_tokens>1) if (min_tokens == 0 && max_tokens == 1 && opt.value.empty()) --max_tokens; // Everything's OK, move the values to the result. for(;!other_tokens.empty() && max_tokens--; ) { opt.value.push_back(other_tokens[0]); opt.original_tokens.push_back(other_tokens[0]); other_tokens.erase(other_tokens.begin()); } } else { throw invalid_command_line_syntax(opt.string_key, invalid_command_line_syntax::missing_parameter); } } std::vector<option> cmdline::parse_long_option(std::vector<string>& args) { vector<option> result; const std::string& tok = args[0]; if (tok.size() >= 3 && tok[0] == '-' && tok[1] == '-') { string name, adjacent; string::size_type p = tok.find('='); if (p != tok.npos) { name = tok.substr(2, p-2); adjacent = tok.substr(p+1); if (adjacent.empty()) throw invalid_command_line_syntax(name, invalid_command_line_syntax::empty_adjacent_parameter); } else { name = tok.substr(2); } option opt; opt.string_key = name; if (!adjacent.empty()) opt.value.push_back(adjacent); opt.original_tokens.push_back(tok); result.push_back(opt); args.erase(args.begin()); } return result; } std::vector<option> cmdline::parse_short_option(std::vector<string>& args) { const std::string& tok = args[0]; if (tok.size() >= 2 && tok[0] == '-' && tok[1] != '-') { vector<option> result; string name = tok.substr(0,2); string adjacent = tok.substr(2); // Short options can be 'grouped', so that // "-d -a" becomes "-da". Loop, processing one // option at a time. We exit the loop when either // we've processed all the token, or when the remainder // of token is considered to be value, not further grouped // option. for(;;) { const option_description* d = m_desc->find_nothrow(name, false); // FIXME: check for 'allow_sticky'. if (d && (m_style & allow_sticky) && d->semantic()->max_tokens() == 0 && !adjacent.empty()) { // 'adjacent' is in fact further option. option opt; opt.string_key = name; result.push_back(opt); if (adjacent.empty()) { args.erase(args.begin()); break; } name = string("-") + adjacent[0]; adjacent.erase(adjacent.begin()); } else { option opt; opt.string_key = name; opt.original_tokens.push_back(tok); if (!adjacent.empty()) opt.value.push_back(adjacent); result.push_back(opt); args.erase(args.begin()); break; } } return result; } return std::vector<option>(); } std::vector<option> cmdline::parse_dos_option(std::vector<string>& args) { vector<option> result; const std::string& tok = args[0]; if (tok.size() >= 2 && tok[0] == '/') { string name = "-" + tok.substr(1,1); string adjacent = tok.substr(2); option opt; opt.string_key = name; if (!adjacent.empty()) opt.value.push_back(adjacent); opt.original_tokens.push_back(tok); result.push_back(opt); args.erase(args.begin()); } return result; } std::vector<option> cmdline::parse_disguised_long_option(std::vector<string>& args) { const std::string& tok = args[0]; if (tok.size() >= 2 && ((tok[0] == '-' && tok[1] != '-') || ((m_style & allow_slash_for_short) && tok[0] == '/'))) { if (m_desc->find_nothrow(tok.substr(1, tok.find('=')-1), (m_style & allow_guessing) ? true : false)) { args[0].insert(0, "-"); if (args[0][1] == '/') args[0][1] = '-'; return parse_long_option(args); } } return vector<option>(); } std::vector<option> cmdline::parse_terminator(std::vector<std::string>& args) { vector<option> result; const std::string& tok = args[0]; if (tok == "--") { for(unsigned i = 1; i < args.size(); ++i) { option opt; opt.value.push_back(args[i]); result.push_back(opt); } args.clear(); } return result; } std::vector<option> cmdline::handle_additional_parser(std::vector<std::string>& args) { vector<option> result; pair<string, string> r = m_additional_parser(args[0]); if (!r.first.empty()) { option next; next.string_key = r.first; if (!r.second.empty()) next.value.push_back(r.second); result.push_back(next); args.erase(args.begin()); } return result; } void cmdline::set_additional_parser(additional_parser p) { m_additional_parser = p; } void cmdline::extra_style_parser(style_parser s) { m_style_parser = s; }}}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -