Add option_parser_print_usage
Signed-off-by: Jim Ramsay <i.am@jimramsay.com>wayvncctl-polishing
parent
dcb23ebfe1
commit
104040291b
|
@ -50,11 +50,16 @@ struct option_parser {
|
|||
void option_parser_init(struct option_parser* self,
|
||||
const struct wv_option* options);
|
||||
|
||||
void option_parser_print_usage(struct option_parser* self, FILE* stream);
|
||||
|
||||
int option_parser_print_arguments(struct option_parser* self, FILE* stream);
|
||||
|
||||
void option_parser_print_options(struct option_parser* self, FILE* stream);
|
||||
|
||||
int option_parser_parse(struct option_parser* self, int argc,
|
||||
const char* const* argv);
|
||||
|
||||
const char* option_parser_get_value(const struct option_parser* self,
|
||||
const char* name);
|
||||
const char* option_parser_get_value_no_default(const struct option_parser* self,
|
||||
const char* name);
|
||||
|
|
|
@ -738,12 +738,9 @@ static int print_command_usage(struct ctl_client* self,
|
|||
WARN("No such command");
|
||||
return 1;
|
||||
}
|
||||
printf("Usage: wayvncctl [options] %s ", info->name);
|
||||
for (int i = 0; i < cmd_options->n_opts; ++i)
|
||||
if (cmd_options->options[i].positional)
|
||||
printf("<%s> ", cmd_options->options[i].positional);
|
||||
|
||||
printf("[parameters]\n\n");
|
||||
printf("Usage: wayvncctl [options] %s", info->name);
|
||||
option_parser_print_usage(cmd_options, stdout);
|
||||
printf("\n\n");
|
||||
table_printer_indent_and_reflow_text(stdout, info->description, 80, 0, 0);
|
||||
printf("\n");
|
||||
if (option_parser_print_arguments(cmd_options, stdout))
|
||||
|
|
30
src/main.c
30
src/main.c
|
@ -66,6 +66,9 @@
|
|||
#define DEFAULT_ADDRESS "127.0.0.1"
|
||||
#define DEFAULT_PORT 5900
|
||||
|
||||
#define XSTR(x) STR(x)
|
||||
#define STR(x) #x
|
||||
|
||||
#define MAYBE_UNUSED __attribute__((unused))
|
||||
|
||||
struct wayvnc {
|
||||
|
@ -907,15 +910,14 @@ void on_capture_done(struct screencopy* sc)
|
|||
|
||||
int wayvnc_usage(struct option_parser* parser, FILE* stream, int rc)
|
||||
{
|
||||
static const char* usage =
|
||||
"Usage: wayvnc [options] [<address> [<port>]]\n"
|
||||
"\n"
|
||||
"Starts a VNC server for $WAYLAND_DISPLAY";
|
||||
fprintf(stream, "%s\n\n", usage);
|
||||
fputs("Usage: wayvnc", stream);
|
||||
option_parser_print_usage(parser, stream);
|
||||
fputs("\n\n", stream);
|
||||
fprintf(stream, "Starts a VNC server for $WAYLAND_DISPLAY\n\n");
|
||||
if (option_parser_print_arguments(parser, stream))
|
||||
fprintf(stream, "\n");
|
||||
fputc('\n', stream);
|
||||
option_parser_print_options(parser, stream);
|
||||
fprintf(stream, "\n");
|
||||
fputc('\n', stream);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1270,9 +1272,11 @@ int main(int argc, char* argv[])
|
|||
|
||||
static const struct wv_option opts[] = {
|
||||
{ .positional = "address",
|
||||
.help = "The IP address or unix socket path to listen on. Default: 127.0.0.1" },
|
||||
.help = "The IP address or unix socket path to listen on.",
|
||||
.default_ = DEFAULT_ADDRESS},
|
||||
{ .positional = "port",
|
||||
.help = "The TCP port to listen on. Default: 5900" },
|
||||
.help = "The TCP port to listen on.",
|
||||
.default_ = XSTR(DEFAULT_PORT)},
|
||||
{ 'C', "config", "<path>",
|
||||
"Select a config file." },
|
||||
{ 'g', "gpu", NULL,
|
||||
|
@ -1305,7 +1309,7 @@ int main(int argc, char* argv[])
|
|||
.default_ = "warning" },
|
||||
{ 'h', "help", NULL,
|
||||
"Get help (this text)." },
|
||||
{ '\0', NULL, NULL, NULL }
|
||||
{}
|
||||
};
|
||||
|
||||
struct option_parser option_parser;
|
||||
|
@ -1344,8 +1348,10 @@ int main(int argc, char* argv[])
|
|||
|
||||
nvnc_set_log_level(log_level);
|
||||
|
||||
address = option_parser_get_value(&option_parser, "address");
|
||||
const char* port_str = option_parser_get_value(&option_parser, "port");
|
||||
// Only check for explicitly-set values here (defaults applied below)
|
||||
address = option_parser_get_value_no_default(&option_parser, "address");
|
||||
const char* port_str = option_parser_get_value_no_default(&option_parser,
|
||||
"port");
|
||||
if (port_str)
|
||||
port = atoi(port_str);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <sys/param.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
|
@ -105,6 +106,39 @@ void option_parser_print_options(struct option_parser* self, FILE* stream)
|
|||
format_option(&printer, &self->options[i]);
|
||||
}
|
||||
|
||||
static void print_string_tolower(FILE* stream, const char *src)
|
||||
{
|
||||
for (const char* c = src; *c != '\0'; c++)
|
||||
fprintf(stream, "%c", tolower(*c));
|
||||
}
|
||||
|
||||
void option_parser_print_usage(struct option_parser* self, FILE* stream)
|
||||
{
|
||||
fprintf(stream, " [");
|
||||
print_string_tolower(stream, self->name);
|
||||
fprintf(stream, "]");
|
||||
int optional_paren_count = 0;
|
||||
for (int i = 0; i < self->n_opts; ++i) {
|
||||
const struct wv_option* opt = &self->options[i];
|
||||
if (!opt->positional)
|
||||
continue;
|
||||
const char* open = "<";
|
||||
const char* close = ">";
|
||||
if (opt->default_) {
|
||||
open = "[";
|
||||
close = ""; // Closed via optional_paren_count loop below
|
||||
optional_paren_count++;
|
||||
} else {
|
||||
// Enforce there must be NO non-optional args after
|
||||
// we've processed at least one optional arg
|
||||
assert(optional_paren_count == 0);
|
||||
}
|
||||
fprintf(stream, " %s%s%s", open, opt->positional, close);
|
||||
}
|
||||
for (int i = 0; i < optional_paren_count; ++i)
|
||||
fprintf(stream, "]");
|
||||
}
|
||||
|
||||
int option_parser_print_arguments(struct option_parser* self, FILE* stream)
|
||||
{
|
||||
size_t max_arg = 0;
|
||||
|
@ -168,6 +202,19 @@ static const struct wv_option* find_positional_option(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const struct wv_option* find_positional_option_by_name(
|
||||
const struct option_parser* self, const char*name)
|
||||
{
|
||||
for (int i = 0; i < self->n_opts; ++i) {
|
||||
const struct wv_option* opt = &self->options[i];
|
||||
if (!opt->positional)
|
||||
continue;
|
||||
if (strcmp(opt->positional, name) == 0)
|
||||
return opt;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int append_value(struct option_parser* self,
|
||||
const struct wv_option* option, const char* value)
|
||||
{
|
||||
|
@ -317,7 +364,7 @@ int option_parser_parse(struct option_parser* self, int argc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
const char* option_parser_get_value(const struct option_parser* self,
|
||||
const char* option_parser_get_value_no_default(const struct option_parser* self,
|
||||
const char* name)
|
||||
{
|
||||
const struct wv_option* opt;
|
||||
|
@ -340,6 +387,18 @@ const char* option_parser_get_value(const struct option_parser* self,
|
|||
return value->value;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* option_parser_get_value(const struct option_parser* self,
|
||||
const char* name)
|
||||
{
|
||||
const char* value = option_parser_get_value_no_default(self, name);
|
||||
if (value)
|
||||
return value;
|
||||
|
||||
bool is_short = name[0] && !name[1];
|
||||
const struct wv_option* opt;
|
||||
if (is_short) {
|
||||
opt = find_short_option(self, name[0]);
|
||||
if (opt)
|
||||
|
@ -348,9 +407,10 @@ const char* option_parser_get_value(const struct option_parser* self,
|
|||
opt = find_long_option(self, name);
|
||||
if (opt)
|
||||
return opt->default_;
|
||||
opt = find_positional_option_by_name(self, name);
|
||||
if (opt)
|
||||
return opt->default_;
|
||||
}
|
||||
|
||||
// TODO: Add positional option?
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -43,13 +43,12 @@ struct wayvncctl {
|
|||
|
||||
static int wayvncctl_usage(FILE* stream, struct option_parser* options, int rc)
|
||||
{
|
||||
static const char* usage =
|
||||
"Usage: wayvncctl [options] <command> [parameters]\n"
|
||||
"\n"
|
||||
"Connects to and interacts with a running wayvnc instance.";
|
||||
fprintf(stream, "%s\n\n", usage);
|
||||
fputs("Usage: wayvncctl", stream);
|
||||
option_parser_print_usage(options, stream);
|
||||
fputs(" [parameters]\n\n", stream);
|
||||
fputs("Connects to and interacts with a running wayvnc instance.\n\n", stream);
|
||||
option_parser_print_options(options, stream);
|
||||
fprintf(stream, "\n");
|
||||
fputc('\n', stream);
|
||||
ctl_client_print_command_list(stream);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,13 @@ static const struct wv_option options[] = {
|
|||
{ },
|
||||
};
|
||||
|
||||
static const struct wv_option default_options[] = {
|
||||
{ .positional = "first" },
|
||||
{ .positional = "second", .default_ = "second_default" },
|
||||
{ 'v', "value-option", "value", "Description of v", .default_ = "v_default" },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int test_simple(void)
|
||||
{
|
||||
struct option_parser parser;
|
||||
|
@ -227,6 +234,61 @@ static int test_subcommand_with_arguments(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int test_defaults_not_set(void)
|
||||
{
|
||||
struct option_parser parser;
|
||||
option_parser_init(&parser, default_options);
|
||||
const char* argv[] = {
|
||||
"executable",
|
||||
"pos 1",
|
||||
};
|
||||
|
||||
ASSERT_INT_EQ(0, option_parser_parse(&parser, ARRAY_SIZE(argv), argv));
|
||||
ASSERT_STR_EQ("pos 1", option_parser_get_value(&parser, "first"));
|
||||
|
||||
ASSERT_STR_EQ("second_default", option_parser_get_value(&parser, "second"));
|
||||
ASSERT_FALSE(option_parser_get_value_no_default(&parser, "second"));
|
||||
|
||||
ASSERT_STR_EQ("v_default", option_parser_get_value(&parser, "value-option"));
|
||||
ASSERT_FALSE(option_parser_get_value_no_default(&parser, "value-option"));
|
||||
ASSERT_STR_EQ("v_default", option_parser_get_value(&parser, "v"));
|
||||
ASSERT_FALSE(option_parser_get_value_no_default(&parser, "v"));
|
||||
|
||||
ASSERT_INT_EQ(0, parser.remaining_argc);
|
||||
ASSERT_FALSE(parser.remaining_argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_defaults_overridden(void)
|
||||
{
|
||||
struct option_parser parser;
|
||||
option_parser_init(&parser, default_options);
|
||||
const char* argv[] = {
|
||||
"executable",
|
||||
"pos 1",
|
||||
"pos 2",
|
||||
"-v",
|
||||
"v_set",
|
||||
};
|
||||
|
||||
ASSERT_INT_EQ(0, option_parser_parse(&parser, ARRAY_SIZE(argv), argv));
|
||||
ASSERT_STR_EQ("pos 1", option_parser_get_value(&parser, "first"));
|
||||
|
||||
ASSERT_STR_EQ("pos 2", option_parser_get_value(&parser, "second"));
|
||||
ASSERT_STR_EQ("pos 2", option_parser_get_value_no_default(&parser, "second"));
|
||||
|
||||
ASSERT_STR_EQ("v_set", option_parser_get_value(&parser, "value-option"));
|
||||
ASSERT_STR_EQ("v_set", option_parser_get_value_no_default(&parser, "value-option"));
|
||||
ASSERT_STR_EQ("v_set", option_parser_get_value(&parser, "v"));
|
||||
ASSERT_STR_EQ("v_set", option_parser_get_value_no_default(&parser, "v"));
|
||||
|
||||
ASSERT_INT_EQ(0, parser.remaining_argc);
|
||||
ASSERT_FALSE(parser.remaining_argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int r = 0;
|
||||
|
@ -246,5 +308,7 @@ int main()
|
|||
RUN_TEST(test_missing_long_value);
|
||||
RUN_TEST(test_subcommand_without_arguments);
|
||||
RUN_TEST(test_subcommand_with_arguments);
|
||||
RUN_TEST(test_defaults_not_set);
|
||||
RUN_TEST(test_defaults_overridden);
|
||||
return r;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue