📄 options_description.cpp
字号:
// For now, we don't check the situation when there are // two full matches. if (r == option_description::full_match) { return m_options[i].get(); } found = m_options[i]; // FIXME: the use of 'key' here might not // be the best approach. approximate_matches.push_back(m_options[i]->key(name)); } if (approximate_matches.size() > 1) boost::throw_exception( ambiguous_option(name, approximate_matches)); return found.get(); } BOOST_PROGRAM_OPTIONS_DECL std::ostream& operator<<(std::ostream& os, const options_description& desc) { desc.print(os); return os; } namespace { /* Given a string 'par', that contains no newline characters outputs it to 'os' with wordwrapping, that is, as several line. Each output line starts with 'indent' space characters, following by characters from 'par'. The total length of line is no longer than 'line_length'. */ void format_paragraph(std::ostream& os, std::string par, unsigned indent, unsigned line_length) { // Through reminder of this function, 'line_length' will // be the length available for characters, not including // indent. assert(indent < line_length); line_length -= indent; // index of tab (if present) is used as additional indent relative // to first_column_width if paragrapth is spanned over multiple // lines if tab is not on first line it is ignored string::size_type par_indent = par.find('\t'); if (par_indent == string::npos) { par_indent = 0; } else { // only one tab per paragraph allowed if (count(par.begin(), par.end(), '\t') > 1) { boost::throw_exception(program_options::error( "Only one tab per paragraph is allowed")); } // erase tab from string par.erase(par_indent, 1); // this assert may fail due to user error or // environment conditions! assert(par_indent < line_length); // ignore tab if not on first line if (par_indent >= line_length) { par_indent = 0; } } if (par.size() < line_length) { os << par; } else { string::const_iterator line_begin = par.begin(); const string::const_iterator par_end = par.end(); bool first_line = true; // of current paragraph! while (line_begin < par_end) // paragraph lines { if (!first_line) { // If line starts with space, but second character // is not space, remove the leading space. // We don't remove double spaces because those // might be intentianal. if ((*line_begin == ' ') && ((line_begin + 1 < par_end) && (*(line_begin + 1) != ' '))) { line_begin += 1; // line_begin != line_end } } // Take care to never increment the iterator past // the end, since MSVC 8.0 (brokenly), assumes that // doing that, even if no access happens, is a bug. unsigned remaining = distance(line_begin, par_end); string::const_iterator line_end = line_begin + ((remaining < line_length) ? remaining : line_length); // prevent chopped words // Is line_end between two non-space characters? if ((*(line_end - 1) != ' ') && ((line_end < par_end) && (*line_end != ' '))) { // find last ' ' in the second half of the current paragraph line string::const_iterator last_space = find(reverse_iterator<string::const_iterator>(line_end), reverse_iterator<string::const_iterator>(line_begin), ' ') .base(); if (last_space != line_begin) { // is last_space within the second half ot the // current line if ((unsigned)distance(last_space, line_end) < (line_length - indent) / 2) { line_end = last_space; } } } // prevent chopped words // write line to stream copy(line_begin, line_end, ostream_iterator<char>(os)); if (first_line) { indent += par_indent; first_line = false; } // more lines to follow? if (line_end != par_end) { os << '\n'; for(unsigned pad = indent; pad > 0; --pad) { os.put(' '); } } // next line starts after of this line line_begin = line_end; } // paragraph lines } } void format_description(std::ostream& os, const std::string& desc, unsigned first_column_width, unsigned line_length) { // we need to use one char less per line to work correctly if actual // console has longer lines assert(line_length > 1); if (line_length > 1) { --line_length; } // line_length must be larger than first_column_width // this assert may fail due to user error or environment conditions! assert(line_length > first_column_width); // Note: can't use 'tokenizer' as name of typedef -- borland // will consider uses of 'tokenizer' below as uses of // boost::tokenizer, not typedef. typedef boost::tokenizer<boost::char_separator<char> > tok; tok paragraphs( desc, char_separator<char>("\n", "", boost::keep_empty_tokens)); tok::const_iterator par_iter = paragraphs.begin(); const tok::const_iterator par_end = paragraphs.end(); while (par_iter != par_end) // paragraphs { format_paragraph(os, *par_iter, first_column_width, line_length); ++par_iter; // prepair next line if any if (par_iter != par_end) { os << '\n'; for(unsigned pad = first_column_width; pad > 0; --pad) { os.put(' '); } } } // paragraphs } void format_one(std::ostream& os, const option_description& opt, unsigned first_column_width, unsigned line_length) { stringstream ss; ss << " " << opt.format_name() << ' ' << opt.format_parameter(); // Don't use ss.rdbuf() since g++ 2.96 is buggy on it. os << ss.str(); if (!opt.description().empty()) { for(unsigned pad = first_column_width - ss.str().size(); pad > 0; --pad) { os.put(' '); } format_description(os, opt.description(), first_column_width, line_length); } } } void options_description::print(std::ostream& os) const { if (!m_caption.empty()) os << m_caption << ":\n"; /* Find the maximum width of the option column */ unsigned width(23); unsigned i; // vc6 has broken for loop scoping for (i = 0; i < m_options.size(); ++i) { const option_description& opt = *m_options[i]; stringstream ss; ss << " " << opt.format_name() << ' ' << opt.format_parameter(); width = (max)(width, static_cast<unsigned>(ss.str().size())); } /* add an additional space to improve readability */ ++width; /* The options formatting style is stolen from Subversion. */ for (i = 0; i < m_options.size(); ++i) { if (belong_to_group[i]) continue; const option_description& opt = *m_options[i]; format_one(os, opt, width, m_line_length); os << "\n"; } for (unsigned j = 0; j < groups.size(); ++j) { os << "\n" << *groups[j]; } }}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -