I'm learning C, and got stuck doing cli parsing with <argp.h>
. I want to specify path with -p, --path
flags, so I did this:
#include "treesome.h"
#include <argp.h>
#include <stdio.h>
const char *argp_program_version =
"treesome-build 0.2";
static char doc[] =
"Treesome -- filesystem tree-like output\
\v Tree will show easy to eyeball directory structure";
static char args_doc[] = "";
static struct argp_option options[] = {
{0,0,0,0, "Output view" },
{"all", 'a', 0, 0, "produce verbose output with all the content"},
{"dereference", 'd', 0, 0, "dereferences soft links"},
{"path", 'p', 0, OPTION_ARG_OPTIONAL, "specify path for tree root"},
{ 0 }
};
struct arguments {
int all, derefence, is_path;
char *path;
};
static error_t parse_opts(int key, char *arg, struct argp_state *state) {
struct arguments *arguments = state->input;
switch (key) {
case 'a':
arguments->all = 1;
break;
case 'd':
arguments->derefence = 1;
break;
case 'p':
arguments->is_path = 1;
break;
case ARGP_KEY_ARG:
if (state->arg_num == 0)
break;
if (arguments->is_path == 1)
arguments->path = arg;
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
};
static struct argp argp = {
options,
parse_opts,
args_doc,
doc
};
int main(int argc, char **argv) {
struct arguments arguments;
arguments.all = 0;
arguments.derefence = 0;
arguments.path = ".";
argp_parse(&argp, argc, argv, 0, 0, &arguments);
printf("Called with args: \n");
printf("%d for all\n", arguments.all);
printf("%d for dereference\n", arguments.derefence);
printf("%s for path\n\n", arguments.path);
return treesome(arguments.path);
};
and typing ./tree -p /home/floatfoo/
I got that path is always default. What might be a problem? I dont quite understand what for ARGP_KEY_ARG
and ARGP_KEY_ARGS
are used for
CodePudding user response:
After removing treesome your option does not take an argument:
{"path", 'p', 0, OPTION_ARG_OPTIONAL, "specify path for tree root"}, ^^^ ./a.out --help -p, --path specify path for tree root
You have to take the option:
{"path", 'p', "path", OPTION_ARG_OPTIONAL, "specify path for tree root"},
./a.out --help
-p, --path[=path] specify path for tree root
In which case only the long form takes the option.
./a.out -p smth -> too many arguments
./a.out --path=smth -> ok
Remove OPTION_ARG_OPTIONAL
if you want -p
to take arg. And also set your path and remove the KEY_ARG case. It's just:
static error_t parse_opts(int key, char *arg, struct argp_state *state) {
struct arguments *arguments = state->input;
switch (key) {
case 'a':
arguments->all = 1;
break;
case 'd':
arguments->derefence = 1;
break;
case 'p':
arguments->path = arg;
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
};