From 7148621aac42724aa14ce635199d5b2513ecab10 Mon Sep 17 00:00:00 2001 From: Peter Munch Date: Fri, 17 Apr 2020 21:49:43 +0200 Subject: [PATCH] Extend OutputStyle --- include/deal.II/base/parameter_handler.h | 147 +++- source/base/parameter_handler.cc | 688 +++++++++--------- .../parameter_handler_3_with_sorting_01.cc | 4 +- .../parameter_handler_subsection_exists.cc | 4 +- .../parameter_handler_write_json.cc | 5 +- .../parameter_handler_write_xml.cc | 5 +- 6 files changed, 465 insertions(+), 388 deletions(-) diff --git a/include/deal.II/base/parameter_handler.h b/include/deal.II/base/parameter_handler.h index a9eb31d0af..aece61a6b7 100644 --- a/include/deal.II/base/parameter_handler.h +++ b/include/deal.II/base/parameter_handler.h @@ -846,57 +846,113 @@ class ParameterHandler : public Subscriptor { public: /** - * List of possible output formats used for - * ParameterHandler::print_parameters(). + * List of possible output formats used for functions like + * ParameterHandler::print_parameters(). The options can be categorized into + * two groups: + * - format options: PRM, LaTeX, Description, XML, JSON + * - stylistic options: Short, KeepDeclarationOrder + * + * A valid combination of options is given in the following table: + * + * Stylistic options | Default | PRM | LaTeX | Description | XML | JSON + * -------------------- | ------- | --- | ----- | ----------- | --- | ---- + * Default | X | X | X | X | X | X + * Short | X | X | - | X | X | X + * KeepDeclarationOrder | X | X | X | X | X | X + * + * Valid combinations are checked at the beginning of the functions that + * accept an OutputStyle as an input argument. + * + * Furthermore, a number of shortcuts of commonly used option combinations are + * provided. E.g., ShortPRM prints the parameters in the PRM + * format, while skipping the documentation. */ enum OutputStyle { /** - * Write human readable output suitable to be read by ParameterHandler - * again. + * Default stylistic style: print documentation and sort all parameters + * alphabetically. + */ + DefaultStyle = 0x0000, + + /** + * Write input for ParameterHandler without comments or changed default + * values. + */ + Short = 0x0001, + + /** + * Keep the order of the parameters as they have been declared. + */ + KeepDeclarationOrder = 0x0002, + + /** + * Write human readable output suitable to be read by + * ParameterHandler::parse_input() again. + */ + PRM = 0x0010, + + /** + * Write human readable output suitable to be read by + * ParameterHandler::parse_input() again. + * + * @deprecated Use `PRM` instead of `Text`. */ - Text = 1, + Text = PRM, /** * Write parameters as a LaTeX table. */ - LaTeX = 2, + LaTeX = 0x0020, + /** * Write out declared parameters with description and possible values. + * + * @note This format is not suitable to be read back again. */ - Description = 3, + Description = 0x0040, /** * Write out everything as an XML file. + * href="http://en.wikipedia.org/wiki/XML">XML file suitable to be read + * by ParameterHandler::parse_input_from_xml() again. * * See the general documentation of this class for an example of output. */ - XML = 4, + XML = 0x0080, /** * Write out everything as a JSON file. + * href="http://en.wikipedia.org/wiki/JSON">JSON file suitable to be + * read by ParameterHandler::parse_input_from_json() again. */ - JSON = 5, + JSON = 0x0100, /** * Write input for ParameterHandler without comments or changed default * values. */ - ShortText = 193, + ShortPRM = PRM | Short, + + /** + * Write input for ParameterHandler without comments or changed default + * values. + * + * @deprecated Use `ShortPRM` instead of `ShortText`. + */ + ShortText = ShortPRM, /** * Write input for ParameterHandler without comments or changed default * values as a XML file. */ - ShortXML = 194, + ShortXML = XML | Short, /** * Write input for ParameterHandler without comments or changed default * values as a JSON file. */ - ShortJSON = 195 + ShortJSON = JSON | Short, }; @@ -1345,19 +1401,16 @@ public: set(const std::string &entry_name, const bool new_value); /** - * Print all parameters with the given style to @p out. + * Print all parameters with the given @p style to @p out. * * Before printing, all current parameters and subsections are sorted * alphabetically by default. - * This behavior can be disabled setting the last parameter @p sort_alphabetical - * to false: in this case entries are printed in the same order - * as they have been declared. + * This behavior can be disabled setting the optional parameter @p style + * to KeepDeclarationOrder: in this case entries are printed in the + * same order as they have been declared. * - * In the case of XML or JSON, a reduced tree, only - * containing the values and skipping the documentation, can be - * printed by setting @p print_documentation to false. - * - * In Text format, the output is formatted in such a way that it is + * In PRM, XML, and JSON format, the output is + * formatted in such a way that it is * possible to use it for later input again. This is most useful to record * the parameters for a specific run, since if you output the parameters * using this function into a log file, you can always recover the results @@ -1368,6 +1421,12 @@ public: * well as the documenting string given to the declare_entry() function if * available. * + * By using the flag Short in combination with PRM, + * XML, or JSON (or by using the shortcuts + * ShortPRM, ShortXML, or ShortJSON), a reduced + * output can be generated, only containing the values and skipping the + * documentation. + * * In XML format, the output starts with one root element * ParameterHandler in order to get a valid XML document and all * subsections under it. @@ -1414,9 +1473,7 @@ public: * @endcode */ std::ostream & - print_parameters(std::ostream & out, - const OutputStyle style, - const bool sort_alphabetical = true) const; + print_parameters(std::ostream &out, const OutputStyle style) const; /** * Print parameters to a logstream. This function allows to print all @@ -1425,12 +1482,15 @@ public: * * All current parameters and subsections are sorted * alphabetically by default. - * This behavior can be disabled setting the last parameter @p sort_alphabetical - * to @p false: in this case entries are printed in the same order - * as they have been declared. + * This behavior can be disabled setting the optional parameter @p style + * to KeepDeclarationOrder: in this case entries are printed in the + * same order as they have been declared. + * + * @note All style settings in @p style not related to the ordering are + * ignored. */ void - log_parameters(LogStream &out, const bool sort_alphabetical = true); + log_parameters(LogStream &out, const OutputStyle style = DefaultStyle); /** * Log parameters in the present subsection. The subsection is determined by @@ -1440,15 +1500,19 @@ public: * * All current parameters and subsections are sorted * alphabetically by default. - * This behavior can be disabled setting the last parameter @p sort_alphabetical - * to @p false: in this case entries are printed in the same order - * as they have been declared. + * This behavior can be disabled setting the optional parameter @p style + * to KeepDeclarationOrder: in this case entries are printed in the + * same order as they have been declared. + * + * @note All style settings in @p style not related to the ordering are + * ignored. * * In most cases, you will not want to use this function directly, but have * it called recursively by the previous function. */ void - log_parameters_section(LogStream &out, const bool sort_alphabetical = true); + log_parameters_section(LogStream & out, + const OutputStyle style = DefaultStyle); /** * Determine an estimate for the memory consumption (in bytes) of this @@ -1748,7 +1812,20 @@ private: friend class MultipleParameterLoop; }; - +/** + * Global operator which returns an object in which all bits are set which are + * either set in the first or the second argument. This operator exists since + * if it did not then the result of the bit-or operator | would be an + * integer which would in turn trigger a compiler warning when we tried to + * assign it to an object of type ParameterHandler::OutputStyle. + */ +inline ParameterHandler::OutputStyle +operator|(const ParameterHandler::OutputStyle f1, + const ParameterHandler::OutputStyle f2) +{ + return static_cast( + static_cast(f1) | static_cast(f2)); +} /** * The class MultipleParameterLoop offers an easy possibility to test several diff --git a/source/base/parameter_handler.cc b/source/base/parameter_handler.cc index 4fc7deca58..0b94d0e4e1 100644 --- a/source/base/parameter_handler.cc +++ b/source/base/parameter_handler.cc @@ -329,6 +329,26 @@ namespace } } + /** + * Assert validity of of given output @p style. + */ + void + assert_validity_of_output_style(const ParameterHandler::OutputStyle style) + { + AssertThrow( + (((style & ParameterHandler::XML) != 0) + + ((style & ParameterHandler::JSON) != 0) + + ((style & ParameterHandler::PRM) != 0) + + ((style & ParameterHandler::Description) != 0) + + ((style & ParameterHandler::LaTeX) != 0)) == 1, + ExcMessage( + "You have chosen either no or multiple style formats. You can choose between: PRM, Description, LaTeX, XML, JSON.")); + + AssertThrow(((style & ParameterHandler::LaTeX) && + (style & ParameterHandler::Short)) == false, + ExcMessage("It is not possible to request short LaTex.")); + } + } // namespace @@ -1219,18 +1239,19 @@ ParameterHandler::set(const std::string &entry_string, const bool new_value) std::ostream & ParameterHandler::print_parameters(std::ostream & out, - const OutputStyle style, - const bool sort_alphabetical) const + const OutputStyle style) const { AssertThrow(out, ExcIO()); + assert_validity_of_output_style(style); + // Create entries copy and sort it, if needed. // In this way we ensure that the class state is never // modified by this function. boost::property_tree::ptree current_entries = *entries.get(); // Sort parameters alphabetically, if needed. - if (sort_alphabetical) + if (!(style & KeepDeclarationOrder)) { // Dive recursively into the subsections, // starting from the top level. @@ -1252,13 +1273,13 @@ ParameterHandler::print_parameters(std::ostream & out, // first // explicity eliminate the documentation from the tree if requested - if (style == ShortXML || style == ShortJSON) + if (style & Short) { // modify the copy of the tree recursively_remove_documentation_from_tree(current_entries); } - if (style == XML || style == ShortXML) + if (style & XML) { // call the writer function and exit as there is nothing // further to do down in this function @@ -1276,35 +1297,35 @@ ParameterHandler::print_parameters(std::ostream & out, return out; } - if (style == JSON || style == ShortJSON) + if (style & JSON) { write_json(out, current_entries); return out; } // for all of the other formats, print a preamble: - switch (style) + if ((style & Short) && (style & Text)) { - case Text: - out << "# Listing of Parameters" << std::endl - << "# ---------------------" << std::endl; - break; - - case LaTeX: - out << "\\subsection{Global parameters}" << std::endl; - out << "\\label{parameters:global}" << std::endl; - out << std::endl << std::endl; - break; - - case Description: - out << "Listing of Parameters:" << std::endl << std::endl; - break; - - case ShortText: - break; - - default: - Assert(false, ExcNotImplemented()); + // nothing to do + } + else if (style & Text) + { + out << "# Listing of Parameters" << std::endl + << "# ---------------------" << std::endl; + } + else if (style & LaTeX) + { + out << "\\subsection{Global parameters}" << std::endl; + out << "\\label{parameters:global}" << std::endl; + out << std::endl << std::endl; + } + else if (style & Description) + { + out << "Listing of Parameters:" << std::endl << std::endl; + } + else + { + Assert(false, ExcNotImplemented()); } // dive recursively into the subsections @@ -1329,285 +1350,271 @@ ParameterHandler::recursively_print_parameters( AssertThrow(out, ExcIO()); // this function should not be necessary for XML or JSON output... - Assert((style != XML) && (style != JSON), ExcInternalError()); + Assert(!(style & (XML | JSON)), ExcInternalError()); const boost::property_tree::ptree ¤t_section = tree.get_child(collate_path_string(path_separator, target_subsection_path)); unsigned int overall_indent_level = indent_level; - switch (style) + const bool is_short = style & Short; + + if (style & Text) { - 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 (const auto &p : current_section) - 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()); - } + // 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 (const auto &p : current_section) + 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 - bool first_entry = true; - for (const auto &p : current_section) - if (is_parameter_node(p.second) == true) + // print entries one by one + bool first_entry = true; + for (const auto &p : current_section) + 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 (!is_short && + !p.second.get("documentation").empty()) { - const std::string value = p.second.get("value"); + if (first_entry == false) + out << '\n'; + else + first_entry = false; - // 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 == Text) && - !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 (const auto &doc_line : doc_lines) - out << std::setw(overall_indent_level * 2) << "" - << "# " << doc_line << '\n'; - } + const std::vector doc_lines = + Utilities::break_text_into_lines( + p.second.get("documentation"), + 78 - overall_indent_level * 2 - 2); + for (const auto &doc_line : doc_lines) + out << std::setw(overall_indent_level * 2) << "" + << "# " << doc_line << '\n'; + } - // print name and value of this entry - out << std::setw(overall_indent_level * 2) << "" - << "set " << demangle(p.first) - << 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 == Text) && - value != p.second.get("default_value")) - { - out << std::setw(longest_value - value.length() + 1) << ' ' - << "# "; - out << "default: " - << p.second.get("default_value"); - } + // print name and value of this entry + out << std::setw(overall_indent_level * 2) << "" + << "set " << demangle(p.first) + << std::setw(longest_name - demangle(p.first).length() + 1) + << " " + << "= " << value; - out << '\n'; + // finally print the default value, but only if it differs + // from the actual value + if (!is_short && + value != p.second.get("default_value")) + { + out << std::setw(longest_value - value.length() + 1) << ' ' + << "# "; + out << "default: " + << p.second.get("default_value"); } - break; - } + out << '\n'; + } + } + else if (style & LaTeX) + { + auto escape = [](const std::string &input) { + return Patterns::internal::escape(input, Patterns::PatternBase::LaTeX); + }; - case LaTeX: + // if there are any parameters in this section then print them + // as an itemized list + bool parameters_exist_here = false; + for (const auto &p : current_section) + if ((is_parameter_node(p.second) == true) || + (is_alias_node(p.second) == true)) + { + parameters_exist_here = true; + break; + } + + if (parameters_exist_here) { - auto escape = [](const std::string &input) { - return Patterns::internal::escape(input, - Patterns::PatternBase::LaTeX); - }; - - // if there are any parameters in this section then print them - // as an itemized list - bool parameters_exist_here = false; + out << "\\begin{itemize}" << '\n'; + + // print entries one by one for (const auto &p : current_section) - if ((is_parameter_node(p.second) == true) || - (is_alias_node(p.second) == true)) + if (is_parameter_node(p.second) == true) { - parameters_exist_here = true; - break; - } - - if (parameters_exist_here) - { - out << "\\begin{itemize}" << '\n'; - - // print entries one by one - for (const auto &p : current_section) - if (is_parameter_node(p.second) == true) - { - const std::string value = - p.second.get("value"); + const std::string value = p.second.get("value"); - // print name - out << "\\item {\\it Parameter name:} {\\tt " - << escape(demangle(p.first)) << "}\n" - << "\\phantomsection"; + // print name + out << "\\item {\\it Parameter name:} {\\tt " + << escape(demangle(p.first)) << "}\n" + << "\\phantomsection"; + { + // create label: labels are not to be escaped but + // mangled + std::string label = "parameters:"; + for (const auto &path : target_subsection_path) { - // create label: labels are not to be escaped but - // mangled - std::string label = "parameters:"; - for (const auto &path : target_subsection_path) - { - label.append(mangle(path)); - label.append("/"); - } - label.append(p.first); - // Backwards-compatibility. Output the label with and - // without escaping whitespace: - if (label.find("_20") != std::string::npos) - out << "\\label{" - << Utilities::replace_in_string(label, "_20", " ") - << "}\n"; - out << "\\label{" << label << "}\n"; + label.append(mangle(path)); + label.append("/"); } - out << "\n\n"; - - out << "\\index[prmindex]{" << escape(demangle(p.first)) + label.append(p.first); + // Backwards-compatibility. Output the label with and + // without escaping whitespace: + if (label.find("_20") != std::string::npos) + out << "\\label{" + << Utilities::replace_in_string(label, "_20", " ") << "}\n"; - out << "\\index[prmindexfull]{"; - for (const auto &path : target_subsection_path) - out << escape(path) << "!"; - out << escape(demangle(p.first)) << "}\n"; - - // finally print value and default - out << "{\\it Value:} " << escape(value) << "\n\n" - << '\n' - << "{\\it Default:} " - << escape(p.second.get("default_value")) - << "\n\n" + out << "\\label{" << label << "}\n"; + } + out << "\n\n"; + + out << "\\index[prmindex]{" << escape(demangle(p.first)) + << "}\n"; + out << "\\index[prmindexfull]{"; + for (const auto &path : target_subsection_path) + out << escape(path) << "!"; + out << escape(demangle(p.first)) << "}\n"; + + // finally print value and default + out << "{\\it Value:} " << escape(value) << "\n\n" + << '\n' + << "{\\it Default:} " + << escape(p.second.get("default_value")) + << "\n\n" + << '\n'; + + // if there is a documenting string, print it as well but + // don't escape to allow formatting/formulas + if (!(style & Short)) + if (!p.second.get("documentation").empty()) + out << "{\\it Description:} " + << p.second.get("documentation") << "\n\n" << '\n'; - // if there is a documenting string, print it as well but - // don't escape to allow formatting/formulas - if (!p.second.get("documentation").empty()) - out << "{\\it Description:} " - << p.second.get("documentation") - << "\n\n" - << '\n'; - - // also output possible values, do not escape because the - // description internally will use LaTeX formatting - 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"); + // also output possible values, do not escape because the + // description internally will use LaTeX formatting + 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 " - << escape(demangle(p.first)) << "}\n" - << "\\phantomsection"; + // print name + out << "\\item {\\it Parameter name:} {\\tt " + << escape(demangle(p.first)) << "}\n" + << "\\phantomsection"; + { + // create label: labels are not to be escaped but + // mangled + std::string label = "parameters:"; + for (const auto &path : target_subsection_path) { - // create label: labels are not to be escaped but - // mangled - std::string label = "parameters:"; - for (const auto &path : target_subsection_path) - { - label.append(mangle(path)); - label.append("/"); - } - label.append(p.first); - // Backwards-compatibility. Output the label with and - // without escaping whitespace: - if (label.find("_20") != std::string::npos) - out << "\\label{" - << Utilities::replace_in_string(label, "_20", " ") - << "}\n"; - out << "\\label{" << label << "}\n"; + label.append(mangle(path)); + label.append("/"); } - out << "\n\n"; - - out << "\\index[prmindex]{" << escape(demangle(p.first)) + label.append(p.first); + // Backwards-compatibility. Output the label with and + // without escaping whitespace: + if (label.find("_20") != std::string::npos) + out << "\\label{" + << Utilities::replace_in_string(label, "_20", " ") << "}\n"; - out << "\\index[prmindexfull]{"; - for (const auto &path : target_subsection_path) - out << escape(path) << "!"; - out << escape(demangle(p.first)) << "}\n"; - - // finally print alias and indicate if it is deprecated - out - << "This parameter is an alias for the parameter ``\\texttt{" - << escape(alias) << "}''." - << (p.second.get("deprecation_status") == - "true" ? - " Its use is deprecated." : - "") - << "\n\n" - << '\n'; - } - out << "\\end{itemize}" << '\n'; - } + out << "\\label{" << label << "}\n"; + } + out << "\n\n"; - break; + out << "\\index[prmindex]{" << escape(demangle(p.first)) + << "}\n"; + out << "\\index[prmindexfull]{"; + for (const auto &path : target_subsection_path) + out << escape(path) << "!"; + out << escape(demangle(p.first)) << "}\n"; + + // finally print alias and indicate if it is deprecated + out + << "This parameter is an alias for the parameter ``\\texttt{" + << escape(alias) << "}''." + << (p.second.get("deprecation_status") == + "true" ? + " Its use is deprecated." : + "") + << "\n\n" + << '\n'; + } + out << "\\end{itemize}" << '\n'; } - - case Description: - { - // first find out the longest entry name to be able to align the - // equal signs - std::size_t longest_name = 0; - for (const auto &p : current_section) - if (is_parameter_node(p.second) == true) - longest_name = std::max(longest_name, demangle(p.first).length()); - - // print entries one by one - for (const auto &p : current_section) - if (is_parameter_node(p.second) == true) + } + else if (style & Description) + { + // first find out the longest entry name to be able to align the + // equal signs + std::size_t longest_name = 0; + for (const auto &p : current_section) + if (is_parameter_node(p.second) == true) + longest_name = std::max(longest_name, demangle(p.first).length()); + + // print entries one by one + for (const auto &p : current_section) + 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) { - // 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 (const auto &description : description_str) - out << std::setw(overall_indent_level * 2 + 6) << "" - << description << '\n'; - } - else if (description_str.empty() == false) - out << " " << description_str[0] << '\n'; - else - out << '\n'; - - // if there is a documenting string, print it as well - if (p.second.get("documentation").length() != 0) - out << std::setw(overall_indent_level * 2 + longest_name + 10) - << "" - << "(" << p.second.get("documentation") - << ")" << '\n'; + out << '\n'; + for (const auto &description : description_str) + out << std::setw(overall_indent_level * 2 + 6) << "" + << description << '\n'; } + else if (description_str.empty() == false) + out << " " << description_str[0] << '\n'; + else + out << '\n'; - break; - } - - default: - Assert(false, ExcNotImplemented()); + // if there is a documenting string, print it as well + if (p.second.get("documentation").length() != 0) + out << std::setw(overall_indent_level * 2 + longest_name + 10) + << "" + << "(" << p.second.get("documentation") << ")" + << '\n'; + } + } + else + { + Assert(false, ExcNotImplemented()); } @@ -1622,8 +1629,8 @@ ParameterHandler::recursively_print_parameters( else if (is_alias_node(p.second) == false) ++n_sections; - if ((style != Description) && (style != ShortText) && (n_parameters != 0) && - (n_sections != 0)) + if (!(style & Description) && (!((style & Text) && is_short)) && + (n_parameters != 0) && (n_sections != 0)) out << "\n\n"; } @@ -1633,43 +1640,38 @@ ParameterHandler::recursively_print_parameters( (is_alias_node(p.second) == false)) { // first print the subsection header - switch (style) + if ((style & Text) || (style & Description)) { - case Text: - case Description: - case ShortText: - out << std::setw(overall_indent_level * 2) << "" - << "subsection " << demangle(p.first) << '\n'; - break; - - case LaTeX: - { - auto escape = [](const std::string &input) { - return Patterns::internal::escape( - input, Patterns::PatternBase::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 (const auto &path : target_subsection_path) - out << escape(path) << "/"; - out << escape(demangle(p.first)); - - out << "}" << '\n'; - out << "\\label{parameters:"; - for (const auto &path : target_subsection_path) - out << mangle(path) << "/"; - out << p.first << "}"; - out << '\n'; - - out << '\n'; - break; - } - - default: - Assert(false, ExcNotImplemented()); + out << std::setw(overall_indent_level * 2) << "" + << "subsection " << demangle(p.first) << '\n'; + } + else if (style & LaTeX) + { + auto escape = [](const std::string &input) { + return Patterns::internal::escape(input, + Patterns::PatternBase::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 (const auto &path : target_subsection_path) + out << escape(path) << "/"; + out << escape(demangle(p.first)); + + out << "}" << '\n'; + out << "\\label{parameters:"; + for (const auto &path : target_subsection_path) + out << mangle(path) << "/"; + out << p.first << "}"; + out << '\n'; + + out << '\n'; + } + else + { + Assert(false, ExcNotImplemented()); } // then the contents of the subsection @@ -1680,36 +1682,36 @@ ParameterHandler::recursively_print_parameters( recursively_print_parameters( tree, directory_path, style, overall_indent_level + 1, out); - switch (style) + if (is_short && (style & Text)) { - 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()); + // write end of subsection. + out << std::setw(overall_indent_level * 2) << "" + << "end" << '\n'; + } + else if (style & 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'; + } + else if (style == Description) + { + // nothing to do + } + else if (style == LaTeX) + { + // nothing to do + } + else + { + Assert(false, ExcNotImplemented()); } } } @@ -1717,19 +1719,19 @@ ParameterHandler::recursively_print_parameters( void -ParameterHandler::log_parameters(LogStream &out, const bool sort_alphabetical) +ParameterHandler::log_parameters(LogStream &out, const OutputStyle style) { out.push("parameters"); // dive recursively into the subsections - log_parameters_section(out, sort_alphabetical); + log_parameters_section(out, style); out.pop(); } void -ParameterHandler::log_parameters_section(LogStream &out, - const bool sort_alphabetical) +ParameterHandler::log_parameters_section(LogStream & out, + const OutputStyle style) { // Create entries copy and sort it, if needed. // In this way we ensure that the class state is never @@ -1738,7 +1740,7 @@ ParameterHandler::log_parameters_section(LogStream &out, boost::property_tree::ptree *current_entries = entries.get(); // Sort parameters alphabetically, if needed. - if (sort_alphabetical) + if (!(style & KeepDeclarationOrder)) { sorted_entries = *entries; current_entries = &sorted_entries; @@ -1765,7 +1767,7 @@ ParameterHandler::log_parameters_section(LogStream &out, { out.push(demangle(p.first)); enter_subsection(demangle(p.first)); - log_parameters_section(out, sort_alphabetical); + log_parameters_section(out, style); leave_subsection(); out.pop(); } diff --git a/tests/parameter_handler/parameter_handler_3_with_sorting_01.cc b/tests/parameter_handler/parameter_handler_3_with_sorting_01.cc index d025bb0140..a198a90a92 100644 --- a/tests/parameter_handler/parameter_handler_3_with_sorting_01.cc +++ b/tests/parameter_handler/parameter_handler_3_with_sorting_01.cc @@ -43,8 +43,8 @@ main() // read and then write parameters prm.parse_input(SOURCE_DIR "/prm/parameter_handler_3.prm"); prm.print_parameters(deallog.get_file_stream(), - ParameterHandler::Text, - false); + ParameterHandler::Text | + ParameterHandler::KeepDeclarationOrder); } catch (std::exception &exc) { diff --git a/tests/parameter_handler/parameter_handler_subsection_exists.cc b/tests/parameter_handler/parameter_handler_subsection_exists.cc index 4b3ddc1183..e959c4b7a0 100644 --- a/tests/parameter_handler/parameter_handler_subsection_exists.cc +++ b/tests/parameter_handler/parameter_handler_subsection_exists.cc @@ -57,8 +57,8 @@ main() prm.leave_subsection(); prm.print_parameters(deallog.get_file_stream(), - ParameterHandler::Text, - false); + ParameterHandler::Text | + ParameterHandler::KeepDeclarationOrder); deallog << std::boolalpha; deallog << "Subsection \"Section 3\" of root exists: " diff --git a/tests/parameter_handler/parameter_handler_write_json.cc b/tests/parameter_handler/parameter_handler_write_json.cc index 50505f010a..f1818f663c 100644 --- a/tests/parameter_handler/parameter_handler_write_json.cc +++ b/tests/parameter_handler/parameter_handler_write_json.cc @@ -59,12 +59,11 @@ main() prm.leave_subsection(); - prm.print_parameters(deallog.get_file_stream(), ParameterHandler::JSON, true); + prm.print_parameters(deallog.get_file_stream(), ParameterHandler::JSON); deallog.get_file_stream() << std::endl; prm.print_parameters(deallog.get_file_stream(), - ParameterHandler::ShortJSON, - true); + ParameterHandler::JSON | ParameterHandler::Short); deallog.get_file_stream() << std::endl; diff --git a/tests/parameter_handler/parameter_handler_write_xml.cc b/tests/parameter_handler/parameter_handler_write_xml.cc index af37cfe7e7..e0145d7e6c 100644 --- a/tests/parameter_handler/parameter_handler_write_xml.cc +++ b/tests/parameter_handler/parameter_handler_write_xml.cc @@ -59,12 +59,11 @@ main() prm.leave_subsection(); - prm.print_parameters(deallog.get_file_stream(), ParameterHandler::XML, true); + prm.print_parameters(deallog.get_file_stream(), ParameterHandler::XML); deallog.get_file_stream() << std::endl; prm.print_parameters(deallog.get_file_stream(), - ParameterHandler::ShortXML, - true); + ParameterHandler::XML | ParameterHandler::Short); deallog.get_file_stream() << std::endl; return 0; -- 2.39.5