welcome edje_external_inspector.
authorbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 25 Nov 2010 23:16:56 +0000 (23:16 +0000)
committerbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 25 Nov 2010 23:16:56 +0000 (23:16 +0000)
this tool is similar to edje_inspector as it uses similar command line
and output formats, but instead of acting upon EDJ compiled files, it
will use edje EXTERNAL module providers (/usr/lib/edje/modules/*),
being able to list modules and their registered types.

it is quite useful to know which parameters are exposed, their types
and default value (--detail=terse) and also mode information such as
flags, min/max/step/accepted/denied and other valuable information
(--detail=all).

as usual it accepts globs to filter input. example usage:

{{{
shell$ edje_external_inspector -t '*anch*'
module {
   name: "elm";
   friendly_name: "Elementary";
   types {
      type {
         name: "elm/anchorblock";
         params {
            string: "style" "default";
            string: "text" "some text";
         }
      }
      type {
         name: "elm/anchorview";
         params {
            string: "style" "default";
            string: "text" "some text";
         }
      }
   }
}

shell$ edje_external_inspector --type='*anch*'
module {
   name: "elm";
   friendly_name: "Elementary";
   types {
      type {
         name: "elm/anchorblock";
         params {
            string: "style" "default";
            string: "text" "some text";
         }
      }
      type {
         name: "elm/anchorview";
         params {
            string: "style" "default";
            string: "text" "some text";
         }
      }
   }
}

shell$ edje_external_inspector --detail=all 'emo*'
module {
   name: "emotion";
   friendly_name: "Emotion";
   types {
      type {
         name: "emotion";
         label: "Emotion";
         params {
            choice: "engine" "xine"; /* flags: REGULAR, choices: "xine" "gstreamer" */
            string: "file"; /* flags: REGULAR */
            bool: "play" "0"; /* flags: REGULAR, false_str: "false", true_str: "true" */
            double: "position" "0"; /* flags: REGULAR */
            bool: "smooth_scale" "0"; /* flags: REGULAR, false_str: "false", true_str: "true" */
            double: "audio_volume" "0.9"; /* flags: REGULAR */
            bool: "audio_mute" "0"; /* flags: REGULAR, false_str: "false", true_str: "true" */
            int: "audio_channel" "0"; /* flags: REGULAR */
            bool: "video_mute" "0"; /* flags: REGULAR, false_str: "false", true_str: "true" */
            int: "video_channel" "0"; /* flags: REGULAR */
            bool: "spu_mute" "0"; /* flags: REGULAR, false_str: "false", true_str: "true" */
            int: "spu_channel" "0"; /* flags: REGULAR */
            int: "chapter" "0"; /* flags: REGULAR */
            double: "play_speed" "1"; /* flags: REGULAR */
            double: "play_length" "0"; /* flags: REGULAR */
         }
      }
   }
}
}}}

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/edje@54999 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

configure.ac
src/bin/Makefile.am
src/bin/edje_external_inspector.c [new file with mode: 0644]
src/lib/edje_external.c

index 42ee764..0230fc9 100644 (file)
@@ -96,6 +96,7 @@ EFL_ENABLE_BIN([edje-recc])
 EFL_ENABLE_BIN([edje-player])
 EFL_ENABLE_BIN([edje-convert])
 EFL_ENABLE_BIN([edje-inspector])
+EFL_ENABLE_BIN([edje-external-inspector])
 
 # Optional EDJE_PROGRAM_CACHE (use much more ram, but increase speed in some cases)
 want_edje_program_cache="no"
@@ -380,15 +381,17 @@ echo "  Ecore IMF............: $have_ecore_imf"
 echo "  EDJE_PROGRAM_CACHE...: $want_edje_program_cache"
 echo "  EDJE_CALC_CACHE......: $want_edje_calc_cache"
 echo "  Fixed point..........: $want_fixed_point"
+echo "  Documentation........: ${build_doc}"
 echo
-echo "  Build edje_cc........: $have_edje_cc"
-echo "  Build edje_decc......: $have_edje_decc"
-echo "  Build edje_recc......: $have_edje_recc"
-echo "  Build edje_player....: $have_edje_player"
-echo "  Build edje_convert...: $have_edje_convert"
-echo "  Build edje_inspector.: $have_edje_inspector"
+echo "Programs:"
 echo
-echo "  Documentation........: ${build_doc}"
+echo "  Build edje_cc................: $have_edje_cc"
+echo "  Build edje_decc..............: $have_edje_decc"
+echo "  Build edje_recc..............: $have_edje_recc"
+echo "  Build edje_player............: $have_edje_player"
+echo "  Build edje_convert...........: $have_edje_convert"
+echo "  Build edje_inspector.........: $have_edje_inspector"
+echo "  Build edje_external_inspector: $have_edje_external_inspector"
 echo
 echo "Compilation............: make (or gmake)"
 echo "  CPPFLAGS.............: $CPPFLAGS"
index 8795242..2d29210 100644 (file)
@@ -15,9 +15,9 @@ AM_CPPFLAGS = \
 
 bin_SCRIPTS = @EDJE_RECC_PRG@
 
-bin_PROGRAMS = @EDJE_CC_PRG@ @EDJE_DECC_PRG@ @EDJE_PLAYER_PRG@ @EDJE_CONVERT_PRG@ @EDJE_INSPECTOR_PRG@
+bin_PROGRAMS = @EDJE_CC_PRG@ @EDJE_DECC_PRG@ @EDJE_PLAYER_PRG@ @EDJE_CONVERT_PRG@ @EDJE_INSPECTOR_PRG@ @EDJE_EXTERNAL_INSPECTOR_PRG@
 
-EXTRA_PROGRAMS = edje_cc edje_decc edje_player edje_convert edje_inspector
+EXTRA_PROGRAMS = edje_cc edje_decc edje_player edje_convert edje_inspector edje_external_inspector
 
 edje_cc_SOURCES = \
 edje_cc.c \
@@ -53,6 +53,10 @@ edje_inspector_SOURCES = edje_inspector.c
 edje_inspector_LDADD = $(top_builddir)/src/lib/libedje.la $(EVIL_LIBS) $(ECORE_EVAS_LIBS) $(EVIL_LIBS)
 edje_inspector_LDFLAGS = @lt_enable_auto_import@
 
+edje_external_inspector_SOURCES = edje_external_inspector.c
+edje_external_inspector_LDADD = $(top_builddir)/src/lib/libedje.la $(EVIL_LIBS) $(ECORE_EVAS_LIBS) $(EVIL_LIBS)
+edje_external_inspector_LDFLAGS = @lt_enable_auto_import@
+
 
 EXTRA_DIST = @EDJE_RECC_PRG@ edje_prefix.h edje_cc.h edje_convert.h
 EXTRA_SCRIPTS = edje_recc
diff --git a/src/bin/edje_external_inspector.c b/src/bin/edje_external_inspector.c
new file mode 100644 (file)
index 0000000..2670df7
--- /dev/null
@@ -0,0 +1,627 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "Edje.h"
+
+#include <Ecore.h>
+#include <Ecore_Getopt.h>
+#include <locale.h>
+#include <fnmatch.h>
+
+static int _log_dom;
+#define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
+#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
+#define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
+#define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
+#define CRIT(...) EINA_LOG_DOM_CRIT(_log_dom, __VA_ARGS__)
+
+#define INDENT "   "
+#define INDENT2 INDENT INDENT
+#define INDENT3 INDENT2 INDENT
+#define INDENT4 INDENT3 INDENT
+
+static char *module_patterns_str = NULL;
+
+static int detail = 1;
+static Eina_Bool machine = EINA_FALSE;
+static char *type_glob = NULL;
+static char * const *module_patterns;
+static const Eina_List *modules;
+
+
+static char *
+_module_patterns_str_new(void)
+{
+   Eina_Strbuf *buf;
+   char * const *itr;
+   char *ret;
+   if (!module_patterns) return strdup("*");
+
+   buf = eina_strbuf_new();
+   for (itr = module_patterns; *itr != NULL; itr++)
+     {
+        eina_strbuf_append(buf, *itr);
+        if (itr[1]) eina_strbuf_append(buf, ", ");
+     }
+   ret = eina_strbuf_string_steal(buf);
+   eina_strbuf_free(buf);
+   return ret;
+}
+
+static Eina_Bool
+module_matches(const char *name)
+{
+   char * const *itr;
+   if (!module_patterns) return EINA_TRUE;
+
+   for (itr = module_patterns; *itr != NULL; itr++)
+     if (fnmatch(*itr, name, 0) == 0) return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+static inline Eina_Bool
+type_matches(const char *name)
+{
+   if (!type_glob) return EINA_TRUE;
+   return fnmatch(type_glob, name, 0) == 0;
+}
+
+static int
+_types_sort(const void *pa, const void *pb)
+{
+   const Eina_Hash_Tuple *ha = pa, *hb = pb;
+   const Edje_External_Type *ta = ha->data, *tb = hb->data;
+   const char *na = ha->key, *nb = hb->key;
+   int r;
+
+   if (!ta->module) return -1;
+   if (!tb->module) return 1;
+   r = strcmp(ta->module, tb->module);
+   if (r != 0) return r;
+
+   if (!na) return -1;
+   if (!nb) return 1;
+   return strcmp(na, nb);
+}
+
+static const char *
+_param_type_str_get(const Edje_External_Param_Info *param)
+{
+   switch (param->type)
+     {
+      case EDJE_EXTERNAL_PARAM_TYPE_INT: return "int";
+      case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE: return "double";
+      case EDJE_EXTERNAL_PARAM_TYPE_STRING: return "string";
+      case EDJE_EXTERNAL_PARAM_TYPE_BOOL: return "bool";
+      case EDJE_EXTERNAL_PARAM_TYPE_CHOICE: return "choice";
+      default:
+         ERR("Unknown parameter type %d", param->type);
+         return "???";
+     }
+}
+
+static const char *
+_param_value_str_get(const Edje_External_Type *type, const Edje_External_Param_Info *param, char *buf, size_t buflen)
+{
+   switch (param->type)
+     {
+      case EDJE_EXTERNAL_PARAM_TYPE_INT:
+         if (param->info.i.def == EDJE_EXTERNAL_INT_UNSET) return NULL;
+         snprintf(buf, buflen, "%d", param->info.i.def);
+         return buf;
+
+      case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
+         if (param->info.d.def == EDJE_EXTERNAL_DOUBLE_UNSET) return NULL;
+         snprintf(buf, buflen, "%g", param->info.d.def);
+         return buf;
+
+      case EDJE_EXTERNAL_PARAM_TYPE_STRING:
+         return param->info.s.def;
+
+      case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
+         if (param->info.b.def == 0) return "0";
+         else if (param->info.b.def == 1) return "1";
+         return NULL;
+
+      case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
+        {
+           char *def;
+           if (param->info.c.def) return param->info.c.def;
+           if (!param->info.c.def_get) return NULL;
+           def = param->info.c.def_get(type->data, param);
+           if (!def) return NULL;
+           eina_strlcpy(buf, def, buflen);
+           free(def);
+           return buf;
+        }
+
+      default:
+         ERR("Unknown parameter type %d", param->type);
+         return NULL;
+     }
+}
+
+static const char *
+_param_flags_str_get(const Edje_External_Param_Info *param)
+{
+   static char buf[] = "GET|SET|STATE|CONSTRUCTOR";
+
+   if (param->flags == EDJE_EXTERNAL_PARAM_FLAGS_NONE) return "NONE";
+   if (param->flags == EDJE_EXTERNAL_PARAM_FLAGS_REGULAR) return "REGULAR";
+
+   buf[0] = '\0';
+
+   if (param->flags & EDJE_EXTERNAL_PARAM_FLAGS_GET)
+     strcat(buf, "GET");
+
+   if (param->flags & EDJE_EXTERNAL_PARAM_FLAGS_SET)
+     {
+        if (buf[0] != '\0') strcat(buf, "|");
+        strcat(buf, "SET");
+     }
+
+   if (param->flags & EDJE_EXTERNAL_PARAM_FLAGS_STATE)
+     {
+        if (buf[0] != '\0') strcat(buf, "|");
+        strcat(buf, "STATE");
+     }
+
+   if (param->flags & EDJE_EXTERNAL_PARAM_FLAGS_CONSTRUCTOR)
+     {
+        if (buf[0] != '\0') strcat(buf, "|");
+        strcat(buf, "CONSTRUCTOR");
+     }
+
+   return buf;
+}
+
+static void
+_param_choices_print(const char * const *choices)
+{
+   fputs(", choices:", stdout);
+   for (; *choices != NULL; choices++)
+     printf(" \"%s\"", *choices);
+}
+
+static void
+_param_extra_details(const Edje_External_Type *type, const Edje_External_Param_Info *param)
+{
+   const char *str = _param_flags_str_get(param);
+   if (machine) printf("FLAGS: %s\n", str);
+   else printf(" /* flags: %s", str);
+
+   switch (param->type)
+     {
+      case EDJE_EXTERNAL_PARAM_TYPE_INT:
+         if (param->info.i.min != EDJE_EXTERNAL_INT_UNSET)
+           printf(", min: %d", param->info.i.min);
+         if (param->info.i.max != EDJE_EXTERNAL_INT_UNSET)
+           printf(", max: %d", param->info.i.max);
+         if (param->info.i.step != EDJE_EXTERNAL_INT_UNSET)
+           printf(", step: %d", param->info.i.step);
+         break;
+
+      case EDJE_EXTERNAL_PARAM_TYPE_DOUBLE:
+         if (param->info.d.min != EDJE_EXTERNAL_DOUBLE_UNSET)
+           printf(", min: %g", param->info.d.min);
+         if (param->info.d.max != EDJE_EXTERNAL_DOUBLE_UNSET)
+           printf(", max: %g", param->info.d.max);
+         if (param->info.d.step != EDJE_EXTERNAL_DOUBLE_UNSET)
+           printf(", step: %g", param->info.d.step);
+         break;
+
+      case EDJE_EXTERNAL_PARAM_TYPE_STRING:
+         if (param->info.s.accept_fmt)
+           printf(", accept_fmt: \"%s\"", param->info.s.accept_fmt);
+         if (param->info.s.deny_fmt)
+           printf(", deny_fmt: \"%s\"", param->info.s.deny_fmt);
+         break;
+
+      case EDJE_EXTERNAL_PARAM_TYPE_BOOL:
+         if (param->info.b.false_str)
+           printf(", false_str: \"%s\"", param->info.b.false_str);
+         if (param->info.b.true_str)
+           printf(", true_str: \"%s\"", param->info.b.true_str);
+         break;
+
+      case EDJE_EXTERNAL_PARAM_TYPE_CHOICE:
+        {
+           if (param->info.c.choices)
+             _param_choices_print(param->info.c.choices);
+           else if (param->info.c.query)
+             {
+                char **choices = param->info.c.query(type->data, param);
+                if (choices)
+                  {
+                     char **itr;
+                     _param_choices_print((const char * const*)choices);
+                     for (itr = choices; *itr; itr++) free(*itr);
+                     free(choices);
+                  }
+             }
+        }
+        break;
+
+      default:
+         ERR("Unknown parameter type %d", param->type);
+     }
+
+   if (!machine) fputs(" */", stdout); /* \n not desired */
+}
+
+static int
+_info_list(void)
+{
+   Eina_Iterator *itr;
+   Eina_List *types;
+   const Eina_Hash_Tuple *tuple;
+   const Eina_List *l;
+   const char *name, *last_module;
+   Eina_Bool module_found = EINA_FALSE, type_found = EINA_FALSE;
+   Eina_Bool in_module = EINA_FALSE;
+
+   EINA_LIST_FOREACH(modules, l, name)
+     {
+        if (!module_matches(name))
+          {
+             DBG("filter out module '%s': does not match '%s'",
+                 name, module_patterns_str);
+             continue;
+          }
+
+        if (!edje_module_load(name))
+          {
+             ERR("error loading external '%s'", name);
+             continue;
+          }
+
+        module_found = EINA_TRUE;
+     }
+
+   itr = edje_external_iterator_get();
+   types = NULL;
+   EINA_ITERATOR_FOREACH(itr, tuple)
+     {
+        const Edje_External_Type *type = tuple->data;
+        name = tuple->key;
+
+        if (!type)
+          {
+             ERR("no type value for '%s'", name);
+             continue;
+          }
+        else if (type->abi_version != edje_external_type_abi_version_get())
+          {
+             ERR("type '%s' with incorrect abi_version %u (expected %u)",
+                 name, type->abi_version, edje_external_type_abi_version_get());
+             continue;
+          }
+
+        if (!type_matches(name))
+          {
+             DBG("filter out type '%s': does not match '%s'", name, type_glob);
+             continue;
+          }
+
+        types = eina_list_append(types, tuple);
+        type_found = EINA_TRUE;
+     }
+   eina_iterator_free(itr);
+
+   last_module = NULL;
+   types = eina_list_sort(types, 0, _types_sort);
+   EINA_LIST_FREE(types, tuple)
+     {
+        Eina_Bool changed_module = EINA_FALSE;
+        const Edje_External_Type *type = tuple->data;
+        const Edje_External_Param_Info *param;
+        name = tuple->key;
+
+        if ((last_module) && (type->module))
+          {
+             changed_module = ((last_module != type->module) &&
+                               (!strcmp(last_module, type->module)));
+          }
+        else if ((!last_module) && (type->module))
+          changed_module = EINA_TRUE;
+
+        if (changed_module)
+          {
+             if (in_module)
+               {
+                  if (machine) puts("TYPES-END\nMODULE-END");
+                  else puts(INDENT "}\n}");
+               }
+
+             if (machine)
+               printf("MODULE-BEGIN\n"
+                      "NAME: %s\n"
+                      "FRIENDLY-NAME: %s\n"
+                      "TYPES-BEGIN\n",
+                      type->module, type->module_name);
+             else
+               printf("module {\n"
+                      INDENT "name: \"%s\";\n"
+                      INDENT "friendly_name: \"%s\";\n"
+                      INDENT "types {\n",
+                      type->module, type->module_name);
+
+             in_module = EINA_TRUE;
+          }
+
+        if (machine) printf("TYPE-BEGIN\nNAME: %s\n", name);
+        else printf(INDENT2 "type {\n" INDENT3 "name: \"%s\";\n", name);
+
+        if (detail > 1)
+          {
+             const char *str;
+
+             if (!type->label_get) str = NULL;
+             else str = type->label_get(type->data);
+             if (machine) printf("LABEL: %s\n", str ? str : "");
+             else if (str) printf(INDENT3 "label: \"%s\";\n", str);
+
+             if (!type->description_get) str = NULL;
+             else str = type->description_get(type->data);
+             if (machine) printf("DESCRIPTION: %s\n", str ? str : "");
+             else if (str) printf(INDENT3 "description: \"%s\";\n", str);
+          }
+
+        if (machine) puts("PARAMS-BEGIN");
+        else puts(INDENT3 "params {");
+
+        for (param = type->parameters_info; param->name != NULL; param++)
+          {
+             const char *pt = _param_type_str_get(param);
+             char buf[128];
+
+             if (machine)
+               printf("PARAM-BEGIN\nNAME: %s\nTYPE: %s\n", param->name, pt);
+             else printf(INDENT4 "%s: \"%s\"", pt, param->name);
+
+             if (detail > 0)
+               {
+                  const char *str = _param_value_str_get
+                    (type, param, buf, sizeof(buf));
+                  if (machine) printf("DEFAULT: %s\n", str ? str : "");
+                  else if (str) printf(" \"%s\"", str);
+
+                  if (detail > 1)
+                    {
+                       if (!machine) putchar(';');
+                       _param_extra_details(type, param);
+                    }
+               }
+
+             if (machine) puts("PARAM-END");
+             else if (detail > 1) putchar('\n');
+             else puts(";");
+          }
+
+        if (machine) puts("PARAMS-END\nTYPE-END");
+        else puts(INDENT3 "}\n" INDENT2 "}");
+
+        last_module = type->module;
+     }
+
+   if (in_module)
+     {
+        if (machine) puts("MODULE-END");
+        else puts(INDENT "}\n}");
+     }
+
+   if (!module_found) WRN("no modules match '%s'", module_patterns_str);
+   if (!type_found) WRN("no types match '%s'", type_glob);
+   return (!module_found) || (!type_found);
+}
+
+static int
+_types_names_list(void)
+{
+   Eina_Iterator *itr;
+   Eina_List *types;
+   const Eina_Hash_Tuple *tuple;
+   const Eina_List *l;
+   const char *name;
+   Eina_Bool module_found = EINA_FALSE, type_found = EINA_FALSE;
+
+   EINA_LIST_FOREACH(modules, l, name)
+     {
+        if (!module_matches(name))
+          {
+             DBG("filter out module '%s': does not match '%s'",
+                 name, module_patterns_str);
+             continue;
+          }
+
+        if (!edje_module_load(name))
+          {
+             ERR("error loading external '%s'", name);
+             continue;
+          }
+
+        module_found = EINA_TRUE;
+     }
+
+   itr = edje_external_iterator_get();
+   types = NULL;
+   EINA_ITERATOR_FOREACH(itr, tuple)
+     {
+        const Edje_External_Type *type = tuple->data;
+        name = tuple->key;
+
+        if (!type)
+          {
+             ERR("no type value for '%s'", name);
+             continue;
+          }
+        else if (type->abi_version != edje_external_type_abi_version_get())
+          {
+             ERR("type '%s' with incorrect abi_version %u (expected %u)",
+                 name, type->abi_version, edje_external_type_abi_version_get());
+             continue;
+          }
+
+        if (!type_matches(name))
+          {
+             DBG("filter out type '%s': does not match '%s'", name, type_glob);
+             continue;
+          }
+
+        types = eina_list_append(types, tuple);
+        type_found = EINA_TRUE;
+     }
+   eina_iterator_free(itr);
+
+   types = eina_list_sort(types, 0, _types_sort);
+   EINA_LIST_FREE(types, tuple)
+     puts(tuple->key);
+
+   if (!module_found) WRN("no modules match '%s'", module_patterns_str);
+   if (!type_found) WRN("no types match '%s'", type_glob);
+   return (!module_found) || (!type_found);
+}
+
+static int
+_modules_names_list(void)
+{
+   const Eina_List *l;
+   const char *name;
+   Eina_Bool found = EINA_FALSE;
+
+   EINA_LIST_FOREACH(modules, l, name)
+     {
+        if (!module_matches(name))
+          {
+             DBG("filter out module '%s': does not match '%s'",
+                 name, module_patterns_str);
+             continue;
+          }
+        found = EINA_TRUE;
+        puts(name);
+     }
+
+   if (!found) WRN("no modules match '%s'", module_patterns_str);
+   return !found;
+}
+
+static const char *mode_choices[] = {
+  "info",
+  "modules-names",
+  "types-names",
+  NULL,
+};
+
+static const char *detail_choices[] = {
+  "none",
+  "terse",
+  "all",
+  NULL
+};
+
+const Ecore_Getopt optdesc = {
+  "edje_external_inspector",
+  "%prog [options] [module|module-glob] ... [module|module-glob]",
+  PACKAGE_VERSION,
+  "(C) 2010 - The Enlightenment Project",
+  "BSD",
+  "Edje external module inspector.",
+  0,
+  {
+    ECORE_GETOPT_CHOICE('m', "mode", "Choose which mode to operate.",
+                        mode_choices),
+    ECORE_GETOPT_STORE_STR('t', "type", "Limit output to type (or glob)."),
+    ECORE_GETOPT_CHOICE('d', "detail", "Choose detail level (default=terse)",
+                        detail_choices),
+    ECORE_GETOPT_STORE_TRUE('M', "machine", "Produce machine readable output."),
+    ECORE_GETOPT_LICENSE('L', "license"),
+    ECORE_GETOPT_COPYRIGHT('C', "copyright"),
+    ECORE_GETOPT_VERSION('V', "version"),
+    ECORE_GETOPT_HELP('h', "help"),
+    ECORE_GETOPT_SENTINEL
+  }
+};
+
+int
+main(int argc, char **argv)
+{
+   Eina_Bool quit_option = EINA_FALSE;
+   char *mode = NULL;
+   char *detail_name = NULL;
+   int arg_index;
+   int ret = 0;
+   Ecore_Getopt_Value values[] = {
+     ECORE_GETOPT_VALUE_STR(mode),
+     ECORE_GETOPT_VALUE_STR(type_glob),
+     ECORE_GETOPT_VALUE_STR(detail_name),
+     ECORE_GETOPT_VALUE_BOOL(machine),
+     ECORE_GETOPT_VALUE_BOOL(quit_option),
+     ECORE_GETOPT_VALUE_BOOL(quit_option),
+     ECORE_GETOPT_VALUE_BOOL(quit_option),
+     ECORE_GETOPT_VALUE_BOOL(quit_option),
+     ECORE_GETOPT_VALUE_NONE
+   };
+
+   setlocale(LC_NUMERIC, "C");
+
+   ecore_init();
+   eina_init();
+   edje_init();
+
+   _log_dom = eina_log_domain_register
+     ("edje_external_inspector", EINA_COLOR_YELLOW);
+   if (_log_dom < 0)
+     {
+        EINA_LOG_CRIT
+          ("could not register log domain 'edje_external_inspector'");
+        ret = 1;
+        goto error_log;
+     }
+
+   arg_index = ecore_getopt_parse(&optdesc, values, argc, argv);
+   if (arg_index < 0)
+     {
+        ERR("could not parse arguments.");
+        ret = 1;
+        goto error_getopt;
+     }
+   else if (quit_option) goto error_getopt;
+
+   if (!mode) mode = (char *)mode_choices[0];
+
+   if (detail_name)
+     {
+        if (!strcmp(detail_name, "none")) detail = 0;
+        else if (!strcmp(detail_name, "terse")) detail = 1;
+        else if (!strcmp(detail_name, "all")) detail = 2;
+        else ERR("Unknown detail level: '%s'", detail_name);
+     }
+
+   if (arg_index < argc) module_patterns = argv + arg_index;
+   else                  module_patterns = NULL;
+
+   modules = edje_available_modules_get();
+   module_patterns_str = _module_patterns_str_new();
+
+   if (!strcmp(mode, "info")) ret = _info_list();
+   else if (!strcmp(mode, "modules-names")) ret = _modules_names_list();
+   else if (!strcmp(mode, "types-names")) ret = _types_names_list();
+   else
+     {
+        ERR("Unknown mode: %s", mode);
+        ret = 1;
+     }
+
+   free(module_patterns_str);
+
+ error_getopt:
+   eina_log_domain_unregister(_log_dom);
+ error_log:
+   edje_shutdown();
+   ecore_shutdown();
+   eina_shutdown();
+
+   return ret;
+}
index c4bd80d..5963f37 100644 (file)
@@ -393,6 +393,46 @@ edje_external_type_abi_version_get(void)
    return EDJE_EXTERNAL_TYPE_ABI_VERSION;
 }
 
+/**
+ * Returns an iterator that emits Eina_Hash_Tuple pointers with key
+ * being the name and data being the Edje_External_Type pointer.
+ *
+ * @code
+ * const Eina_Hash_Tuple *tuple;
+ * Eina_Iterator *itr;
+ * const Eina_List *l, *modules;
+ * const char *s;
+ *
+ * modules = edje_available_modules_get();
+ * EINA_LIST_FOREACH(modules, l, s)
+ *   {
+ *      if (!edje_module_load(s))
+ *        printf("Error loading edje module: %s\n", s);
+ *   }
+ *
+ * itr = edje_external_iterator_get();
+ * EINA_ITERATOR_FOREACH(itr, tuple)
+ *   {
+ *      const char *name = tuple->key;
+ *      const Edje_External_Type *type = tuple->data;
+ *
+ *      if ((!type) ||
+ *          (type->abi_version != edje_external_type_abi_version_get()))
+ *        {
+ *           printf("Error: invalid type %p (abi: %d, expected: %d)\n",
+ *                   type, type ? type->abi_version : 0,
+ *                   edje_external_type_abi_version_get());
+ *           continue;
+ *        }
+ *
+ *      printf("%s: %s (%s) label='%s' desc='%s'\n",
+ *             name, type->module, type->module_name,
+ *             type->label_get ? type->label_get(type->data) : "",
+ *             type->description_get ? type->description_get(type->data) : "");
+ *   }
+ *
+ * @endcode
+ */
 EAPI Eina_Iterator *
 edje_external_iterator_get(void)
 {