q66 pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=edc548fac5497c1bd8d7c35c2942f6686baa64c4

commit edc548fac5497c1bd8d7c35c2942f6686baa64c4
Author: Daniel Kolesa <quake...@gmail.com>
Date:   Mon Jan 20 17:10:21 2014 +0000

    ecore_getopt: support for per-category help listing
---
 src/lib/ecore/Ecore_Getopt.h |  11 ++--
 src/lib/ecore/ecore_getopt.c | 149 +++++++++++++++++++++++++++++++++++++------
 2 files changed, 137 insertions(+), 23 deletions(-)

diff --git a/src/lib/ecore/Ecore_Getopt.h b/src/lib/ecore/Ecore_Getopt.h
index d41ed3e..e4f5eb5 100644
--- a/src/lib/ecore/Ecore_Getopt.h
+++ b/src/lib/ecore/Ecore_Getopt.h
@@ -360,9 +360,9 @@ struct _Ecore_Getopt
                              ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES,            
                      \
                              NULL)
 
-#define ECORE_GETOPT_HELP(shortname, longname)      \
-  {shortname, longname, "show this message.", NULL, \
-   ECORE_GETOPT_ACTION_HELP,                        \
+#define ECORE_GETOPT_HELP(shortname, longname)            \
+  {shortname, longname, "show this message.", "CATEGORY", \
+   ECORE_GETOPT_ACTION_HELP,                              \
    {.dummy = NULL}}
 
 #define ECORE_GETOPT_VERSION(shortname, longname)      \
@@ -390,8 +390,8 @@ struct _Ecore_Getopt
    ECORE_GETOPT_ACTION_BREAK,                   \
    {.dummy = NULL}}
 
-#define ECORE_GETOPT_CATEGORY(name) \
-  {0, NULL, name, NULL, ECORE_GETOPT_ACTION_CATEGORY, {.dummy = NULL}}
+#define ECORE_GETOPT_CATEGORY(name, help) \
+  {0, name, help, NULL, ECORE_GETOPT_ACTION_CATEGORY, {.dummy = NULL}}
 
 #define ECORE_GETOPT_SENTINEL {0, NULL, NULL, NULL, 0, {.dummy = NULL}}
 
@@ -410,6 +410,7 @@ struct _Ecore_Getopt
 #define ECORE_GETOPT_VALUE_NONE {.ptrp = NULL}
 
 EAPI void       ecore_getopt_help(FILE *fp, const Ecore_Getopt *info);
+EAPI Eina_Bool  ecore_getopt_help_category(FILE *fp, const Ecore_Getopt *info, 
const char *category);
 EAPI Eina_Bool  ecore_getopt_parser_has_duplicates(const Ecore_Getopt *parser);
 EAPI int        ecore_getopt_parse(const Ecore_Getopt *parser, 
Ecore_Getopt_Value *values, int argc, char **argv);
 
diff --git a/src/lib/ecore/ecore_getopt.c b/src/lib/ecore/ecore_getopt.c
index b2195be..7a1505f 100644
--- a/src/lib/ecore/ecore_getopt.c
+++ b/src/lib/ecore/ecore_getopt.c
@@ -355,7 +355,7 @@ _ecore_getopt_desc_arg_requirement(const Ecore_Getopt_Desc 
*desc)
         return desc->action_param.callback.arg_req;
 
       case ECORE_GETOPT_ACTION_HELP:
-        return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
+        return ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL;
 
       case ECORE_GETOPT_ACTION_VERSION:
         return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
@@ -620,9 +620,55 @@ _ecore_getopt_help_desc_choices(FILE                    
*fp,
    return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
 }
 
+static int
+_ecore_getopt_help_desc_categories(FILE                    *fp,
+                                   const int                base,
+                                   const int                total,
+                                   int                      used,
+                                   const Ecore_Getopt_Desc *desc)
+{
+   const char sep[] = ", ";
+   const int seplen = sizeof(sep) - 1;
+   Eina_Bool cat_before = EINA_FALSE;
+
+   if (used > 0)
+     {
+        fputc('\n', fp);
+        used = 0;
+     }
+   for (; used < base; used++)
+     fputc(' ', fp);
+
+   /* do not print available categories if none available */
+   for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
+     if (desc->action == ECORE_GETOPT_ACTION_CATEGORY) goto hascat;
+
+   return _ecore_getopt_help_line(fp, base, total, used,
+                                  _("No categories available."),
+                                  strlen(_("No categories available.")));
+
+hascat:
+   used = _ecore_getopt_help_line
+       (fp, base, total, used, _("Categories: "), strlen(_("Categories: ")));
+
+   for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
+     {
+         if (desc->action != ECORE_GETOPT_ACTION_CATEGORY || !desc->longname)
+           continue;
+         if (cat_before)
+           used = _ecore_getopt_help_line(fp, base, total, used, sep, seplen);
+         used = _ecore_getopt_help_line
+             (fp, base, total, used, desc->longname, strlen(desc->longname));
+         cat_before = EINA_TRUE;
+     }
+
+   return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
+}
+
 static void
 _ecore_getopt_help_desc(FILE                    *fp,
-                        const Ecore_Getopt_Desc *desc)
+                        const Ecore_Getopt_Desc *desc,
+                        const Ecore_Getopt      *parser)
 {
    Ecore_Getopt_Desc_Arg_Requirement arg_req;
    char metavar[32] = "ARG";
@@ -699,6 +745,11 @@ _ecore_getopt_help_desc(FILE                    *fp,
         _ecore_getopt_help_desc_choices(fp, helpcol, cols, used, desc);
         break;
 
+      case ECORE_GETOPT_ACTION_HELP:
+        _ecore_getopt_help_desc_categories(fp, helpcol, cols, used,
+                                           parser->descs);
+        break;
+
       default:
         break;
      }
@@ -710,7 +761,8 @@ end:
 static Eina_Bool
 _ecore_getopt_desc_is_sentinel(const Ecore_Getopt_Desc *desc)
 {
-   return (desc->shortname == '\0') && (!desc->longname);
+   return (desc->shortname == '\0') && (!desc->longname)
+     && (desc->action != ECORE_GETOPT_ACTION_CATEGORY);
 }
 
 static void
@@ -722,7 +774,7 @@ _ecore_getopt_help_options(FILE               *fp,
    fputs(_("Options:\n"), fp);
 
    for (desc = parser->descs; !_ecore_getopt_desc_is_sentinel(desc); desc++)
-     _ecore_getopt_help_desc(fp, desc);
+     _ecore_getopt_help_desc(fp, desc, parser);
 
    fputc('\n', fp);
 
@@ -730,25 +782,18 @@ _ecore_getopt_help_options(FILE               *fp,
 
    fputs(_("Positional arguments:\n"), fp);
    for (; desc->metavar != NULL; desc++)
-     _ecore_getopt_help_desc(fp, desc);
+     _ecore_getopt_help_desc(fp, desc, parser);
 
    fputc('\n', fp);
 }
 
-/**
- * Show nicely formatted help message for the given parser.
- *
- * @param fp The file the message will be printed on.
- * @param parser The parser to be used.
- */
-EAPI void
-ecore_getopt_help(FILE               *fp,
-                  const Ecore_Getopt *parser)
+static Eina_Bool
+_ecore_getopt_help_prepare(const Ecore_Getopt *parser)
 {
    const char *var;
 
    EINA_MAIN_LOOP_CHECK_RETURN;
-   if (!parser) return;
+   if (!parser) return EINA_FALSE;
 
    if (_argc < 1)
      {
@@ -769,11 +814,75 @@ ecore_getopt_help(FILE               *fp,
         helpcol = cols / 3;
      }
 
+   return EINA_TRUE;
+}
+
+/**
+ * Show nicely formatted help message for the given parser.
+ *
+ * @param fp The file the message will be printed on.
+ * @param parser The parser to be used.
+ *
+ * @see ecore_getopt_help_category()
+ */
+EAPI void
+ecore_getopt_help(FILE               *fp,
+                  const Ecore_Getopt *parser)
+{
+   if (!_ecore_getopt_help_prepare(parser))
+     return;
+
    _ecore_getopt_help_usage(fp, parser);
    _ecore_getopt_help_description(fp, parser);
    _ecore_getopt_help_options(fp, parser);
 }
 
+/**
+ * Show help for a single category (along with program usage and description).
+ *
+ * @param fp The file the message will be printed on.
+ * @param parser The parser to be used.
+ * @param category The category to print.
+ *
+ * @return @c EINA_TRUE when the category exists, @c EINA_FALSE otherwise.
+ *
+ * @see ecore_getopt_help()
+ */
+EAPI Eina_Bool
+ecore_getopt_help_category(FILE               *fp,
+                           const Ecore_Getopt *parser,
+                           const char         *category)
+{
+   const Ecore_Getopt_Desc *desc;
+   Eina_Bool found = EINA_FALSE;
+
+   if (!category || !_ecore_getopt_help_prepare(parser)) return EINA_FALSE;
+   for (desc = parser->descs; !_ecore_getopt_desc_is_sentinel(desc); desc++)
+     {
+        if (desc->action != ECORE_GETOPT_ACTION_CATEGORY) continue;
+        if (!desc->longname || strcmp(desc->longname, category)) continue;
+        found = EINA_TRUE;
+        break;
+     }
+   if (!found)
+     {
+        fprintf(stderr, _("ERROR: unknown category '%s'.\n"), category);
+        return EINA_FALSE;
+     }
+
+   _ecore_getopt_help_usage(fp, parser);
+   _ecore_getopt_help_description(fp, parser);
+
+   fprintf(fp, "%s\n", (desc++)->help);
+   for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
+     {
+        if (desc->action == ECORE_GETOPT_ACTION_CATEGORY) break;
+        _ecore_getopt_help_desc(fp, desc, parser);
+     }
+
+   return EINA_TRUE;
+}
+
 static const Ecore_Getopt_Desc *
 _ecore_getopt_parse_find_long(const Ecore_Getopt *parser,
                               const char         *name)
@@ -787,7 +896,7 @@ _ecore_getopt_parse_find_long(const Ecore_Getopt *parser,
 
    for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
      {
-        if (!desc->longname)
+        if (!desc->longname || desc->action == ECORE_GETOPT_ACTION_CATEGORY)
           continue;
 
         if (p)
@@ -873,7 +982,7 @@ _ecore_getopt_parse_find_nonargs_base(const Ecore_Getopt 
*parser,
                goto found_nonarg;
           }
 
-                  
+
 
         if (desc->action == ECORE_GETOPT_ACTION_BREAK)
           abreak = 1;
@@ -1430,10 +1539,12 @@ static Eina_Bool
 _ecore_getopt_parse_help(const Ecore_Getopt      *parser,
                          const Ecore_Getopt_Desc *desc EINA_UNUSED,
                          Ecore_Getopt_Value      *val,
-                         const char              *arg_val EINA_UNUSED)
+                         const char              *arg_val)
 {
    if (val->boolp)
      (*val->boolp) = EINA_TRUE;
+   if (arg_val)
+     return ecore_getopt_help_category(stdout, parser, arg_val);
    ecore_getopt_help(stdout, parser);
    return EINA_TRUE;
 }
@@ -1862,6 +1973,8 @@ _ecore_getopt_parse_find_long_other(const Ecore_Getopt    
  *parser,
      {
         if (desc == orig)
           return NULL;
+        if (desc->action == ECORE_GETOPT_ACTION_CATEGORY)
+          continue;
 
         if (desc->longname && (strcmp(name, desc->longname) == 0))
           return desc;

-- 


Reply via email to