Add G_OPTION_FLAG_NO_ARG and G_OPTION_FLAG_FILENAME to allow greater
authorMatthias Clasen <mclasen@redhat.com>
Sat, 18 Jun 2005 04:55:26 +0000 (04:55 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Sat, 18 Jun 2005 04:55:26 +0000 (04:55 +0000)
2005-06-18  Matthias Clasen  <mclasen@redhat.com>

* glib/goption.h:
* glib/goption.c: Add G_OPTION_FLAG_NO_ARG and
G_OPTION_FLAG_FILENAME to allow greater control of
G_OPTION_ARG_CALLBACK options. (#302632, Dan Winship)

* tests/option-test.c: test callback args

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-8
docs/reference/ChangeLog
docs/reference/glib/tmpl/option.sgml
glib/goption.c
glib/goption.h
tests/option-test.c

index 47afe36..cd102ae 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2005-06-18  Matthias Clasen  <mclasen@redhat.com>
+
+       * glib/goption.h: 
+       * glib/goption.c: Add G_OPTION_FLAG_NO_ARG and
+       G_OPTION_FLAG_FILENAME to allow greater control of
+       G_OPTION_ARG_CALLBACK options. (#302632, Dan Winship)
+
+       * tests/option-test.c: test callback args
+
 2005-06-14  Theppitak Karoonboonyanan  <thep@linux.thai.net>
 
        * configure.in: Added 'th' (Thai) to ALL_LINGUAS.
index 47afe36..cd102ae 100644 (file)
@@ -1,3 +1,12 @@
+2005-06-18  Matthias Clasen  <mclasen@redhat.com>
+
+       * glib/goption.h: 
+       * glib/goption.c: Add G_OPTION_FLAG_NO_ARG and
+       G_OPTION_FLAG_FILENAME to allow greater control of
+       G_OPTION_ARG_CALLBACK options. (#302632, Dan Winship)
+
+       * tests/option-test.c: test callback args
+
 2005-06-14  Theppitak Karoonboonyanan  <thep@linux.thai.net>
 
        * configure.in: Added 'th' (Thai) to ALL_LINGUAS.
index 47afe36..cd102ae 100644 (file)
@@ -1,3 +1,12 @@
+2005-06-18  Matthias Clasen  <mclasen@redhat.com>
+
+       * glib/goption.h: 
+       * glib/goption.c: Add G_OPTION_FLAG_NO_ARG and
+       G_OPTION_FLAG_FILENAME to allow greater control of
+       G_OPTION_ARG_CALLBACK options. (#302632, Dan Winship)
+
+       * tests/option-test.c: test callback args
+
 2005-06-14  Theppitak Karoonboonyanan  <thep@linux.thai.net>
 
        * configure.in: Added 'th' (Thai) to ALL_LINGUAS.
index 47afe36..cd102ae 100644 (file)
@@ -1,3 +1,12 @@
+2005-06-18  Matthias Clasen  <mclasen@redhat.com>
+
+       * glib/goption.h: 
+       * glib/goption.c: Add G_OPTION_FLAG_NO_ARG and
+       G_OPTION_FLAG_FILENAME to allow greater control of
+       G_OPTION_ARG_CALLBACK options. (#302632, Dan Winship)
+
+       * tests/option-test.c: test callback args
+
 2005-06-14  Theppitak Karoonboonyanan  <thep@linux.thai.net>
 
        * configure.in: Added 'th' (Thai) to ALL_LINGUAS.
index 9e7d06d..9b13ec6 100644 (file)
@@ -1,3 +1,8 @@
+2005-06-18  Matthias Clasen  <mclasen@redhat.com>
+
+       * glib/tmpl/option.sgml (GOptionFlags): document
+       G_OPTION_FLAG_NO_ARG and G_OPTION_FLAG_FILENAME  (Dan Winship)
+
 2005-06-16  Mathieu Lacage <mathieu@gnome.org>
 
        * gobject/tut_gtype.xml: fix typo reported by Hong Gang XU.
index 3aa2c1b..d0f6acd 100644 (file)
@@ -124,9 +124,6 @@ main (int argc, char *argv[])
 
 </para>
 
-<!-- ##### SECTION Stability_Level ##### -->
-
-
 <!-- ##### ENUM GOptionError ##### -->
 <para>
 Error codes returned by option parsing.
@@ -267,8 +264,14 @@ Flags which modify individual options.
    output.
 @G_OPTION_FLAG_IN_MAIN: The option appears in the main section of the
    <option>--help</option> output, even if it is defined in a group.
-@G_OPTION_FLAG_REVERSE: For options of the G_OPTION_ARG_NONE kind, this flag
+@G_OPTION_FLAG_REVERSE: For options of the %G_OPTION_ARG_NONE kind, this flag
    indicates that the sense of the option is reversed.
+@G_OPTION_FLAG_NO_ARG: For options of the %G_OPTION_ARG_CALLBACK kind,
+   this flag indicates that the callback does not take any argument
+   (like a %G_OPTION_ARG_NONE option). Since 2.8
+@G_OPTION_FLAG_FILENAME: For options of the %G_OPTION_ARG_CALLBACK
+   kind, this flag indicates that the argument should be passed to the
+   callback in the GLib filename encoding rather than UTF-8. Since 2.8
 
 <!-- ##### MACRO G_OPTION_REMAINING ##### -->
 <para>
index 4f2d2b6..78a66c7 100644 (file)
 
 #define TRANSLATE(group, str) (((group)->translate_func ? (* (group)->translate_func) ((str), (group)->translate_data) : (str)))
 
+#define NO_ARG(entry) ((entry)->arg == G_OPTION_ARG_NONE ||       \
+                       ((entry)->arg == G_OPTION_ARG_CALLBACK &&  \
+                        ((entry)->flags & G_OPTION_FLAG_NO_ARG)))
+
 typedef struct 
 {
   GOptionArg arg_type;
@@ -393,7 +397,7 @@ calculate_max_length (GOptionGroup *group)
       if (entry->short_name)
        len += 4;
       
-      if (entry->arg != G_OPTION_ARG_NONE && entry->arg_description)
+      if (!NO_ARG (entry) && entry->arg_description)
        len += 1 + g_utf8_strlen (TRANSLATE (group, entry->arg_description), -1);
       
       max_length = MAX (max_length, len);
@@ -847,17 +851,28 @@ parse_arg (GOptionContext *context,
       }
     case G_OPTION_ARG_CALLBACK:
       {
-       gchar *tmp;
+       gchar *data;
        gboolean retval;
        
-       tmp = g_locale_to_utf8 (value, -1, NULL, NULL, error);
+       if (entry->flags & G_OPTION_FLAG_NO_ARG)
+         data = NULL;
+       else if (entry->flags & G_OPTION_FLAG_FILENAME)
+         {
+#ifdef G_OS_WIN32
+           data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
+#else
+           data = g_strdup (value);
+#endif
+         }
+       else
+         data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
 
-       if (!value)
+       if (!(entry->flags & G_OPTION_FLAG_NO_ARG) && !data)
          return FALSE;
 
-       retval = (* (GOptionArgFunc) entry->arg_data) (option_name, tmp, group->user_data, error);
+       retval = (* (GOptionArgFunc) entry->arg_data) (option_name, data, group->user_data, error);
        
-       g_free (tmp);
+       g_free (data);
        
        return retval;
        
@@ -887,7 +902,7 @@ parse_short_option (GOptionContext *context,
     {
       if (arg == group->entries[j].short_name)
        {
-         if (group->entries[j].arg == G_OPTION_ARG_NONE)
+         if (NO_ARG (&group->entries[j]))
            {
              parse_arg (context, group, &group->entries[j],
                         NULL, NULL, error);
@@ -954,7 +969,7 @@ parse_long_option (GOptionContext *context,
       if (*index >= *argc)
        return TRUE;
 
-      if (group->entries[j].arg == G_OPTION_ARG_NONE &&
+      if (NO_ARG (&group->entries[j]) &&
          strcmp (arg, group->entries[j].long_name) == 0)
        {
          parse_arg (context, group, &group->entries[j],
index 285bf01..dcd36e4 100644 (file)
@@ -34,7 +34,9 @@ typedef enum
 {
   G_OPTION_FLAG_HIDDEN       = 1 << 0,
   G_OPTION_FLAG_IN_MAIN      = 1 << 1,
-  G_OPTION_FLAG_REVERSE             = 1 << 2
+  G_OPTION_FLAG_REVERSE      = 1 << 2,
+  G_OPTION_FLAG_NO_ARG       = 1 << 3,
+  G_OPTION_FLAG_FILENAME     = 1 << 4
 } GOptionFlags;
 
 typedef enum
index 3c4035f..ffd1761 100644 (file)
@@ -9,6 +9,9 @@ int arg_test1_int;
 gchar *arg_test2_string;
 gchar *arg_test3_filename;
 
+gchar *callback_test1_string;
+gboolean callback_test2_int;
+
 gchar **array_test1_array;
 
 gboolean ignore_test1_boolean;
@@ -324,6 +327,78 @@ arg_test3 (void)
   g_option_context_free (context);
 }
 
+static gboolean
+callback_parse1 (const gchar *option_name, const gchar *value,
+                gpointer data, GError **error)
+{
+       callback_test1_string = g_strdup (value);
+       return TRUE;
+}
+
+void
+callback_test1 (void)
+{
+  GOptionContext *context;
+  gboolean retval;
+  GError *error = NULL;
+  gchar **argv;
+  int argc;
+  GOptionEntry entries [] =
+    { { "test", 0, 0, G_OPTION_ARG_CALLBACK, callback_parse1, NULL, NULL },
+      { NULL } };
+  
+  context = g_option_context_new (NULL);
+  g_option_context_add_main_entries (context, entries, NULL);
+
+  /* Now try parsing */
+  argv = split_string ("program --test foo.txt", &argc);
+  
+  retval = g_option_context_parse (context, &argc, &argv, &error);
+  g_assert (retval);
+
+  g_assert (strcmp (callback_test1_string, "foo.txt") == 0);
+
+  g_free (callback_test1_string);
+  
+  g_strfreev (argv);
+  g_option_context_free (context);
+}
+
+static gboolean
+callback_parse2 (const gchar *option_name, const gchar *value,
+                gpointer data, GError **error)
+{
+       callback_test2_int++;
+       return TRUE;
+}
+
+void
+callback_test2 (void)
+{
+  GOptionContext *context;
+  gboolean retval;
+  GError *error = NULL;
+  gchar **argv;
+  int argc;
+  GOptionEntry entries [] =
+    { { "test", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, callback_parse2, NULL, NULL },
+      { NULL } };
+  
+  context = g_option_context_new (NULL);
+  g_option_context_add_main_entries (context, entries, NULL);
+
+  /* Now try parsing */
+  argv = split_string ("program --test --test", &argc);
+  
+  retval = g_option_context_parse (context, &argc, &argv, &error);
+  g_assert (retval);
+
+  g_assert (callback_test2_int == 2);
+  
+  g_strfreev (argv);
+  g_option_context_free (context);
+}
+
 void
 ignore_test1 (void)
 {
@@ -937,6 +1012,10 @@ main (int argc, char **argv)
   /* Test string arrays */
   array_test1 ();
 
+  /* Test callback args */
+  callback_test1 ();
+  callback_test2 ();
+
   /* Test ignoring options */
   ignore_test1 ();
   ignore_test2 ();