GTK+ / Gnome Application Development | |||
---|---|---|---|
<<< Previous | Home | Next >>> |
Gnome uses a powerful option-parsing library called popt. popt handles all the default Gnome options---to see the default options, pass the --help option to any Gnome application. You can add a "popt table" with your custom options. To do so, replace gnome_init() with the gnome_init_with_popt_table() variant (Figure 3).
#include <libgnomeui/gnome-init.h> |
int
gnome_init_with_popt_table
(const char* app_id, const char* app_version, int argc, char** argv, const struct poptOption*
options, int flags, poptContext* return_ctx);
Figure 3. Init with Argument Parsing
A popt table is simply an array of struct poptOption, defined as follows:
struct poptOption { const char* longName; char shortName; int argInfo; void* arg; int val; char* descrip; char* argDescrip; }; |
The first two components are the long and short names for the option; for example, "help" and 'h' would correspond to command-line options --help and -h. These can be NULL and '\0' respectively, if you want only one name for the option.
The arginfo member tells what kind of table entry this is. Here are the possible values:
POPT_ARG_NONE means the option is a simple switch, it takes no argument.
POPT_ARG_STRING means the option takes a string argument, as in --geometry="300x300+50+100".
POPT_ARG_INT means the option takes an int argument, as in --columns=10.
POPT_ARG_LONG means the option takes a long argument.
POPT_ARG_INCLUDE_TABLE means that this struct poptOption does not specify an option, but rather another popt table to be included.
POPT_ARG_CALLBACK means that this struct poptOption does not specify an option, but rather a callback function to be used for parsing options in this table. This kind of entry should be at the beginning of your table.
POPT_ARG_INTL_DOMAIN means that this struct poptOption specifies the translation domain for this table and any subtables.
The meaning of arg depends on the arginfo member. For options that take an argument, arg should point to a variable of the argument type. popt will fill the pointed-to variable with the argument. For POPT_ARG_NONE, *arg is set to TRUE if the option is found on the command line. In all cases, arg may be NULL, causing popt to ignore it.
For POPT_ARG_INCLUDE_TABLE, arg points to the table to include; for POPT_ARG_CALLBACK, it points to the callback to invoke; for POPT_ARG_INTL_DOMAIN it should be the translation domain string.
The val member serves as an identifier for each option. Typically it isn't that useful in Gnome applications, but if you use a callback it will be available in the callback. If you aren't going to use it, set it to 0.
The final two members are used to automatically generate output for the --help option. descrip describes an option; argDescrip describes the argument to that option, if applicable. For example, the help for the --display option looks like this:
--display=DISPLAY X display to use |
Here argDescrip is "DISPLAY" and descrip is "X display to use." Remember to mark these two strings for translation.
descrip has a slightly different meaning for POPT_ARG_INCLUDE_TABLE; in this case it titles a "group" of options in the help output. For example, "Help options" in the following output:
Help options -?, --help Show this help message --usage Display brief usage message |
If you place an entry of type POPT_ARG_CALLBACK at the beginning of a popt table, a user-defined callback will be invoked with information about each option found on the command line. Here is the type your callback is expected to have:
typedef void (*poptCallbackType)(poptContext con, enum poptCallbackReason reason, const struct poptOption* opt, const char* arg, void* data); |
The opaque poptContext object contains all of popt's state. This makes it possible to use popt more than once in the same program, or parse more than one set of options simultaneously. You can also extract information about the current parsing state from the poptContext, using functions provided by popt.
Possible poptCallbackReason values are:
POPT_CALLBACK_REASON_PRE
POPT_CALLBACK_REASON_POST
POPT_CALLBACK_REASON_OPTION
Your callback is called once for each option found on the command line with POPT_CALLBACK_REASON_OPTION as the reason argument. If you request, it can also be called before and after argument parsing. In these cases reason will be POPT_CALLBACK_REASON_PRE or POPT_CALLBACK_REASON_POST. To specify that you want your callback to be called before or after parsing, you have to combine a pair of flags with POPT_ARG_CALLBACK. For example, the following struct poptOption initializer specifies a callback to be invoked both before and after argument parsing:
{ NULL, '\0', POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST, &parse_an_arg_callback, 0, NULL} |
The opt argument to the callback is the struct poptOption corresponding to the most recently-seen command line option (you can access the val member of this struct to determine which option you are looking at). The arg argument is the text of any argument passed to the command line option; the data argument is the callback data, given as the descrip member of the struct poptOption which specified the callback.
The flags argument to gnome_init_with_popt_table() can basically be ignored in a Gnome context; the available flags are not very useful.
If you pass a non-NULL pointer for return_ctx, the final argument to gnome_init_with_popt_table(), the current context will be returned; you can use this to extract the non-option components of the command line, such as filenames. This is done with the function poptGetArgs()---here's an example:
char** args; poptContext ctx; int i; bindtextdomain (PACKAGE, GNOMELOCALEDIR); textdomain (PACKAGE); gnome_init_with_popt_table(APPNAME, VERSION, argc, argv, options, 0, &ctx); args = poptGetArgs(ctx); if (args != NULL) { i = 0; while (args[i] != NULL) { /* Do something with each argument */ ++i; } } poptFreeContext(ctx); |
Notice that you must free the poptContext if you ask for it; however, if you pass NULL for return_ctx the library will free it for you. Also keep in mind that poptGetArgs() will return NULL if there are no arguments on the command line.
The GnomeHello application outputs the following if you invoke it with the --help option:
$ ./hello --help Usage: hello [OPTION...] GNOME Options --disable-sound Disable sound server usage --enable-sound Enable sound server usage --espeaker=HOSTNAME:PORT Host:port on which the sound server to use is running Help options -?, --help Show this help message --usage Display brief usage message GTK options --gdk-debug=FLAGS Gdk debugging flags to set --gdk-no-debug=FLAGS Gdk debugging flags to unset --display=DISPLAY X display to use --sync Make X calls synchronous --no-xshm Don't use X shared memory extension --name=NAME Program name as used by the window manager --class=CLASS Program class as used by the window manager --gxid_host=HOST --gxid_port=PORT --xim-preedit=STYLE --xim-status=STYLE --gtk-debug=FLAGS Gtk+ debugging flags to set --gtk-no-debug=FLAGS Gtk+ debugging flags to unset --g-fatal-warnings Make all warnings fatal --gtk-module=MODULE Load an additional Gtk module GNOME GUI options -V, --version Help options -?, --help Show this help message --usage Display brief usage message Session management options --sm-client-id=ID Specify session management ID --sm-config-prefix=PREFIX Specify prefix of saved configuration --sm-disable Disable connection to session manager GnomeHello options -g, --greet Say hello to specific people listed on the command line -m, --message=MESSAGE Specify a message other than "Hello, World!" --geometry=GEOMETRY Specify the geometry of the main window $ |
Almost all of these options are common to all Gnome applications; only the last three, labelled "GnomeHello options," are specific to GnomeHello. The --greet or -g option turns on "greet mode"; GnomeHello will expect a list of names on the command line, and create a dialog to say hello to each person named. The --message option expects a string argument which replaces the usual "Hello, World!" message; the --geometry option expects a standard X geometry string, specifying the position and size of the main application window.
Here are the variables and popt table GnomeHello uses to do its argument parsing:
static int greet_mode = FALSE; static char* message = NULL; static char* geometry = NULL; struct poptOption options[] = { { "greet", 'g', POPT_ARG_NONE, &greet_mode, 0, N_("Say hello to specific people listed on the command line"), NULL }, { "message", 'm', POPT_ARG_STRING, &message, 0, N_("Specify a message other than \"Hello, World!\""), N_("MESSAGE") }, { "geometry", '\0', POPT_ARG_STRING, &geometry, 0, N_("Specify the geometry of the main window"), N_("GEOMETRY") }, { NULL, '\0', 0, NULL, 0, NULL, NULL } }; |
And here's the first part of main(), where GnomeHello checks that the arguments are properly combined and assembles a list of people to greet:
GtkWidget* app; poptContext pctx; char** args; int i; GSList* greet = NULL; GnomeClient* client; bindtextdomain(PACKAGE, GNOMELOCALEDIR); textdomain(PACKAGE); gnome_init_with_popt_table(PACKAGE, VERSION, argc, argv, options, 0, &pctx); /* Argument parsing */ args = poptGetArgs(pctx); if (greet_mode && args) { i = 0; while (args[i] != NULL) { greet = g_slist_prepend(greet, args[i]); ++i; } /* Put them in order */ greet = g_slist_reverse(greet); } else if (greet_mode && args == NULL) { g_error(_("You must specify someone to greet.")); } else if (args != NULL) { g_error(_("Command line arguments are only allowed with --greet.")); } else { g_assert(!greet_mode && args == NULL); } poptFreeContext(pctx); |
Again, complete source for GnomeHello is included in Appendix E.