Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

liboptparse: Support setting alternate usage callback function #929

Merged
merged 4 commits into from Dec 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 3 additions & 9 deletions src/cmd/flux.c
Expand Up @@ -86,9 +86,6 @@ void usage (optparse_t *p)
static optparse_t * setup_optparse_parse_args (int argc, char *argv[])
{
optparse_err_t e;
struct optparse_option helpopt = {
.name = "help", .key = 'h', .usage = "Display this message"
};
optparse_t *p = optparse_create ("flux");
if (p == NULL)
log_err_exit ("optparse_create");
Expand All @@ -97,13 +94,10 @@ static optparse_t * setup_optparse_parse_args (int argc, char *argv[])
if (e != OPTPARSE_SUCCESS)
log_msg_exit ("optparse_add_option_table() failed");

// Remove automatic `--help' in favor of our own usage() from above
e = optparse_remove_option (p, "help");
// Disable automatic `--help' in favor of our own usage() from above
e = optparse_set (p, OPTPARSE_OPTION_CB, "help", NULL);
if (e != OPTPARSE_SUCCESS)
log_msg_exit ("optparse_remove_option (\"help\")");
e = optparse_add_option (p, &helpopt);
if (e != OPTPARSE_SUCCESS)
log_msg_exit ("optparse_add_option (\"help\")");
log_msg_exit ("optparse_set() failed");

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though it is almost impossible to have an error, should we check error here just for completeness? (And in case code gets duplicated or used as an example)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, you're right. I was being lazy. New push coming.

// Don't print internal subcommands in --help (we print subcommands using
// emit_command_help() above.
Expand Down
22 changes: 22 additions & 0 deletions src/common/liboptparse/optparse.c
Expand Up @@ -247,6 +247,20 @@ static optparse_err_t optparse_set_fatalerr_handle (optparse_t *p, void *handle)
return (0);
}

static optparse_err_t optparse_set_option_cb (optparse_t *p, const char *name,
optparse_cb_f fn)
{
struct option_info *o;

if (!name)
return (OPTPARSE_BAD_ARG);

if (!(o = find_option_info (p, name)))
return (OPTPARSE_BAD_ARG);

o->p_opt->cb = fn;
return (0);
}

/*
* Generic function that prints a message to stderr. Default logging function.
Expand Down Expand Up @@ -983,6 +997,8 @@ optparse_err_t optparse_set (optparse_t *p, optparse_item_t item, ...)
{
optparse_err_t e = OPTPARSE_SUCCESS;
va_list vargs;
optparse_cb_f cb;
char *str;
int n;

if (p == NULL)
Expand All @@ -1009,6 +1025,11 @@ optparse_err_t optparse_set (optparse_t *p, optparse_item_t item, ...)
else
p->left_margin = n;
break;
case OPTPARSE_OPTION_CB:
str = va_arg (vargs, char *);
cb = va_arg (vargs, void *);
e = optparse_set_option_cb (p, str, cb);
break;
case OPTPARSE_OPTION_WIDTH:
n = va_arg (vargs, int);
if ((n < 0) || (n > 1000))
Expand Down Expand Up @@ -1065,6 +1086,7 @@ optparse_err_t optparse_get (optparse_t *p, optparse_item_t item, ...)
case OPTPARSE_FATALERR_FN:
case OPTPARSE_FATALERR_HANDLE:
case OPTPARSE_LEFT_MARGIN:
case OPTPARSE_OPTION_CB:
case OPTPARSE_OPTION_WIDTH:
e = OPTPARSE_NOT_IMPL;
break;
Expand Down
3 changes: 2 additions & 1 deletion src/common/liboptparse/optparse.h
Expand Up @@ -22,7 +22,7 @@ typedef int (*opt_fatalerr_f) (void *h, int exit_code);
/*
* prototype for option callback hook
*/
typedef int (*optparse_cb_f) (optparse_t *p, struct optparse_option *,
typedef int (*optparse_cb_f) (optparse_t *p, struct optparse_option *o,
const char *optarg);

/*
Expand Down Expand Up @@ -50,6 +50,7 @@ typedef enum {
OPTPARSE_LOG_FN, /* Set log function (default fprintf(stderr,..)) */
OPTPARSE_FATALERR_FN, /* Set fatal err function (default: exit() ) */
OPTPARSE_FATALERR_HANDLE, /* Set handle passed to fatalerr function */
OPTPARSE_OPTION_CB, /* Change option cb function (char *,optparse_cb_f) */
OPTPARSE_OPTION_WIDTH, /* Width allotted to options in --help output */
OPTPARSE_LEFT_MARGIN, /* Left pad for option output (default = 2) */
OPTPARSE_PRINT_SUBCMDS,/* Print all subcommands in --help (default = T */
Expand Down
70 changes: 69 additions & 1 deletion src/common/liboptparse/test/optparse.c
Expand Up @@ -251,6 +251,73 @@ This is some doc for group 1\n\
optparse_destroy (p);
}

int alt_print_usage (optparse_t *p, struct optparse_option *o, const char *optarg)
{
output_f ("alt_print_usage called");
return (0);
}

void test_option_cb (void)
{
optparse_err_t e;
optparse_t *p = optparse_create ("test-help");
char *av[] = { "test-help", "-h", NULL };
int ac = sizeof (av) / sizeof (av[0]) - 1;
int optindex;

ok (p != NULL, "optparse_create");

e = optparse_set (p, OPTPARSE_LOG_FN, output_f);
ok (e == OPTPARSE_SUCCESS, "optparse_set (LOG_FN)");

e = optparse_set (p, OPTPARSE_FATALERR_FN, myfatal);
ok (e == OPTPARSE_SUCCESS, "optparse_set (FATALERR_FN)");

/* We will test OPTION_CB by modifying the help function callback */

/* Check default --help output works as expected */

optindex = optparse_parse_args (p, ac, av);
ok (optindex == ac, "parse options, verify optindex");

usage_output_is ("\
Usage: test-help [OPTIONS]...\n\
-h, --help Display this message.\n",
"Default usage output from -h call correct");

/* Check --help calls alternate usage function when cb is changed */

e = optparse_set (p, OPTPARSE_OPTION_CB, "help", alt_print_usage);
ok (e == OPTPARSE_SUCCESS, "optparse_set (OPTION_CB)");

optindex = optparse_parse_args (p, ac, av);
ok (optindex == ac, "parse options, verify optindex");

usage_output_is ("alt_print_usage called", "alt usage output as expected");

/* Check --help doesn't call a usage function if cb set to NULL */

output_f ("no usage output");

e = optparse_set (p, OPTPARSE_OPTION_CB, "help", NULL);
ok (e == OPTPARSE_SUCCESS, "optparse_set (OPTION_CB)");

optindex = optparse_parse_args (p, ac, av);
ok (optindex == ac, "parse options, verify optindex");

usage_output_is ("no usage output", "no usage output is expected");

/* Finally check for some proper error handling */

e = optparse_set (p, OPTPARSE_OPTION_CB, NULL, NULL);
ok (e == OPTPARSE_BAD_ARG, "optparse_set (OPTION_CB): bad arg null name ");

e = optparse_set (p, OPTPARSE_OPTION_CB, "bad-option", NULL);
ok (e == OPTPARSE_BAD_ARG, "optparse_set (OPTION_CB): bad arg bad name ");

optparse_destroy (p);
}

void test_convenience_accessors (void)
{
struct optparse_option opts [] = {
Expand Down Expand Up @@ -862,10 +929,11 @@ void test_corner_case (void)
int main (int argc, char *argv[])
{

plan (196);
plan (212);

test_convenience_accessors (); /* 35 tests */
test_usage_output (); /* 42 tests */
test_option_cb (); /* 16 tests */
test_errors (); /* 9 tests */
test_multiret (); /* 19 tests */
test_data (); /* 8 tests */
Expand Down