]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Extend OutputStyle 9919/head
authorPeter Munch <peterrmuench@gmail.com>
Fri, 17 Apr 2020 19:49:43 +0000 (21:49 +0200)
committerPeter Munch <peterrmuench@gmail.com>
Wed, 22 Apr 2020 21:30:01 +0000 (23:30 +0200)
include/deal.II/base/parameter_handler.h
source/base/parameter_handler.cc
tests/parameter_handler/parameter_handler_3_with_sorting_01.cc
tests/parameter_handler/parameter_handler_subsection_exists.cc
tests/parameter_handler/parameter_handler_write_json.cc
tests/parameter_handler/parameter_handler_write_xml.cc

index a9eb31d0af466a5ebc303b05a9a564f4ec460d22..aece61a6b78891f7f8485b4758e7aa5ea5480e06 100644 (file)
@@ -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 <a
-     * href="http://en.wikipedia.org/wiki/XML">XML</a> file.
+     * href="http://en.wikipedia.org/wiki/XML">XML</a> 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 <a
-     * href="http://en.wikipedia.org/wiki/JSON">JSON</a> file.
+     * href="http://en.wikipedia.org/wiki/JSON">JSON</a> 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 <tt>false</tt>: 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 <tt>KeepDeclarationOrder</tt>: in this case entries are printed in the
+   * same order as they have been declared.
    *
-   * In the case of <tt>XML</tt> or <tt>JSON</tt>, a reduced tree, only
-   * containing the values and skipping the documentation, can be
-   * printed by setting @p print_documentation to <tt>false</tt>.
-   *
-   * In <tt>Text</tt> format, the output is formatted in such a way that it is
+   * In <tt>PRM</tt>, <tt>XML</tt>, and <tt>JSON</tt> 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 <tt>Short</tt> in combination with <tt>PRM</tt>,
+   * <tt>XML</tt>, or <tt>JSON</tt> (or by using the shortcuts
+   * <tt>ShortPRM</tt>, <tt>ShortXML</tt>, or <tt>ShortJSON</tt>), a reduced
+   * output can be generated, only containing the values and skipping the
+   * documentation.
+   *
    * In <tt>XML</tt> format, the output starts with one root element
    * <tt>ParameterHandler</tt> 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 <tt>KeepDeclarationOrder</tt>: 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 <tt>KeepDeclarationOrder</tt>: 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 <tt>operator |</tt> 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<ParameterHandler::OutputStyle>(
+    static_cast<unsigned int>(f1) | static_cast<unsigned int>(f2));
+}
 
 /**
  * The class MultipleParameterLoop offers an easy possibility to test several
index 4fc7deca58ef5b1189f52e9a53a3fe7bb268271f..0b94d0e4e1b1bec6b5661e40b27a69b678523be0 100644 (file)
@@ -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 &current_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<std::string>("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<std::string>("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<std::string>("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<std::string>("documentation").empty())
               {
-                const std::string value = p.second.get<std::string>("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<std::string>("documentation").empty())
-                  {
-                    if (first_entry == false)
-                      out << '\n';
-                    else
-                      first_entry = false;
-
-                    const std::vector<std::string> doc_lines =
-                      Utilities::break_text_into_lines(
-                        p.second.get<std::string>("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<std::string> doc_lines =
+                  Utilities::break_text_into_lines(
+                    p.second.get<std::string>("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<std::string>("default_value"))
-                  {
-                    out << std::setw(longest_value - value.length() + 1) << ' '
-                        << "# ";
-                    out << "default: "
-                        << p.second.get<std::string>("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<std::string>("default_value"))
+              {
+                out << std::setw(longest_value - value.length() + 1) << ' '
+                    << "# ";
+                out << "default: "
+                    << p.second.get<std::string>("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<std::string>("value");
+                const std::string value = p.second.get<std::string>("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<std::string>("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<std::string>("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<std::string>("documentation").empty())
+                    out << "{\\it Description:} "
+                        << p.second.get<std::string>("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<std::string>("documentation").empty())
-                      out << "{\\it Description:} "
-                          << p.second.get<std::string>("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<unsigned int>("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<std::string>("alias");
+                // also output possible values, do not escape because the
+                // description internally will use LaTeX formatting
+                const unsigned int pattern_index =
+                  p.second.get<unsigned int>("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<std::string>("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<std::string>("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<std::string>("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<unsigned int>("pattern");
+            const std::string full_desc_str =
+              patterns[pattern_index]->description(Patterns::PatternBase::Text);
+            const std::vector<std::string> 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<unsigned int>("pattern");
-                const std::string full_desc_str =
-                  patterns[pattern_index]->description(
-                    Patterns::PatternBase::Text);
-                const std::vector<std::string> 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<std::string>("documentation").length() != 0)
-                  out << std::setw(overall_indent_level * 2 + longest_name + 10)
-                      << ""
-                      << "(" << p.second.get<std::string>("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<std::string>("documentation").length() != 0)
+              out << std::setw(overall_indent_level * 2 + longest_name + 10)
+                  << ""
+                  << "(" << p.second.get<std::string>("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();
       }
index d025bb01406c1dabfd9a39d695d0020a91d8b270..a198a90a923f076d829b2eb3f5007cb7117cce7a 100644 (file)
@@ -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)
     {
index 4b3ddc1183a2499e4cfc404faa4aca2801064a33..e959c4b7a00cc0cea1373f525b849996419925f4 100644 (file)
@@ -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: "
index 50505f010a34968d4f45c593170378e878920bea..f1818f663c8a7f5050186b5a8754f05b0ed41861 100644 (file)
@@ -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;
 
 
index af37cfe7e71b492f3ad60709a9e7a2c978ba5dfc..e0145d7e6c2d78025fd4bca351ea8d0791173ddc 100644 (file)
@@ -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;

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.