mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 23:07:18 +00:00
[common] option: added shortopt support and pretty help print
This commit is contained in:
parent
b9841351b4
commit
2d5f6d65ce
@ -36,6 +36,7 @@ struct Option
|
|||||||
char * module;
|
char * module;
|
||||||
char * name;
|
char * name;
|
||||||
char * description;
|
char * description;
|
||||||
|
const char shortopt;
|
||||||
|
|
||||||
enum OptionType type;
|
enum OptionType type;
|
||||||
union
|
union
|
||||||
|
@ -19,6 +19,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "common/option.h"
|
#include "common/option.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
#include "common/stringutils.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -90,6 +91,9 @@ static char * bool_toString(struct Option * opt)
|
|||||||
|
|
||||||
static char * string_toString(struct Option * opt)
|
static char * string_toString(struct Option * opt)
|
||||||
{
|
{
|
||||||
|
if (!opt->value.x_string)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return strdup(opt->value.x_string);
|
return strdup(opt->value.x_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +160,10 @@ bool option_register(struct Option options[])
|
|||||||
|
|
||||||
// ensure the string is locally allocated
|
// ensure the string is locally allocated
|
||||||
if (o->type == OPTION_TYPE_STRING)
|
if (o->type == OPTION_TYPE_STRING)
|
||||||
|
{
|
||||||
|
if (o->value.x_string)
|
||||||
o->value.x_string = strdup(o->value.x_string);
|
o->value.x_string = strdup(o->value.x_string);
|
||||||
|
}
|
||||||
|
|
||||||
// add the option to the correct group for help printout
|
// add the option to the correct group for help printout
|
||||||
bool found = false;
|
bool found = false;
|
||||||
@ -236,6 +243,12 @@ static bool option_set(struct Option * opt, const char * value)
|
|||||||
bool option_parse(int argc, char * argv[])
|
bool option_parse(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
for(int a = 1; a < argc; ++a)
|
for(int a = 1; a < argc; ++a)
|
||||||
|
{
|
||||||
|
struct Option * o = NULL;
|
||||||
|
char * value = NULL;
|
||||||
|
|
||||||
|
// emulate getopt for backwards compatability
|
||||||
|
if (argv[a][0] == '-')
|
||||||
{
|
{
|
||||||
if (strcmp(argv[a], "-h") == 0 || strcmp(argv[a], "--help") == 0)
|
if (strcmp(argv[a], "-h") == 0 || strcmp(argv[a], "--help") == 0)
|
||||||
{
|
{
|
||||||
@ -243,44 +256,71 @@ bool option_parse(int argc, char * argv[])
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strlen(argv[a]) != 2)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Ignored invalid argvument: %s", argv[a]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < state.oCount; ++i)
|
||||||
|
{
|
||||||
|
if (state.options[i]->shortopt == argv[a][1])
|
||||||
|
{
|
||||||
|
o = state.options[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o->type != OPTION_TYPE_BOOL && a < argc - 1)
|
||||||
|
{
|
||||||
|
++a;
|
||||||
|
value = strdup(argv[a]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
char * arg = strdup(argv[a]);
|
char * arg = strdup(argv[a]);
|
||||||
char * module = strtok(arg , ":");
|
char * module = strtok(arg , ":");
|
||||||
char * name = strtok(NULL, "=");
|
char * name = strtok(NULL, "=");
|
||||||
char * value = strtok(NULL, "" );
|
value = strtok(NULL, "" );
|
||||||
|
|
||||||
if (!module || !name || !value)
|
if (!module || !name)
|
||||||
{
|
{
|
||||||
DEBUG_WARN("Ignored invalid argument: %s", argv[a]);
|
DEBUG_WARN("Ignored invalid argument: %s", argv[a]);
|
||||||
free(arg);
|
free(arg);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool found = false;
|
o = option_get(module, name);
|
||||||
struct Option * o;
|
if (value)
|
||||||
for(int i = 0; i < state.oCount; ++i)
|
value = strdup(value);
|
||||||
{
|
|
||||||
o = state.options[i];
|
|
||||||
if ((strcmp(o->module, module) != 0) || (strcmp(o->name, name) != 0))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
found = true;
|
free(arg);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
if (!value)
|
||||||
|
{
|
||||||
|
if (o->type == OPTION_TYPE_BOOL)
|
||||||
|
{
|
||||||
|
option_set(o, "yes");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (o->type != OPTION_TYPE_CUSTOM)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Ignored invalid argument, missing value: %s", argv[a]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!o)
|
||||||
{
|
{
|
||||||
DEBUG_WARN("Ignored unknown argument: %s", argv[a]);
|
DEBUG_WARN("Ignored unknown argument: %s", argv[a]);
|
||||||
free(arg);
|
free(value);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!option_set(o, value))
|
option_set(o, value);
|
||||||
{
|
free(value);
|
||||||
free(arg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -510,13 +550,108 @@ void option_print()
|
|||||||
|
|
||||||
for(int g = 0; g < state.gCount; ++g)
|
for(int g = 0; g < state.gCount; ++g)
|
||||||
{
|
{
|
||||||
|
StringList lines = stringlist_new(true);
|
||||||
|
StringList values = stringlist_new(true);
|
||||||
|
int len;
|
||||||
|
int maxLen;
|
||||||
|
int valueLen = 5;
|
||||||
|
char * line;
|
||||||
|
|
||||||
|
// ensure the pad length is atleast as wide as the heading
|
||||||
|
if (state.groups[g].pad < 4)
|
||||||
|
state.groups[g].pad = 4;
|
||||||
|
|
||||||
|
// get the values and the max value length
|
||||||
for(int i = 0; i < state.groups[g].count; ++i)
|
for(int i = 0; i < state.groups[g].count; ++i)
|
||||||
{
|
{
|
||||||
struct Option * o = state.groups[g].options[i];
|
struct Option * o = state.groups[g].options[i];
|
||||||
char * value = o->toString(o);
|
char * value = o->toString(o);
|
||||||
printf(" %s:%-*s - %s [%s]\n", o->module, state.groups[g].pad, o->name, o->description, value);
|
if (!value)
|
||||||
free(value);
|
{
|
||||||
|
value = strdup("NULL");
|
||||||
|
len = 4;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
len = strlen(value);
|
||||||
|
|
||||||
|
if (len > valueLen)
|
||||||
|
valueLen = len;
|
||||||
|
|
||||||
|
stringlist_push(values, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the heading
|
||||||
|
maxLen = alloc_sprintf(
|
||||||
|
&line,
|
||||||
|
"%-*s | Short | %-*s | Description",
|
||||||
|
state.groups[g].pad + 4,
|
||||||
|
"Long",
|
||||||
|
valueLen,
|
||||||
|
"Value"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(maxLen > 0);
|
||||||
|
stringlist_push(lines, line);
|
||||||
|
|
||||||
|
for(int i = 0; i < state.groups[g].count; ++i)
|
||||||
|
{
|
||||||
|
struct Option * o = state.groups[g].options[i];
|
||||||
|
char * value = stringlist_at(values, i);
|
||||||
|
|
||||||
|
len = alloc_sprintf(
|
||||||
|
&line,
|
||||||
|
"%s:%-*s | %c%c | %-*s | %s",
|
||||||
|
o->module,
|
||||||
|
state.groups[g].pad,
|
||||||
|
o->name,
|
||||||
|
o->shortopt ? '-' : ' ',
|
||||||
|
o->shortopt ? o->shortopt : ' ',
|
||||||
|
valueLen,
|
||||||
|
value,
|
||||||
|
o->description
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(len > 0);
|
||||||
|
stringlist_push(lines, line);
|
||||||
|
if (len > maxLen)
|
||||||
|
maxLen = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
stringlist_free(&values);
|
||||||
|
|
||||||
|
// print out the lines
|
||||||
|
for(int i = 0; i < stringlist_count(lines); ++i)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
// print a horizontal rule
|
||||||
|
printf(" |");
|
||||||
|
for(int i = 0; i < maxLen + 2; ++i)
|
||||||
|
putc('-', stdout);
|
||||||
|
printf("|\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
char * line = stringlist_at(lines, i);
|
||||||
|
printf(" | %-*s |\n", maxLen, line);
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
// print a horizontal rule
|
||||||
|
printf(" |");
|
||||||
|
for(int i = 0; i < maxLen + 2; ++i)
|
||||||
|
putc('-', stdout);
|
||||||
|
printf("|\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print a horizontal rule
|
||||||
|
printf(" |");
|
||||||
|
for(int i = 0; i < maxLen + 2; ++i)
|
||||||
|
putc('-', stdout);
|
||||||
|
printf("|\n");
|
||||||
|
|
||||||
|
stringlist_free(&lines);
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user