Skip to content

Commit

Permalink
Fix command line parser
Browse files Browse the repository at this point in the history
Allows to specify multiple --config options.

Signed-off-by: Artem Senichev <[email protected]>
  • Loading branch information
artemsen committed Oct 15, 2024
1 parent 979cc7d commit 5191cbf
Showing 1 changed file with 42 additions and 91 deletions.
133 changes: 42 additions & 91 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,42 +22,25 @@ struct cmdarg {
const char* long_opt; ///< Long option name
const char* format; ///< Format description
const char* help; ///< Help string
const char* value; ///< Argument value
};

// clang-format off
static struct cmdarg arguments[] = {
{ 'g', "gallery", NULL, "start in gallery mode", NULL },
{ 'r', "recursive", NULL, "read directories recursively", NULL },
{ 'o', "order", "ORDER", "set sort order for image list: none/[alpha]/reverse/random", NULL },
{ 's', "scale", "SCALE", "set initial image scale: [optimal]/fit/width/height/fill/real", NULL },
{ 'l', "slideshow", NULL, "activate slideshow mode on startup", NULL },
{ 'p', "position", "POS", "set window position [parent]/X,Y", NULL },
{ 'w', "size", "SIZE", "set window size: fullscreen/[parent]/image/W,H", NULL },
{ 'f', "fullscreen", NULL, "show image in full screen mode", NULL },
{ 'a', "class", "NAME", "set window class/app_id", NULL },
{ 'c', "config", "S.K=V", "set configuration parameter: section.key=value", NULL },
{ 'v', "version", NULL, "print version info and exit", NULL },
{ 'h', "help", NULL, "print this help and exit", NULL },
static const struct cmdarg arguments[] = {
{ 'g', "gallery", NULL, "start in gallery mode" },
{ 'r', "recursive", NULL, "read directories recursively" },
{ 'o', "order", "ORDER", "set sort order for image list: none/[alpha]/reverse/random" },
{ 's', "scale", "SCALE", "set initial image scale: [optimal]/fit/width/height/fill/real" },
{ 'l', "slideshow", NULL, "activate slideshow mode on startup" },
{ 'p', "position", "POS", "set window position [parent]/X,Y" },
{ 'w', "size", "SIZE", "set window size: fullscreen/[parent]/image/W,H" },
{ 'f', "fullscreen", NULL, "show image in full screen mode" },
{ 'a', "class", "NAME", "set window class/app_id" },
{ 'c', "config", "S.K=V", "set configuration parameter: section.key=value" },
{ 'v', "version", NULL, "print version info and exit" },
{ 'h', "help", NULL, "print this help and exit" },
};
// clang-format on

/**
* Get argument description by it short opt.
* @param short_opt short opt to find
* @return pointer to the argument description or NULL if not found
*/
static struct cmdarg* get_arg(char short_opt)
{
for (size_t i = 0; i < ARRAY_SIZE(arguments); ++i) {
struct cmdarg* arg = &arguments[i];
if (arg->short_opt == short_opt) {
return arg;
}
}
return NULL;
}

/**
* Print usage info.
*/
Expand Down Expand Up @@ -96,9 +79,9 @@ static void print_version(void)
* Parse command line arguments.
* @param argc number of arguments to parse
* @param argv arguments array
* @return index of the first non option argument, or -1 if error
* @return index of the first non option argument
*/
static int parse_cmdargs(int argc, char* argv[])
static int parse_cmdargs(int argc, char* argv[], struct config** cfg)
{
struct option options[1 + ARRAY_SIZE(arguments)];
char short_opts[ARRAY_SIZE(arguments) * 2];
Expand All @@ -124,106 +107,74 @@ static int parse_cmdargs(int argc, char* argv[])

// parse arguments
while ((opt = getopt_long(argc, argv, short_opts, options, NULL)) != -1) {
struct cmdarg* arg;

if (opt == '?') {
return -1;
}
arg = get_arg(opt);
if (!arg) {
return -1;
}

arg->value = arg->format ? optarg : arg->long_opt;
}

return optind;
}

/**
* Load configuration.
* @return pointer to config instnce or NULL on error
*/
static struct config* load_config(void)
{
struct config* cfg = config_load();

for (size_t i = 0; i < ARRAY_SIZE(arguments); ++i) {
const struct cmdarg* arg = &arguments[i];
if (!arg->value) {
continue;
}
switch (arg->short_opt) {
switch (opt) {
case 'g':
config_set(&cfg, APP_CFG_SECTION, APP_CFG_MODE,
config_set(cfg, APP_CFG_SECTION, APP_CFG_MODE,
APP_MODE_GALLERY);
break;
case 'r':
config_set(&cfg, IMGLIST_SECTION, IMGLIST_RECURSIVE, "yes");
config_set(cfg, IMGLIST_SECTION, IMGLIST_RECURSIVE, "yes");
break;
case 'o':
config_set(&cfg, IMGLIST_SECTION, IMGLIST_ORDER, arg->value);
config_set(cfg, IMGLIST_SECTION, IMGLIST_ORDER, optarg);
break;
case 's':
config_set(&cfg, VIEWER_SECTION, VIEWER_SCALE, arg->value);
config_set(cfg, VIEWER_SECTION, VIEWER_SCALE, optarg);
break;
case 'l':
config_set(&cfg, VIEWER_SECTION, VIEWER_SLIDESHOW, "yes");
config_set(cfg, VIEWER_SECTION, VIEWER_SLIDESHOW, "yes");
break;
case 'p':
config_set(&cfg, APP_CFG_SECTION, APP_CFG_POSITION, arg->value);
config_set(cfg, APP_CFG_SECTION, APP_CFG_POSITION, optarg);
break;
case 'w':
config_set(&cfg, APP_CFG_SECTION, APP_CFG_SIZE, arg->value);
config_set(cfg, APP_CFG_SECTION, APP_CFG_SIZE, optarg);
break;
case 'f':
config_set(&cfg, APP_CFG_SECTION, APP_CFG_SIZE, APP_FULLSCREEN);
config_set(cfg, APP_CFG_SECTION, APP_CFG_SIZE, APP_FULLSCREEN);
break;
case 'a':
config_set(&cfg, APP_CFG_SECTION, APP_CFG_APP_ID, arg->value);
config_set(cfg, APP_CFG_SECTION, APP_CFG_APP_ID, optarg);
break;
case 'c':
if (!config_set_arg(&cfg, arg->value)) {
if (!config_set_arg(cfg, optarg)) {
fprintf(stderr,
"WARNING: Invalid config agrument: \"%s\"\n",
arg->value);
optarg);
}
break;
case 'v':
print_version();
exit(EXIT_SUCCESS);
break;
case 'h':
print_help();
exit(EXIT_SUCCESS);
break;
default:
exit(EXIT_FAILURE);
}
}

return cfg;
return optind;
}

/**
* Application entry point.
*/
int main(int argc, char* argv[])
{
bool rc = false;
bool rc;
struct config* cfg;
int argn;

setlocale(LC_ALL, "");

// parse command line arguments
argn = parse_cmdargs(argc, argv);
if (argn < 0) {
return EXIT_FAILURE;
}
if (get_arg('v')->value) {
print_version();
return EXIT_SUCCESS;
}
if (get_arg('h')->value) {
print_help();
return EXIT_SUCCESS;
}

cfg = load_config();
cfg = config_load();
argn = parse_cmdargs(argc, argv, &cfg);
rc = app_init(cfg, (const char**)&argv[argn], argc - argn);

if (rc) {
if (cfg && rc) {
config_check(cfg);
}
config_free(cfg);
Expand Down

0 comments on commit 5191cbf

Please sign in to comment.