From 974f4b395cf941bf611b4fe07985149b156743fb Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Wed, 7 Jun 2017 10:02:07 -0600 Subject: [PATCH] Make ParameterHandler::print_parameters() const. This is done by introducing a new, private function, that duplicates most of what the now deprecated function ParameterHandler::print_parameters_section() does, but without changing the state of the object. The duplication of code will be removed once the deprecated function is removed. --- include/deal.II/base/parameter_handler.h | 38 ++- source/base/parameter_handler.cc | 398 ++++++++++++++++++++++- 2 files changed, 429 insertions(+), 7 deletions(-) diff --git a/include/deal.II/base/parameter_handler.h b/include/deal.II/base/parameter_handler.h index 95abdfd8e3..afcf791a43 100644 --- a/include/deal.II/base/parameter_handler.h +++ b/include/deal.II/base/parameter_handler.h @@ -2060,8 +2060,9 @@ public: * \printindex[prmindexfull] * @endcode */ - std::ostream &print_parameters (std::ostream &out, - const OutputStyle style); + std::ostream & + print_parameters (std::ostream &out, + const OutputStyle style) const; /** * Print out the parameters of the present subsection as given by the @@ -2245,6 +2246,11 @@ private: */ static const char path_separator = '.'; + /** + * Path of presently selected subsections; empty list means top level + */ + std::vector subsection_path; + /** * The complete tree of sections and entries. See the general documentation * of this class for a description how data is stored in this variable. @@ -2282,14 +2288,22 @@ private: static std::string demangle (const std::string &s); /** - * Path of presently selected subsections; empty list means top level + * Given a list of directories and subdirectories that identify + * a particular place in the tree, return the string that identifies + * this place in the way the BOOST property tree libraries likes + * to identify things. */ - std::vector subsection_path; + static + std::string + collate_path_string (const std::vector &subsection_path); /** * Return the string that identifies the current path into the property * tree. This is only a path, i.e. it is not terminated by the * path_separator character. + * + * This function simply calls collate_path_string() with + * @p subsection_path as argument */ std::string get_current_path () const; @@ -2315,6 +2329,22 @@ private: const std::string &input_filename, const unsigned int current_line_n); + /** + * Print out the parameters of the subsection given by the + * @p target_subsection_path argument, as well as all subsections + * within it recursively. This function is called from the + * print_parameters() function, and is implemented for all @p style + * arguments other than XML and JSON (where we can output the + * entire set of parameters via BOOST functions). The @p indent_level + * argument indicates how many spaces the output should be indented, + * so that subsections properly nest inside the output of higher + * sections. + */ + void recursively_print_parameters (const std::vector &target_subsection_path, + const OutputStyle style, + const unsigned int indent_level, + std::ostream &out) const; + friend class MultipleParameterLoop; }; diff --git a/source/base/parameter_handler.cc b/source/base/parameter_handler.cc index 4443438a85..9d2f8b9995 100644 --- a/source/base/parameter_handler.cc +++ b/source/base/parameter_handler.cc @@ -1582,8 +1582,9 @@ namespace } + std::string -ParameterHandler::get_current_path () const +ParameterHandler::collate_path_string (const std::vector &subsection_path) { if (subsection_path.size() > 0) { @@ -1600,6 +1601,13 @@ ParameterHandler::get_current_path () const } +std::string +ParameterHandler::get_current_path () const +{ + return collate_path_string (subsection_path); +} + + std::string ParameterHandler::get_current_full_path (const std::string &name) const @@ -2253,7 +2261,7 @@ ParameterHandler::set (const std::string &entry_string, std::ostream & ParameterHandler::print_parameters (std::ostream &out, - const OutputStyle style) + const OutputStyle style) const { AssertThrow (out, ExcIO()); @@ -2311,13 +2319,397 @@ ParameterHandler::print_parameters (std::ostream &out, } // dive recursively into the subsections - print_parameters_section (out, style, 0); + recursively_print_parameters (std::vector(), // start at the top level + style, + 0, + out); return out; } +void +ParameterHandler::recursively_print_parameters (const std::vector &target_subsection_path, + const OutputStyle style, + const unsigned int indent_level, + std::ostream &out) const +{ + AssertThrow (out, ExcIO()); + + // this function should not be necessary for XML or JSON output... + Assert ((style != XML) && (style != JSON), + ExcInternalError()); + + const boost::property_tree::ptree ¤t_section + = entries->get_child (collate_path_string(target_subsection_path)); + + unsigned int overall_indent_level = indent_level; + + switch (style) + { + case Text: + case ShortText: + { + // first find out the longest entry name to be able to align the + // equal signs to do this loop over all nodes of the current + // tree, select the parameter nodes (and discard sub-tree nodes) + // and take the maximum of their lengths + // + // likewise find the longest actual value string to make sure we + // can align the default and documentation strings + std::size_t longest_name = 0; + std::size_t longest_value = 0; + for (boost::property_tree::ptree::const_iterator + p = current_section.begin(); + p != current_section.end(); ++p) + if (is_parameter_node (p->second) == true) + { + longest_name = std::max (longest_name, + demangle(p->first).length()); + longest_value = std::max (longest_value, + p->second.get("value").length()); + } + + // print entries one by one. make sure they are sorted by using + // the appropriate iterators + bool first_entry = true; + for (boost::property_tree::ptree::const_assoc_iterator + p = current_section.ordered_begin(); + p != current_section.not_found(); ++p) + if (is_parameter_node (p->second) == true) + { + const std::string value = p->second.get("value"); + + // if there is documentation, then add an empty line + // (unless this is the first entry in a subsection), print + // the documentation, and then the actual entry; break the + // documentation into readable chunks such that the whole + // thing is at most 78 characters wide + if ((!(style & 128)) && + !p->second.get("documentation").empty()) + { + if (first_entry == false) + out << '\n'; + else + first_entry = false; + + const std::vector doc_lines + = Utilities:: + break_text_into_lines (p->second.get("documentation"), + 78 - overall_indent_level*2 - 2); + + for (unsigned int i=0; ifirst) + << std::setw(longest_name-demangle(p->first).length()+1) << " " + << "= " << value; + + // finally print the default value, but only if it differs + // from the actual value + if ((!(style & 64)) && value != p->second.get("default_value")) + { + out << std::setw(longest_value-value.length()+1) << ' ' + << "# "; + out << "default: " << p->second.get("default_value"); + } + + out << '\n'; + } + + break; + } + + case LaTeX: + { + // if there are any parameters in this section then print them + // as an itemized list + bool parameters_exist_here = false; + for (boost::property_tree::ptree::const_assoc_iterator + p = current_section.ordered_begin(); + p != current_section.not_found(); ++p) + if ((is_parameter_node (p->second) == true) + || + (is_alias_node (p->second) == true)) + { + parameters_exist_here = true; + break; + } + + if (parameters_exist_here) + { + out << "\\begin{itemize}" + << '\n'; + + // print entries one by one. make sure they are sorted by + // using the appropriate iterators + for (boost::property_tree::ptree::const_assoc_iterator + p = current_section.ordered_begin(); + p != current_section.not_found(); ++p) + if (is_parameter_node (p->second) == true) + { + const std::string value = p->second.get("value"); + + // print name + out << "\\item {\\it Parameter name:} {\\tt " << demangle(p->first) << "}\n" + << "\\phantomsection\\label{parameters:"; + for (unsigned int i=0; ifirst); + out << "}\n\n" + << '\n'; + + out << "\\index[prmindex]{" + << demangle(p->first) + << "}\n"; + out << "\\index[prmindexfull]{"; + for (unsigned int i=0; ifirst) + << "}\n"; + + // finally print value and default + out << "{\\it Value:} " << value << "\n\n" + << '\n' + << "{\\it Default:} " + << p->second.get("default_value") << "\n\n" + << '\n'; + + // if there is a documenting string, print it as well + if (!p->second.get("documentation").empty()) + out << "{\\it Description:} " + << p->second.get("documentation") << "\n\n" + << '\n'; + + // also output possible values + const unsigned int pattern_index = p->second.get ("pattern"); + const std::string desc_str = patterns[pattern_index]->description (Patterns::PatternBase::LaTeX); + out << "{\\it Possible values:} " + << desc_str + << '\n'; + } + else if (is_alias_node (p->second) == true) + { + const std::string alias = p->second.get("alias"); + + // print name + out << "\\item {\\it Parameter name:} {\\tt " << demangle(p->first) << "}\n" + << "\\phantomsection\\label{parameters:"; + for (unsigned int i=0; ifirst); + out << "}\n\n" + << '\n'; + + out << "\\index[prmindex]{" + << demangle(p->first) + << "}\n"; + out << "\\index[prmindexfull]{"; + for (unsigned int i=0; ifirst) + << "}\n"; + + // finally print alias and indicate if it is deprecated + out << "This parameter is an alias for the parameter ``\\texttt{" + << alias << "}''." + << (p->second.get("deprecation_status") == "true" + ? + " Its use is deprecated." + : + "") + << "\n\n" + << '\n'; + } + out << "\\end{itemize}" + << '\n'; + } + + break; + } + + case Description: + { + // first find out the longest entry name to be able to align the + // equal signs + std::size_t longest_name = 0; + for (boost::property_tree::ptree::const_iterator + p = current_section.begin(); + p != current_section.end(); ++p) + if (is_parameter_node (p->second) == true) + longest_name = std::max (longest_name, + demangle(p->first).length()); + + // print entries one by one. make sure they are sorted by using + // the appropriate iterators + for (boost::property_tree::ptree::const_assoc_iterator + p = current_section.ordered_begin(); + p != current_section.not_found(); ++p) + if (is_parameter_node (p->second) == true) + { + // print name and value + out << std::setw(overall_indent_level*2) << "" + << "set " + << demangle(p->first) + << std::setw(longest_name-demangle(p->first).length()+1) << " " + << " = "; + + // print possible values: + const unsigned int pattern_index = p->second.get ("pattern"); + const std::string full_desc_str = patterns[pattern_index]->description (Patterns::PatternBase::Text); + const std::vector description_str + = Utilities::break_text_into_lines (full_desc_str, + 78 - overall_indent_level*2 - 2, '|'); + if (description_str.size() > 1) + { + out << '\n'; + for (unsigned int i=0; isecond.get("documentation").length() != 0) + out << std::setw(overall_indent_level*2 + longest_name + 10) << "" + << "(" << p->second.get("documentation") << ")" + << '\n'; + } + + break; + } + + default: + Assert (false, ExcNotImplemented()); + } + + + // if there was text before and there are sections to come, put two + // newlines between the last entry and the first subsection + { + unsigned int n_parameters = 0; + unsigned int n_sections = 0; + for (boost::property_tree::ptree::const_iterator + p = current_section.begin(); + p != current_section.end(); ++p) + if (is_parameter_node (p->second) == true) + ++n_parameters; + else if (is_alias_node (p->second) == false) + ++n_sections; + + if ((style != Description) + && + (!(style & 128)) + && + (n_parameters != 0) + && + (n_sections != 0)) + out << "\n\n"; + } + + // now traverse subsections tree, in alphabetical order + for (boost::property_tree::ptree::const_assoc_iterator + p = current_section.ordered_begin(); + p != current_section.not_found(); ++p) + if ((is_parameter_node (p->second) == false) + && + (is_alias_node (p->second) == false)) + { + // first print the subsection header + switch (style) + { + case Text: + case Description: + case ShortText: + out << std::setw(overall_indent_level*2) << "" + << "subsection " << demangle(p->first) + << '\n'; + break; + + case LaTeX: + { + out << '\n' + << "\\subsection{Parameters in section \\tt "; + + // find the path to the current section so that we can + // print it in the \subsection{...} heading + for (unsigned int i=0; ifirst); + + out << "}" << '\n'; + out << "\\label{parameters:"; + for (unsigned int i=0; ifirst << "}"; + out << '\n'; + + out << '\n'; + break; + } + + default: + Assert (false, ExcNotImplemented()); + } + + // then the contents of the subsection + const std::string subsection = demangle(p->first); + std::vector directory_path = target_subsection_path; + directory_path.emplace_back (subsection); + + recursively_print_parameters (directory_path, style, + overall_indent_level+1, + out); + + switch (style) + { + case Text: + // write end of subsection. one blank line after each + // subsection + out << std::setw(overall_indent_level*2) << "" + << "end" << '\n' + << '\n'; + + // if this is a toplevel subsection, then have two + // newlines + if (overall_indent_level == 0) + out << '\n'; + + break; + + case Description: + break; + + case ShortText: + // write end of subsection. + out << std::setw(overall_indent_level*2) << "" + << "end" << '\n'; + break; + + case LaTeX: + break; + + default: + Assert (false, ExcNotImplemented()); + } + } +} + + + // Print a section in the desired style. The styles are separated into // several verbosity classes depending on the higher bits. // -- 2.39.5