A command-line argument parser single-header library written in C using X macros.
- Start by cloning the repository with
git clone https://github.com/Noxmor/clapx. - Run
make install. - Done! You can now include the library by typing
#include <clapx/clapx.h>.
Note
Alternatively, you can also just copy/clone the library locally and include it directly.
In order to use clapx, you will want to first define the CLAPX_FLAGS and CLAPX_SUBCOMMANDS macros to fit the specification of your application.
Important
The macros CLAPX_FLAGS and CLAPX_SUBCOMMANDS must be defined before including clapx with implementation details.
Define CLAPX_IMPLEMENTATION before including clapx to include the implementation details.
In order to define global flags, you will need to define the CLAPX_FLAGS macro. Each flag will then be defined via one of the CLAPX_<type>_FLAG macros, like this:
void help_callback(void);
#define CLAPX_FLAGS \
CLAPX_BOOL_FLAG(help, "help", 'h', "Prints this help message.", help_callback) \
CLAPX_STRING_FLAG(foo, "foo", CLAPX_NO_SHORT, CLAPX_NO_DESC, CLAPX_NO_CALLBACK, "my-custom-default-string") \
CLAPX_CHAR_FLAG(bar, CLAPX_ONLY_SHORT('b'), CLAPX_NO_DESC, CLAPX_NO_CALLBACK, 'b')CLAPX_BOOL_FLAG(label, long_name, short_name, desc, callback)CLAPX_U8_FLAG(label, type, long_name, short_name, desc, callback, default_value)CLAPX_U16_FLAG(label, type, long_name, short_name, desc, callback, default_value)CLAPX_U32_FLAG(label, type, long_name, short_name, desc, callback, default_value)CLAPX_U64_FLAG(label, type, long_name, short_name, desc, callback, default_value)CLAPX_I8_FLAG(label, type, long_name, short_name, desc, callback, default_value)CLAPX_I16_FLAG(label, type, long_name, short_name, desc, callback, default_value)CLAPX_I32_FLAG(label, type, long_name, short_name, desc, callback, default_value)CLAPX_I64_FLAG(label, type, long_name, short_name, desc, callback, default_value)CLAPX_CHAR_FLAG(label, type, long_name, short_name, desc, callback, default_value)CLAPX_STRING_FLAG(label, type, long_name, short_name, desc, callback, default_value)CLAPX_CUSTOM_FLAG(label, type, long_name, short_name, desc, callback, parser)
where...
labelis a unique and valid C identifier.typeis eitherCLAPX_FLAG_TYPE_OPT_ARGorCLAPX_FLAG_TYPE_REQ_ARG.long_nameis a string literal orCLAPX_NO_LONG.short_nameis an alphanumeric character orCLAPX_NO_SHORT.descis either a string literal orCLAPX_NO_DESC.callbackis a function pointer of typeclapx_flag_callback_torCLAPX_NO_CALLBACK. If set, this callback is triggered immediately after the flag is parsed.parseris a function pointer of typeclapx_custom_parser_callback_t.
Note
Any pair of arguments (long_name, short_name) may be replaced with one of the following macros:
CLAPX_ONLY_LONG(long_name)CLAPX_ONLY_SHORT(short_name)
In order to define subcommands, you will need to define the CLAPX_SUBCOMMANDS macro. Each subcommand will then be defined via the CLAPX_SUBCOMMAND macro, like this:
void foo_callback(int argc, char** argv);
#define CLAPX_SUBCOMMANDS \
CLAPX_SUBCOMMAND(foo, "foo", "The foo subcommand.", foo_callback) \
CLAPX_SUBCOMMAND(bar, "bar", CLAPX_NO_DESC, CLAPX_NO_CALLBACK, CLAPX_BOOL_FLAG(help, "help", 'h', CLAPX_NO_DESC, CLAPX_NO_CALLBACK))CLAPX_SUBCOMMAND(label, name, desc, callback, ...)
where...
labelis a unique and valid C identifier.nameis a string literal.descis either a string literal orCLAPX_NO_DESC.callbackis a function pointer of typeclapx_subcommand_callback_torCLAPX_NO_CALLBACK. If set, this callback is triggered immediately after the command-line is completely parsed....are zero or moreCLAPX_FLAGmacros.
You can parse the command-line, typically inside your main function, as follows:
int main(int argc, char** argv)
{
if (clapx_parse_args(argc, argv) != CLAPX_SUCCESS)
{
// Some internal parser error occured.
return EXIT_FAILURE;
}
}Most likely, after parsing the command-line, you will want to inspect the value of a certain flag, since it may differ from the default value if the user specified it. The way this is done depends on whether the flag is global or subcommand-specific.
For global flags: Use one of the CLAPX_<type>_FLAG_VALUE(flag) macros, like this:
int main(int argc, char** argv)
{
// Retrieves the value of the global flag 'foo'.
const char* string_flag_value = CLAPX_STRING_FLAG_VALUE(foo);
}CLAPX_BOOL_FLAG_VALUE(flag)CLAPX_U8_FLAG_VALUE(flag)CLAPX_U16_FLAG_VALUE(flag)CLAPX_U32_FLAG_VALUE(flag)CLAPX_U64_FLAG_VALUE(flag)CLAPX_I8_FLAG_VALUE(flag)CLAPX_I16_FLAG_VALUE(flag)CLAPX_I32_FLAG_VALUE(flag)CLAPX_I64_FLAG_VALUE(flag)CLAPX_CHAR_FLAG_VALUE(flag)CLAPX_STRING_FLAG_VALUE(flag)
where...
flagis the label of the flag.
For subcommand-specific flags: Use one of the CLAPX_SUBCOMMAND_<t<pe>_FLAG_VALUE(subcommand, flag) macros, like this:
void foo_callback(int argc, char** argv)
{
// Retrieves the value of the 'bar' flag, which is bound to the 'foo' subcommand.
if (CLAPX_SUBCOMMAND_BOOL_FLAG_VALUE(foo, bar))
{
// ...
}
else
{
// ...
}
}CLAPX_SUBCOMMAND_BOOL_FLAG_VALUE(subcommand, flag)CLAPX_SUBCOMMAND_U8_FLAG_VALUE(subcommand, flag)CLAPX_SUBCOMMAND_U16_FLAG_VALUE(subcommand, flag)CLAPX_SUBCOMMAND_U32_FLAG_VALUE(subcommand, flag)CLAPX_SUBCOMMAND_U64_FLAG_VALUE(subcommand, flag)CLAPX_SUBCOMMAND_I8_FLAG_VALUE(subcommand, flag)CLAPX_SUBCOMMAND_I16_FLAG_VALUE(subcommand, flag)CLAPX_SUBCOMMAND_I32_FLAG_VALUE(subcommand, flag)CLAPX_SUBCOMMAND_I64_FLAG_VALUE(subcommand, flag)CLAPX_SUBCOMMAND_CHAR_FLAG_VALUE(subcommand, flag)CLAPX_SUBCOMMAND_STRING_FLAG_VALUE(subcommand, flag)
where...
subcommandis the label of the subcommand.flagis the label of the subcommand-specific flag.