commander.c - C option parser

Every time I write a C program I end up rolling my own option parsing with a loop and strcmp(), so I figured it was time to port over commander.c from the original ruby commander, and there’s also a node.js port.

Commander.c is a super simple script that makes defining options declarative and does the dirty work for you, its usage looks like this:

#include <stdio.h>
#include "commander.h"

static void
verbose(command_t *self) {
  printf("verbose: enabled\n");
}

static void
required(command_t *self) {
  printf("required: %s\n", self->arg);
}

static void
optional(command_t *self) {
  printf("optional: %s\n", self->arg);
}

int
main(int argc, const char **argv){
  command_t cmd;
  command_init(&cmd, argv[0], "0.0.1");
  command_option(&cmd, "-v", "--verbose", "enable verbose stuff", verbose);
  command_option(&cmd, "-r", "--required <arg>", "required arg", required);
  command_option(&cmd, "-o", "--optional [arg]", "optional arg", optional);
  command_parse(&cmd, argc, argv);
  printf("additional args:\n");
  for (int i = 0; i < cmd.argc; ++i) {
    printf("  - '%s'\n", cmd.argv[i]);
  }
  return 0;
}

As a bonus it generates the --help from what it already knows about your program:

Usage: example [options]

Options:

  -V, --version                 output program version
  -h, --help                    output help information
  -v, --verbose                 enable verbose stuff
  -r, --required <arg>          required arg
  -o, --optional [arg]          optional arg

Commander handles optional and required args:

$ mon --sleep
 --sleep requires an argument

Warns about unrecognized flags:

$ ./test --foo
unrecognized flag --foo

Unparsed arguments are then provided as cmd.argv and of course its companion cmd.argc, which of course includes -- support to flag subsequent args as literals:

$ ./test foo -- --foo
additional args:
  - 'foo'
  - '--bar'

If you have a struct that you want to access within each callback just assign to cmd.data, a void *.

That’s it for now, I’ll be adding a few more things in the near future so check it out on github.

Notes

  1. tjholowaychuk posted this