changeset 24060:9158b9c65676

Overhaul and document libgui parser class. * libgui/src/qtinfo/parser[.cc,.h]: Overhaul and documented the class interface to reduce the coupling with webinfo.cc. Rename is_ref --> is_reference and find_ref --> find_reference, and node_text_to_html --> node_as_html for clarity. Removed unused search_node(const QString& node, QIODevice *io). `node_as_html` now obtains the node text itself, reduces the interface burden. Refactored the hard to get `anchor` logic. `find_reference` now avoids many unnessary iterators. `is_reference` now really only checks for being a reference, moved position calculation to `node_as_html` where needed uniquely. `search_node` now avoids return before closing the info file properly. * libgui/src/qtinfo/webinfo.cc(load_node,load_ref): Decouple from Texinfo parser by using parser's new interface methods.
author Kai T. Ohlhus <k.ohlhus@gmail.com>
date Wed, 20 Sep 2017 16:53:13 +0200
parents d8e2fffb371c
children a1801e80bb11
files libgui/src/qtinfo/parser.cc libgui/src/qtinfo/parser.h libgui/src/qtinfo/webinfo.cc
diffstat 3 files changed, 125 insertions(+), 154 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/qtinfo/parser.cc	Tue Sep 19 22:01:09 2017 -0700
+++ b/libgui/src/qtinfo/parser.cc	Wed Sep 20 16:53:13 2017 +0200
@@ -132,70 +132,58 @@
   return iodevice;
 }
 
-int
-parser::is_ref (const QString& node)
+QString
+parser::find_reference (const QString& ref_name)
 {
-  if (_ref_map.contains (node))
-    {
-      node_position ref = _ref_map [node];
+  QString xref_name = "XREF" + ref_name;
+  xref_name.remove (' ');  // Delete spaces as XREF uses no whitespace
 
-      return ref.pos-_node_map [ref._node_name].pos;
+  if (_ref_map.contains (xref_name))
+    return xref_name;
+  else if (_node_map.contains ("The " + ref_name + " Statement"))
+    {
+      // See, for example "The while Statement" which has no XREF.
+      return "The " + ref_name + " Statement";
     }
-  if (_node_map.contains (node))
-    return 0;  // node: show from the beginning
+  else
+    return "Top";
+}
 
-  return -1;
+bool
+parser::is_reference (const QString& ref)
+{
+  return _ref_map.contains (ref);
 }
 
 QString
 parser::search_node (const QString& node_arg)
 {
   QString node = node_arg;
-
-  QFileInfo file_info;
-  QString ref;
+  QString text = "";
 
-  if (_ref_map.contains (node))
-    {
-      ref = node;
-      node = _ref_map [ref]._node_name;
-    }
+  // If node_arg was a reference, translate to node.
+  if (_ref_map.contains (node_arg))
+    node = _ref_map [node_arg]._node_name;
 
   if (_node_map.contains (node))
     {
-      int pos = _node_map [node].pos;
-      int realPos;
+      QFileInfo file_info;
+      int real_pos;
+      real_position (_node_map [node].pos, file_info, real_pos);
 
-      real_position (pos, file_info, realPos);
-
-      QIODevice *io = open_file (file_info);
+      QIODevice* io = open_file (file_info);
       if (! io)
-        return QString ();
-
-      seek (io, realPos);
+        return text;
 
-      QString text = get_next_node (io);
-      if (! text.isEmpty ())
-        return text;
+      seek (io, real_pos);
+
+      text = get_next_node (io);
 
       io->close ();
       delete io;
     }
 
-  return QString ();
-}
-
-QString
-parser::search_node (const QString& node, QIODevice *io)
-{
-  while (! io->atEnd ())
-    {
-      QString text = get_next_node (io);
-      if (node == get_node_name (text))
-        return text;
-    }
-
-  return QString ();
+  return text;
 }
 
 void
@@ -386,23 +374,25 @@
 }
 
 QString
-parser::node_text_to_html (const QString& text_arg, int anchorPos,
-                           const QString& anchor)
+parser::node_as_html (const QString& node, const QString& anchor)
 {
-  QString text = text_arg;
+  QString text = search_node (node);
 
   QString nodeName = get_node_name (text);
   QString nodeUp   = get_node_up (text);
   QString nodeNext = get_node_next (text);
   QString nodePrev = get_node_prev (text);
 
-  if (anchorPos > -1)
+  // Insert anchor, if node is a XREF-reference
+  if (is_reference (node))
     {
-      QString text1 = text.left (anchorPos);
-      QString text2 = text.mid (anchorPos);
+      node_position ref = _ref_map[node];
+      int anchor_pos = ref.pos - _node_map[ref._node_name].pos;
 
-      int n = text1.indexOf ("\n");
-      text1.remove (0, n);
+      QString text1 = text.left (anchor_pos);
+      QString text2 = text.mid (anchor_pos);
+
+      text1.remove (0, text1.indexOf ("\n"));
 
       info_to_html (text1);
       info_to_html (text2);
@@ -413,8 +403,7 @@
     }
   else
     {
-      int n = text.indexOf ("\n");
-      text.remove (0, n);
+      text.remove (0, text.indexOf ("\n"));
       info_to_html (text);
     }
 
@@ -434,7 +423,6 @@
   text.append ("</body></html>\n");
 
   return text;
-
 }
 
 void
@@ -518,7 +506,7 @@
 }
 
 void
-parser::real_position (int pos, QFileInfo & file_info, int & real_pos)
+parser::real_position (int pos, QFileInfo& file_info, int& real_pos)
 {
   int header = -1;
   int sum = 0;
@@ -554,7 +542,7 @@
 }
 
 QString
-parser::global_search (const QString& text, int max_founds)
+parser::global_search (const QString& text, int max_results)
 {
   QString results;
   QStringList words = text.split (" ", QString::SkipEmptyParts);
@@ -585,8 +573,7 @@
           if (node.isEmpty ())
             continue;
 
-          int n = node_text.indexOf ("\n");
-          node_text.remove (0, n);
+          node_text.remove (0, node_text.indexOf ("\n"));
 
           int pos = 0;
           int founds = 0;
@@ -601,7 +588,7 @@
           founds = 0;
 
           while ((pos = re.indexIn (node_text, pos)) != -1
-                 && founds < max_founds)
+                 && founds < max_results)
             {
               if (founds == 0)
                 {
@@ -643,42 +630,3 @@
   results.append ("</body></html>");
   return results;
 }
-
-QString
-parser::find_ref (const QString& ref_name)
-{
-  QString ref_nm = ref_name;
-  ref_nm.remove (' ');  // Delete spaces as XREF uses no whitespace
-  QString text = "";
-
-  QHash<QString, node_position>::iterator it;
-  for (it = _ref_map.begin (); it != _ref_map.end (); ++it)
-    {
-      QString k = it.key ();
-      node_position p = it.value ();
-
-      if (k == "XREF" + ref_nm)
-        {
-          // found ref, so return its name
-          text = "XREF" + ref_nm;
-          break;
-        }
-    }
-
-  if (text.isEmpty ())  // try the statement-nodes
-    {
-      QHash<QString, node_map_item>::iterator itn;
-      for (itn = _node_map.begin (); itn != _node_map.end (); ++itn)
-        {
-          QString k = itn.key ();
-          if (k == "The " + ref_name + " Statement")
-            {
-              // found ref, so return its name
-              text = k;
-              break;
-            }
-        }
-    }
-
-  return text;
-}
--- a/libgui/src/qtinfo/parser.h	Tue Sep 19 22:01:09 2017 -0700
+++ b/libgui/src/qtinfo/parser.h	Wed Sep 20 16:53:13 2017 +0200
@@ -34,20 +34,18 @@
 
 /**
  * @class parser
- * This class gets nodes and searchs inside of 'info files'.
- * <p>Each info file has nodes. Every node has the documentation.
- * Info files contains a map with position of each node.</p>
- * <p>What is position?
- * There is a simple answer:
- * If you make a queue with info files, position will be the number of bytes
- * from begining to node position.</p>
- * <p>
+ * This class processes Texinfo `*.info`-files and their contained nodes
+ * for searching and translation to HTML.
+ *
+ * Texinfo files are structured by nodes and contain a map with the
+ * `position` of each node.  The nodes themselves hold the actual
+ * documentation.
+ *
+ * If you make a queue with info files, `position` will be the number of
+ * bytes from begining to a node position.
+ *
  * But is not so easy. There is headers, and qtinfo must not take these
  * headers into account.
- * </p>
- * <p>
- * This class also translates info files to html.
- * </p>
  */
 class parser
   : public QObject
@@ -55,24 +53,54 @@
   Q_OBJECT
 
 public:
-  parser (QObject *parent = nullptr);
-  bool set_info_path (const QString& _info_path);
+  /**
+   * Ctor.
+   */
+  parser (QObject* parent = nullptr);
+
+  /**
+   * Sets the path of the Texinfo files to \p info_path.
+   *
+   * \returns true, if successful, otherwise false.
+   */
+  bool set_info_path (const QString& info_path);
+
+  /**
+   * Returns the path of the Texinfo files.
+   */
   QString get_info_path ();
+
+  /**
+   * Search for the text of \p node.
+   */
   QString search_node (const QString& node);
-  QString global_search (const QString& text, int maxFounds);
-
-  QString find_ref (const QString& name);
 
-  /** Checks if this node is reference. If node is reference, it will be
-   *  returned its position in text, else it will be returned -1.
-    */
-  int is_ref (const QString& node);
+  /**
+   * Search for string \p text with \p max_results search results.
+   */
+  QString global_search (const QString& text, int max_results);
+
+  /**
+   * Find reference \p ref.
+   *
+   * \returns A valid XREF-reference, if \p ref exists.
+   *          Otherwise node "Top" is returned.
+   */
+  QString find_reference (const QString& ref);
 
-  /** Translates text of node to Html. If anchorPos is not -1, then anchor is
-   *  inserted in that position.
-    */
-  QString node_text_to_html (const QString& text, int anchorPos = -1,
-                             const QString& anchor = QString ());
+  /**
+   * Checks if \p ref is a XREF-reference.
+   */
+  bool is_reference (const QString& ref);
+
+  /**
+   * Get a HTML representation of \p node.
+   * \param anchor name of the anchor `<a name="anchor">`, if \p node is
+   *        a XREF-reference.
+   * \returns HTML string.
+   */
+  QString node_as_html (const QString& node,
+                        const QString& anchor = QString ());
 
 private:
   struct node_position
@@ -92,28 +120,37 @@
     int real_size;
   };
 
-  QString search_node (const QString& node, QIODevice *io);
-  QString get_next_node (QIODevice *io);
+  QString get_next_node (QIODevice* io);
   QString get_node_name (const QString& text);
   QString get_node_up (const QString& text);
   QString get_node_next (const QString& text);
   QString get_node_prev (const QString& text);
-  void append_line (QString *test, const char *line);
 
-  /** Parses info files and gets map of node positions.*/
+  /**
+   * Append \p line to \text.
+   */
+  void append_line (QString *text, const char *line);
+
+  /**
+   * Parse `*.info` file and generate map of nodes and their positions.
+   */
   void parse_info_map ();
 
-  /** Open info files and uncompress them. */
-  QIODevice * open_file (QFileInfo & fileInfo);
+  /**
+   * Open compressed `*.info` file \p fileInfo.
+   */
+  QIODevice* open_file (QFileInfo& fileInfo);
 
   /** Calculates real position of nodes.
-    * @param pos position from info file.
-    * @param fileInfo returns file what contains that position.
-    * @param realPos returns real position inside of fileInfo.
-    */
-  void real_position (int pos, QFileInfo & file_info, int & real_pos);
+   * \param pos position from info file.
+   * \param file_info returns file that contains \p pos.
+   * \param real_pos returns real position inside \p file_info.
+   */
+  void real_position (int pos, QFileInfo& file_info, int& real_pos);
 
-  /** Seeks to position pos. */
+  /**
+   * Seeks in \p io to position \p pos.
+   */
   void seek (QIODevice *io, int pos);
 
   QString                       _info_path;
--- a/libgui/src/qtinfo/webinfo.cc	Tue Sep 19 22:01:09 2017 -0700
+++ b/libgui/src/qtinfo/webinfo.cc	Wed Sep 20 16:53:13 2017 +0200
@@ -196,15 +196,11 @@
         }
     }
 
-  QString text = _parser.search_node (node_name);
-  int i = _parser.is_ref (node_name);
   _text_browser = addNewTab (tab_text);
-  _text_browser->setHtml (_parser.node_text_to_html (text, i - 1, "anchor"));
+  _text_browser->setHtml (_parser.node_as_html (node_name, "anchor"));
 
-  if (i != -1)
-    {
-      _text_browser->scrollToAnchor ("anchor");
-    }
+  if (_parser.is_reference (node_name))
+    _text_browser->scrollToAnchor ("anchor");
 }
 
 void
@@ -293,16 +289,8 @@
 void
 webinfo::load_ref (const QString& ref_name)
 {
-  QString text = _parser.find_ref (ref_name);
-  if (text.length () > 0)
-    {
-      load_node (text);
-    }
-  else
-    {
-      // not found
-      load_node ("Top");
-    }
+  // Will load "Top", if ref_name was not found.
+  load_node (_parser.find_reference (ref_name));
 
   if (_text_browser)
     _text_browser->setFocus ();
@@ -481,5 +469,3 @@
       QTabBar::mousePressEvent (me);
     }
 }
-
-