SF.net SVN: geany-plugins:[1310] trunk/geanygendoc/src

colombanw at users.sourceforge.net colombanw at xxxxx
Mon Apr 26 23:03:10 UTC 2010


Revision: 1310
          http://geany-plugins.svn.sourceforge.net/geany-plugins/?rev=1310&view=rev
Author:   colombanw
Date:     2010-04-26 23:03:10 +0000 (Mon, 26 Apr 2010)

Log Message:
-----------
GeanyGenDoc: Support automatic documentation of children

Allow a rule to request for automatic generation of its children
documentation. This is useful for fragmented documentation styles
such as Doxygen not to need to manually generate documentation for
each children of i.e. a structure.

Modified Paths:
--------------
    trunk/geanygendoc/src/ggd-doc-setting.c
    trunk/geanygendoc/src/ggd-doc-setting.h
    trunk/geanygendoc/src/ggd-file-type-loader.c
    trunk/geanygendoc/src/ggd-tag-utils.c
    trunk/geanygendoc/src/ggd-tag-utils.h
    trunk/geanygendoc/src/ggd.c

Modified: trunk/geanygendoc/src/ggd-doc-setting.c
===================================================================
--- trunk/geanygendoc/src/ggd-doc-setting.c	2010-04-25 21:16:59 UTC (rev 1309)
+++ trunk/geanygendoc/src/ggd-doc-setting.c	2010-04-26 23:03:10 UTC (rev 1310)
@@ -49,6 +49,7 @@
   setting->policy = GGD_POLICY_KEEP;
   setting->merge_children = FALSE;
   setting->matches = tm_tag_max_t;
+  setting->autodoc_children = FALSE;
   
   /*g_debug ("New setting matching '%s'", match);*/
   
@@ -107,13 +108,15 @@
   g_return_if_fail (setting != NULL);
   
   fprintf (stream, "  %s [%p]:\n"
-                   "    template: %p\n"
-                   "    position: %u\n"
-                   "      policy: %u\n",
+                   "          template: %p\n"
+                   "          position: %u\n"
+                   "            policy: %u\n"
+                   " auto-doc-children: %s\n",
                    setting->match, (gpointer)setting,
                    (gpointer)setting->template,
                    setting->position,
-                   setting->policy);
+                   setting->policy,
+                   setting->autodoc_children ? "True" : "False");
 }
 
 /**

Modified: trunk/geanygendoc/src/ggd-doc-setting.h
===================================================================
--- trunk/geanygendoc/src/ggd-doc-setting.h	2010-04-25 21:16:59 UTC (rev 1309)
+++ trunk/geanygendoc/src/ggd-doc-setting.h	2010-04-26 23:03:10 UTC (rev 1310)
@@ -70,6 +70,7 @@
   GgdPolicy   policy;
   gboolean    merge_children;
   TMTagType   matches;
+  gboolean    autodoc_children;
 };
 
 

Modified: trunk/geanygendoc/src/ggd-file-type-loader.c
===================================================================
--- trunk/geanygendoc/src/ggd-file-type-loader.c	2010-04-25 21:16:59 UTC (rev 1309)
+++ trunk/geanygendoc/src/ggd-file-type-loader.c	2010-04-26 23:03:10 UTC (rev 1310)
@@ -51,6 +51,7 @@
  * string               ::= ( """ .* """ | "'" .* "'" )
  * constant             ::= [_A-Z][_A-Z0-9]+
  * integer              ::= [0-9]+
+ * boolean              ::= ( "True" | "False" )
  * setting_value        ::= ( string | constant | integer )
  * setting              ::= "setting-name" "=" setting_value ";"
  * setting_list         ::= ( "{" setting* "}" | setting )
@@ -65,11 +66,12 @@
  *                            "typedef" | "union" | "variable" | "extern" |
  *                            "define" | "macro" | "file" )
  * matches              ::= type ( "|" type )*
- * doctype_subsetting   ::= ( "template" "=" string |
- *                            "position" "=" position |
- *                            "policy"   "=" policy |
- *                            "children" "=" children |
- *                            "matches"  "=" matches ) ";"
+ * doctype_subsetting   ::= ( "template"          "=" string |
+ *                            "position"          "=" position |
+ *                            "policy"            "=" policy |
+ *                            "children"          "=" children |
+ *                            "matches"           "=" matches |
+ *                            "auto_doc_children" "=" boolean ) ";"
  * match                ::= type ( "." type )*
  * doctype_setting      ::= ( match "=" "{" doctype_subsetting* "}" |
  *                            match "." doctype_subsetting )
@@ -97,6 +99,39 @@
   return q;
 }
 
+/* reads a boolean (True or False) */
+static gboolean
+ggd_file_type_read_boolean (GScanner *scanner,
+                            gboolean *value_)
+{
+  gboolean success = FALSE;
+  
+  if (g_scanner_get_next_token (scanner) != G_TOKEN_IDENTIFIER) {
+    g_scanner_unexp_token (scanner, G_TOKEN_IDENTIFIER,
+                           _("boolean value"), NULL, NULL, NULL, TRUE);
+  } else {
+    const gchar  *bool_str  = scanner->value.v_identifier;
+    gboolean      value     = FALSE;
+    
+    success = TRUE;
+    if (strcmp (bool_str, "TRUE") == 0 ||
+        strcmp (bool_str, "True") == 0) {
+      value = TRUE;
+    } else if (strcmp (bool_str, "FALSE") == 0 ||
+               strcmp (bool_str, "False") == 0) {
+      value = FALSE;
+    } else {
+      g_scanner_error (scanner, _("invalid boolean value \"%s\""), bool_str);
+      success = FALSE;
+    }
+    if (success && value_) {
+      *value_ = value;
+    }
+  }
+  
+  return success;
+}
+
 /* reads #GgdDocSetting:template */
 static gboolean
 ggd_file_type_read_setting_template (GScanner       *scanner,
@@ -239,6 +274,14 @@
   return success;
 }
 
+/* reads #GgdDocSetting:autodoc_children */
+static gboolean
+ggd_file_type_read_setting_auto_doc_children (GScanner       *scanner,
+                                              GgdDocSetting  *setting)
+{
+  return ggd_file_type_read_boolean (scanner, &setting->autodoc_children);
+}
+
 /* dispatches read of value of doctype subsetting @name */
 static gboolean
 ggd_file_type_read_setting_value (GScanner      *scanner,
@@ -251,11 +294,12 @@
     gboolean    (*handler)  (GScanner      *scanner,
                              GgdDocSetting *setting);
   } settings_table[] = {
-    { "template", ggd_file_type_read_setting_template },
-    { "position", ggd_file_type_read_setting_position },
-    { "policy",   ggd_file_type_read_setting_policy   },
-    { "children", ggd_file_type_read_setting_children },
-    { "matches",  ggd_file_type_read_setting_matches  }
+    { "template",           ggd_file_type_read_setting_template           },
+    { "position",           ggd_file_type_read_setting_position           },
+    { "policy",             ggd_file_type_read_setting_policy             },
+    { "children",           ggd_file_type_read_setting_children           },
+    { "matches",            ggd_file_type_read_setting_matches            },
+    { "auto_doc_children",  ggd_file_type_read_setting_auto_doc_children  }
   };
   gboolean  success = FALSE;
   gboolean  found   = FALSE;

Modified: trunk/geanygendoc/src/ggd-tag-utils.c
===================================================================
--- trunk/geanygendoc/src/ggd-tag-utils.c	2010-04-25 21:16:59 UTC (rev 1309)
+++ trunk/geanygendoc/src/ggd-tag-utils.c	2010-04-26 23:03:10 UTC (rev 1310)
@@ -96,6 +96,42 @@
 }
 
 /**
+ * ggd_tag_sort_by_line_to_list:
+ * @tags: A #GPtrArray of #TMTag<!-- -->s
+ * @direction: Sort direction: %GGD_SORT_ASC for an ascending sort or
+ *             %GGD_SORT_DESC for a descending sort.
+ * 
+ * Creates a sorted list of tags from a #GPtrArray of #TMTag<!-- -->s. The list
+ * is sorted by the tags' line position. The sort direction depend on
+ * @direction.
+ * 
+ * <note><para>The tags are not copied; you must then not free the array' items
+ * if you still want to use the returned list.</para></note>
+ * 
+ * Returns: A newly created list of tags that should be freed with
+ *          g_list_free().
+ */
+GList *
+ggd_tag_sort_by_line_to_list (const GPtrArray  *tags,
+                              gint              direction)
+{
+  GList  *children = NULL;
+  guint   i;
+  TMTag  *el;
+  
+  g_return_val_if_fail (tags != NULL, NULL);
+  g_return_val_if_fail (direction != 0, NULL);
+  
+  GGD_PTR_ARRAY_FOR (tags, i, el) {
+    children = g_list_insert_sorted_with_data (children, el,
+                                               tag_cmp_by_line,
+                                               GINT_TO_POINTER (direction));
+  }
+  
+  return children;
+}
+
+/**
  * ggd_tag_find_from_line:
  * @tags: A #GPtrArray of TMTag<!-- -->s
  * @line: Line for which find the tag
@@ -429,17 +465,19 @@
  * @tags: Array of tags that contains @parent
  * @parent: Tag for which get children
  * @depth: Maximum depth for children to be found (< 0 means infinite)
+ * @filter: A logical OR of the TMTagType<!-- -->s to match
  * 
- * Finds children tags of a #TMTag.
+ * Finds children tags of a #TMTag that matches @matches.
  * <note><para>The returned list of children is sorted in the order they appears
  * in the source file (by their lines positions)</para></note>
  * 
  * Returns: The list of children found for @parent
  */
 GList *
-ggd_tag_find_children (const GPtrArray *tags,
-                       const TMTag     *parent,
-                       gint             depth)
+ggd_tag_find_children_filtered (const GPtrArray *tags,
+                                const TMTag     *parent,
+                                gint             depth,
+                                TMTagType        filter)
 {
   GList  *children = NULL;
   guint   i;
@@ -455,7 +493,8 @@
     fake_scope = g_strdup (parent->name);
   }
   GGD_PTR_ARRAY_FOR (tags, i, el) {
-    if (scope_child_matches (fake_scope, el->atts.entry.scope, depth)) {
+    if (scope_child_matches (fake_scope, el->atts.entry.scope, depth) &&
+        el->type & filter) {
       children = g_list_insert_sorted_with_data (children, el,
                                                  tag_cmp_by_line,
                                                  GINT_TO_POINTER (GGD_SORT_ASC));
@@ -465,3 +504,23 @@
   
   return children;
 }
+
+/**
+ * ggd_tag_find_children:
+ * @tags: Array of tags that contains @parent
+ * @parent: Tag for which get children
+ * @depth: Maximum depth for children to be found (< 0 means infinite)
+ * 
+ * Finds children tags of a #TMTag.
+ * <note><para>The returned list of children is sorted in the order they appears
+ * in the source file (by their lines positions)</para></note>
+ * 
+ * Returns: The list of children found for @parent
+ */
+GList *
+ggd_tag_find_children (const GPtrArray *tags,
+                       const TMTag     *parent,
+                       gint             depth)
+{
+  return ggd_tag_find_children_filtered (tags, parent, depth, tm_tag_max_t);
+}

Modified: trunk/geanygendoc/src/ggd-tag-utils.h
===================================================================
--- trunk/geanygendoc/src/ggd-tag-utils.h	2010-04-25 21:16:59 UTC (rev 1309)
+++ trunk/geanygendoc/src/ggd-tag-utils.h	2010-04-26 23:03:10 UTC (rev 1310)
@@ -41,11 +41,17 @@
 
 void          ggd_tag_sort_by_line            (GPtrArray *tags,
                                                gint       direction);
+GList        *ggd_tag_sort_by_line_to_list    (const GPtrArray  *tags,
+                                               gint              direction);
 TMTag        *ggd_tag_find_from_line          (const GPtrArray *tags,
                                                gulong           line);
 TMTag        *ggd_tag_find_at_current_pos     (GeanyDocument *doc);
 TMTag        *ggd_tag_find_parent             (const GPtrArray *tags,
                                                const TMTag     *child);
+GList        *ggd_tag_find_children_filtered  (const GPtrArray *tags,
+                                               const TMTag     *parent,
+                                               gint             depth,
+                                               TMTagType        filter);
 GList        *ggd_tag_find_children           (const GPtrArray *tags,
                                                const TMTag     *parent,
                                                gint             depth);

Modified: trunk/geanygendoc/src/ggd.c
===================================================================
--- trunk/geanygendoc/src/ggd.c	2010-04-25 21:16:59 UTC (rev 1309)
+++ trunk/geanygendoc/src/ggd.c	2010-04-26 23:03:10 UTC (rev 1310)
@@ -371,10 +371,100 @@
   return setting;
 }
 
+/*
+ * get_config:
+ * @doc: A #GeanyDocument for which get the configuration
+ * @doc_type: A documentation type identifier
+ * @file_type_: Return location for the corresponding #GgdFileType, or %NULL
+ * @doc_type_: Return location for the corresponding #GgdDocType, or %NULL
+ * 
+ * Gets the configuration for a document and a documentation type.
+ * 
+ * Returns: %TRUE on success, %FALSE otherwise.
+ */
+static gboolean
+get_config (GeanyDocument  *doc,
+            const gchar    *doc_type,
+            GgdFileType   **file_type_,
+            GgdDocType    **doc_type_)
+{
+  gboolean      success = FALSE;
+  GgdFileType  *ft;
+  
+  ft = ggd_file_type_manager_get_file_type (doc->file_type->id);
+  if (ft) {
+    GgdDocType *doctype;
+    
+    doctype = ggd_file_type_get_doc (ft, doc_type);
+    if (! doctype) {
+      msgwin_status_add (_("No documentation type \"%s\" for language \"%s\""),
+                         doc_type, doc->file_type->name);
+    } else {
+      if (file_type_) *file_type_ = ft;
+      if (doc_type_) *doc_type_ = doctype;
+      success = TRUE;
+    }
+  }
+  
+  return success;
+}
+
+/*
+ * insert_multiple_comments:
+ * @doc: A #GeanyDocument in which insert comments
+ * @filetype: The #GgdFileType to use
+ * @doctype: The #GgdDocType to use
+ * @sorted_tag_list: A list of tag to document. This list must be sorted by
+ *                   tag's line.
+ * 
+ * Tries to insert the documentation for all tags listed in @sorted_tag_list,
+ * taking care of settings and duplications.
+ * 
+ * Returns: %TRUE on success, %FALSE otherwise.
+ */
+static gboolean
+insert_multiple_comments (GeanyDocument *doc,
+                          GgdFileType   *filetype,
+                          GgdDocType    *doctype,
+                          GList         *sorted_tag_list)
+{
+  gboolean          success = FALSE;
+  GList            *node;
+  GPtrArray        *tag_array;
+  ScintillaObject  *sci = doc->editor->sci;
+  GHashTable       *tag_done_table; /* keeps the list of documented tags.
+                                     * Useful since documenting a tag might
+                                     * actually document another one */
+  
+  success = TRUE;
+  tag_array = doc->tm_file->tags_array;
+  tag_done_table = g_hash_table_new (NULL, NULL);
+  sci_start_undo_action (sci);
+  for (node = sorted_tag_list; node; node = node->next) {
+    GgdDocSetting  *setting;
+    const TMTag    *tag = node->data;
+    
+    setting = get_setting_from_tag (doctype, tag_array, tag, &tag);
+    if (setting && ! g_hash_table_lookup (tag_done_table, tag)) {
+      if (! do_insert_comment (sci, tag_array, tag, filetype, setting)) {
+        success = FALSE;
+        break;
+      } else {
+        g_hash_table_insert (tag_done_table, (gpointer)tag, (gpointer)tag);
+      }
+    }
+  }
+  sci_end_undo_action (sci);
+  g_hash_table_destroy (tag_done_table);
+  
+  return success;
+}
+
 /**
  * ggd_insert_comment:
  * @doc: The document in which insert the comment
  * @line: SCI's line for which generate a comment. Usually the current line.
+ * @doc_type: Documentation type identifier
  * 
  * Tries to insert a comment in a #GeanyDocument.
  * 
@@ -390,34 +480,32 @@
                     const gchar    *doc_type)
 {
   gboolean          success = FALSE;
-  ScintillaObject  *sci;
   const TMTag      *tag;
   GPtrArray        *tag_array;
+  GgdFileType      *filetype;
+  GgdDocType       *doctype;
   
-  sci = doc->editor->sci;
+  g_return_val_if_fail (DOC_VALID (doc), FALSE);
+  
   tag_array = doc->tm_file->tags_array;
   tag = ggd_tag_find_from_line (tag_array, line + 1 /* it is a SCI line */);
   if (! tag || (tag->type & tm_tag_file_t)) {
     msgwin_status_add (_("No valid tag for line %d"), line);
   } else {
-    GgdFileType *ft;
-    
-    ft = ggd_file_type_manager_get_file_type (doc->file_type->id);
-    if (ft) {
-      GgdDocType *doctype;
+    if (get_config (doc, doc_type, &filetype, &doctype)) {
+      GgdDocSetting  *setting;
+      GList          *tag_list = NULL;
       
-      doctype = ggd_file_type_get_doc (ft, doc_type);
-      if (! doctype) {
-        msgwin_status_add (_("No documentation type \"%s\" for language \"%s\""),
-                           doc_type, doc->file_type->name);
-      } else {
-        GgdDocSetting *setting;
-        
-        setting = get_setting_from_tag (doctype, tag_array, tag, &tag);
-        if (setting) {
-          success = do_insert_comment (sci, tag_array, tag, ft, setting);
-        }
+      setting = get_setting_from_tag (doctype, tag_array, tag, &tag);
+      if (setting->autodoc_children) {
+        tag_list = ggd_tag_find_children_filtered (tag_array, tag, 0,
+                                                   setting->matches);
       }
+      /* we assume that a parent always comes before any children, then simply add
+       * it at the end */
+      tag_list = g_list_append (tag_list, (gpointer)tag);
+      success = insert_multiple_comments (doc, filetype, doctype, tag_list);
+      g_list_free (tag_list);
     }
   }
   
@@ -438,50 +526,21 @@
                          const gchar   *doc_type)
 {
   gboolean      success = FALSE;
-  GgdFileType  *ft;
+  GgdFileType  *filetype;
+  GgdDocType   *doctype;
   
   g_return_val_if_fail (DOC_VALID (doc), FALSE);
   
-  ft = ggd_file_type_manager_get_file_type (doc->file_type->id);
-  if (ft) {
-    GgdDocType *doctype;
+  if (get_config (doc, doc_type, &filetype, &doctype)) {
+    GList    *tag_list;
     
-    doctype = ggd_file_type_get_doc (ft, doc_type);
-    if (! doctype) {
-      msgwin_status_add (_("No documentation type \"%s\" for language \"%s\""),
-                         doc_type, doc->file_type->name);
-    } else {
-      GPtrArray        *tag_array;
-      ScintillaObject  *sci = doc->editor->sci;
-      const TMTag      *tag;
-      guint             i;
-      GHashTable       *tag_done_table; /* keeps the list of documented tags.
-                                         * Useful since documenting a tag might
-                                         * actually document another one */
-      
-      success = TRUE;
-      tag_array = doc->tm_file->tags_array;
-      tag_done_table = g_hash_table_new (NULL, NULL);
-      /* sort the tags to be sure to insert by the end of the document, then we
-       * don't modify the element's position of tags we'll work on */
-      ggd_tag_sort_by_line (tag_array, GGD_SORT_DESC);
-      sci_start_undo_action (sci);
-      GGD_PTR_ARRAY_FOR (tag_array, i, tag) {
-        GgdDocSetting  *setting;
-        
-        setting = get_setting_from_tag (doctype, tag_array, tag, &tag);
-        if (setting && ! g_hash_table_lookup (tag_done_table, tag)) {
-          if (! do_insert_comment (sci, tag_array, tag, ft, setting)) {
-            success = FALSE;
-            break;
-          } else {
-            g_hash_table_insert (tag_done_table, (gpointer)tag, (gpointer)tag);
-          }
-        }
-      }
-      sci_end_undo_action (sci);
-      g_hash_table_destroy (tag_done_table);
-    }
+    /* get a sorted list of tags to be sure to insert by the end of the
+     * document, then we don't modify the element's position of tags we'll work
+     * on */
+    tag_list = ggd_tag_sort_by_line_to_list (doc->tm_file->tags_array,
+                                             GGD_SORT_DESC);
+    success = insert_multiple_comments (doc, filetype, doctype, tag_list);
+    g_list_free (tag_list);
   }
   
   return success;


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Plugins-Commits mailing list