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).
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:
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.