Command line arguments parsing (CLAP) library, written in iso-C99 (and C++ compatible).
This module is inspired by ArgP
(which is GNU C),
the python argparse
module and,
for the code, by the argparse
libray of CofyC with a few additions and modifications.
Indeed, getopt
is quite difficult to use, and GNU C (so is ArgP), which is not always available. The goal is to provide high-level library
for command line argument parsing, in the spirit of the awesome python argparse
module. CLAP provides help and usage messages. It takes care
of recognising arguments and values from argv
. It delivers errors if any.
- Handles long (starting with two dashes, e.g.
--something
), short (one dash and one alphanumeric character, e.g.-x
) and positional arguments () ; - Issues errors messages when arguments are invalid ;
- Options are case-sensitive.
- Short options are bundlable (e.g.
-a -b
can be given as-ab
) ; - Convert strings into other types (boolean, float, integers) ;
- Basic file management available ;
- Callbacking is possible ;
- An option can be set mandatory.
You first need CLAP.c
and CLAP.h
(maybe you should consider adding a submodule).
And, of course, you should include the header:
#include "CLAP.h"
A ClapOption
's array need to be construct. Syntax may be, for example,
double threshold = 10;
bool verbose = false;
ClapOption options[] = {
CLAP_HELP(),
CLAP_DOUBLE('e', "threshold", &threshold, "Threshold", CLAP_FLAG_MANDATORY),
CLAP_BOOLEAN('v', "verbose", &verbose, "Talk more !", 0),
CLAP_END()
};
You have to end the array with CLAP_END()
. You can provide as many argument as you want, using some macros. Most of them have this form:
CLAP_BOOLEAN(short, long, pointer, help, flags [, callback])
where,
short
(char
) is the alphanumeric character for short option (-x
). Set to 0 if you don't want a short option.long
(const char*
) is the string for long option (--long
). Set toNULL
if you don't want a long option.pointer
(void*
) is a pointer to the variable which has to be modified is the option is used.help
(const char*
) is a text printed when usage is requested.flags
(unsigned int
) is a variable for flagging (see below). Set to 0 if there is no flags.callback
(int fun(ClapHandler* h, ClapOption* c)
) is a pointer to a callback function (see below). If there is no callback, you may not set this option. If there is a callback, set theCLAP_FLAG_CALLBACK
flag.
The following macros are defined:
CLAP_INTEGER(...)
: integer option, converted toint
.CLAP_DOUBLE(...)
: floatting option, converted todouble
.CLAP_STRING(...)
: string option, left aschar*
. Note that the string is not copied, so the pointer is set to one ofargv
string.CLAP_FILE_R(...)
: the path given in argument is opened withfopen(.., 'r')
, converted toFILE*
.CLAP_FILE_W(...)
: the path given in argument is opened withfopen(.., 'w')
, converted toFILE*
.CLAP_BOOLEAN(...)
: this option does not set the variable, it reverses the value when used (e.g. set it tofalse
iftrue
).
Flags can be:
CLAP_FLAG_MANDATORY
: the option is mandatory, it must be set, otherwise there is an error issued.CLAP_FLAG_CALLBACK
; the option calls a callback function at the end.CLAP_FLAG_POSITIONAL
: this option is positional. In the macro, you need to setshort
to 0, whilelong
is used as the name of the option in usage.
Additionnaly, there is 3 more macros you can use:
CLAP_GROUP(h)
: option below are in a new group when printed in the usage.CLAP_HELP()
: set-h
and--help
to call the usage.CLAP_END()
: signal the end of the array. Options given after that macro are ignored.
Then, use:
ClapHandler *handler = clap_handler_new(
options,
"program_name",
"A description of the programm",
"An epilog (e.g. copyrigthing, author ...)"
);
if (handler == NULL) {
return EXIT_FAILURE;
}
if (clap_parse(handler, argc, argv) != 0) {
return EXIT_FAILURE;
}
where clap_handler_new()
is the function to initialize the parser, which returns NULL
if there is a mistake in the array of options that you provide.
The clap_parse()
function finally perform the job. Its return value depends where the error occured:
-1
: error happens in the level of parsing. Most of the time, because a mandatory argument is not set.-2
error happens in the level of recognition. The option probably does not exists.-3
: error happens in the level of setting. The value is probably not what expected.-4
: this is not an error, but the help was requested, so parsing stops.- Your callbacks can also return errors (see below).
When done, simply use
clap_handler_delete(handler);
Note that the option array and string are not free()
'd, you are responsible for that.
Here is an example of callback use:
#include "CLAP.h"
#include <stdio.h>
#include <stdlib.h>
int a_callback(ClapHandler* handler, ClapOption* opt) {
char* string = *((char**) opt->ptr_value);
printf("The callback was called, and the value is `%s`.\n", string);
return 0;
}
int main(int argc, char** argv) {
char* a_string = NULL;
ClapOption options[] = {
CLAP_HELP(),
CLAP_STRING('c', "callback", &a_string, "Call the callback", CLAP_FLAG_CALLBACK, a_callback),
CLAP_END()
};
ClapHandler *handler = clap_handler_new(
options,
"program_name",
"A description of the programm",
"An epilog (e.g. copyrigthing, author ...)"
);
if (handler == NULL) {
return EXIT_FAILURE;
}
if (clap_parse(handler, argc, argv) != 0) {
return EXIT_FAILURE;
}
clap_handler_delete(handler);
}
Notice, in the CLAP_STRING()
macro, the CLAP_FLAG_CALLBACK
flag (if you don't set it, the callback is not called) and then the function pointer. Also, the signature of the callback function must be
int a_callback(ClapHandler* handler, ClapOption* opt)
The return value must be 0
if you want the program to continue, otherwise it wilkl stop (return nothing else but 0 if there is an error, for example).
See the code in example.c. Compilation is performed by using cmake && make
.
Here is some outputs:
~ $ ./CLAP -h ## usage
Usage: program_name [OPTION]... [file] -e <float>
A description of the program
Positional arguments:
file Read a file
Other arguments:
-h, --help show this help message and exit
-e, --threshold=FLOAT thresholding
-c, --callback=STRING call the callback with a value
Some test options:
-v, --verbose talk more !
-t, --test play with boolean !
An epilog (e.g. copyrighting, author ...)
~ $ ./CLAP
error: option `-e` is mandatory but not set
~ $ ./CLAP -e 1
Threshold is set to 1.000
Variable test is true !
~ $ ./CLAP -e 1 -v -t
Threshold is set to 1.000
Something else !
Variable test is false !
~ $ ./CLAP -e 1 -vt ## short option are bundlable
Threshold is set to 1.000
Something else !
Variable test is false !
~ $ ./CLAP example.c -e 1 -vt ## positional arguments
File can be read !
Threshold is set to 1.000
Something else !
Variable test is false !
~ $ ./CLAP invalid_file -e 1 -vt ## invalid file is invalid
error: option `file` can't open `invalid_file`