Added event help text

Signed-off-by: Jim Ramsay <i.am@jimramsay.com>
pull/183/head
Jim Ramsay 2022-11-08 07:32:04 -05:00 committed by Andri Yngvason
parent c75b64eae8
commit debd8a67cb
2 changed files with 143 additions and 40 deletions

View File

@ -263,41 +263,76 @@ out:
printf("\n"); printf("\n");
} }
static void print_help(json_t* data) static void print_command_usage(const char* name, json_t* data)
{
char* desc = NULL;
json_t* params = NULL;
json_unpack(data, "{s:s, s?o}", "description", &desc,
"params", &params);
printf("Usage: wayvncctl [options] %s%s\n\n%s\n", name,
params ? " [params]" : "",
desc);
if (params) {
printf("\nParameters:");
const char* param_name;
json_t* param_value;
json_object_foreach(params, param_name, param_value) {
printf("\n --%s=...\n %s\n", param_name,
json_string_value(param_value));
}
}
printf("\nRun 'wayvncctl --help' for allowed Options\n");
}
static void print_event_details(const char* name, json_t* data)
{
char* desc = NULL;
json_t* params = NULL;
json_unpack(data, "{s:s, s?o}", "description", &desc,
"params", &params);
printf("Event: %s\n\n%s\n", name,
desc);
if (params) {
printf("\nParameters:");
const char* param_name;
json_t* param_value;
json_object_foreach(params, param_name, param_value) {
printf("\n %s:...\n %s\n", param_name,
json_string_value(param_value));
}
}
}
static void print_help(json_t* data, json_t* request)
{ {
if (json_object_get(data, "commands")) { if (json_object_get(data, "commands")) {
printf("Allowed commands:\n"); printf("Allowed commands:\n");
json_t* cmd_list = json_object_get(data, "commands"); json_t* cmd_list = json_object_get(data, "commands");
size_t index; size_t index;
json_t* value; json_t* value;
json_array_foreach(cmd_list, index, value) { json_array_foreach(cmd_list, index, value) {
printf(" - %s\n", json_string_value(value)); printf(" - %s\n", json_string_value(value));
} }
printf("\nRun 'wayvncctl command-name --help' for command-specific details.\n"); printf("\nRun 'wayvncctl command-name --help' for command-specific details.\n");
printf("\nSupported events:\n");
json_t* evt_list = json_object_get(data, "events");
json_array_foreach(evt_list, index, value) {
printf(" - %s\n", json_string_value(value));
}
printf("\nRun 'wayvncctl help --event=event-name' for event-specific details.\n");
return; return;
} }
bool is_command = json_object_get(request, "command");
const char* key; const char* key;
json_t* value; json_t* value;
json_object_foreach(data, key, value) { json_object_foreach(data, key, value) {
char* desc = NULL; if (is_command)
json_t* params = NULL; print_command_usage(key, value);
json_unpack(value, "{s:s, s?o}", "description", &desc, else
"params", &params); print_event_details(key, value);
printf("Usage: wayvncctl [options] %s%s\n\n%s\n", key,
params ? " [params]" : "",
desc);
if (params) {
printf("\nParameters:");
const char* param_name;
json_t* param_value;
json_object_foreach(params, param_name, param_value) {
printf("\n --%s=...\n %s\n", param_name,
json_string_value(param_value));
}
}
printf("\nRun 'wayvncctl --help' for allowed Options\n");
} }
} }
@ -310,10 +345,12 @@ static void pretty_version(json_t* data)
printf(" %s: %s\n", key, json_string_value(value)); printf(" %s: %s\n", key, json_string_value(value));
} }
static void pretty_print(json_t* data, const char* method) static void pretty_print(json_t* data,
struct jsonipc_request* request)
{ {
const char* method = request->method;
if (strcmp(method, "help") == 0) if (strcmp(method, "help") == 0)
print_help(data); print_help(data, request->params);
else if (strcmp(method, "version") == 0) else if (strcmp(method, "version") == 0)
pretty_version(data); pretty_version(data);
else else
@ -336,7 +373,7 @@ static int ctl_client_print_response(struct ctl_client* self,
if (flags & PRINT_JSON) if (flags & PRINT_JSON)
print_compact_json(response->data); print_compact_json(response->data);
else if (response->code == 0) else if (response->code == 0)
pretty_print(response->data, request->method); pretty_print(response->data, request);
else else
print_error(response, request->method); print_error(response, request->method);
} }

View File

@ -47,6 +47,14 @@ enum cmd_type {
CMD_SET_OUTPUT, CMD_SET_OUTPUT,
CMD_UNKNOWN, CMD_UNKNOWN,
}; };
#define CMD_LIST_LEN CMD_UNKNOWN
enum event_type {
EVT_CLIENT_CONNECTED,
EVT_CLIENT_DISCONNECTED,
EVT_UNKNOWN,
};
#define EVT_LIST_LEN EVT_UNKNOWN
struct cmd_param_info { struct cmd_param_info {
char* name; char* name;
@ -61,9 +69,10 @@ struct cmd_info {
static struct cmd_info cmd_list[] = { static struct cmd_info cmd_list[] = {
[CMD_HELP] = { "help", [CMD_HELP] = { "help",
"List all commands, or show usage of a specific command", "List all commands and events, or show usage of a specific command or event",
{ {
{"command", "The command to show (optional)"}, {"command", "The command to show (optional)"},
{"event", "The event to show (optional)"},
{NULL, NULL}, {NULL, NULL},
} }
}, },
@ -86,13 +95,32 @@ static struct cmd_info cmd_list[] = {
}, },
}; };
#define CLIENT_EVENT_PARAMS(including) \
{"id", "A unique identifier for this client"}, \
{"connection_count", "The total number of connected VNC clients " including " this one."}, \
{"hostname", "The hostname or IP address of this client (may be null)"}, \
{"username", "The username used to authentice this client (may be null)."}, \
{NULL, NULL},
static struct cmd_info evt_list[] = {
[EVT_CLIENT_CONNECTED] = {"client-connected",
"Sent when a new vnc client connects to wayvnc",
{ CLIENT_EVENT_PARAMS("including") }
},
[EVT_CLIENT_DISCONNECTED] = {"client-disconnected",
"Sent when a vnc client disconnects from wayvnc",
{ CLIENT_EVENT_PARAMS("not including") }
},
};
struct cmd { struct cmd {
enum cmd_type type; enum cmd_type type;
}; };
struct cmd_help { struct cmd_help {
struct cmd cmd; struct cmd cmd;
char command[64]; char id[64];
bool id_is_command;
}; };
struct cmd_set_output { struct cmd_set_output {
@ -147,7 +175,7 @@ static enum cmd_type parse_command_name(const char* name)
{ {
if (!name || name[0] == '\0') if (!name || name[0] == '\0')
return CMD_UNKNOWN; return CMD_UNKNOWN;
for (int i = 0; i < CMD_UNKNOWN; ++i) { for (int i = 0; i < CMD_LIST_LEN; ++i) {
if (strcmp(name, cmd_list[i].name) == 0) { if (strcmp(name, cmd_list[i].name) == 0) {
return i; return i;
} }
@ -159,15 +187,28 @@ static struct cmd_help* cmd_help_new(json_t* args,
struct jsonipc_error* err) struct jsonipc_error* err)
{ {
const char* command = NULL; const char* command = NULL;
if (args && json_unpack(args, "{s?s}", "command", &command) == -1) { const char* event = NULL;
if (args && json_unpack(args, "{s?s, s?s}",
"command", &command,
"event", &event) == -1) {
jsonipc_error_printf(err, EINVAL, jsonipc_error_printf(err, EINVAL,
"expecting \"command\" (optional)"); "expecting \"command\" or \"event\" (optional)");
return NULL;
}
if (command && event) {
jsonipc_error_printf(err, EINVAL,
"expecting exacly one of \"command\" or \"event\"");
return NULL; return NULL;
} }
struct cmd_help* cmd = calloc(1, sizeof(*cmd)); struct cmd_help* cmd = calloc(1, sizeof(*cmd));
cmd->cmd.type = CMD_HELP; cmd->cmd.type = CMD_HELP;
if (command) if (command) {
strlcpy(cmd->command, command, sizeof(cmd->command)); strlcpy(cmd->id, command, sizeof(cmd->id));
cmd->id_is_command = true;
} else if (event) {
strlcpy(cmd->id, event, sizeof(cmd->id));
cmd->id_is_command = false;
}
return cmd; return cmd;
} }
@ -207,14 +248,25 @@ static struct cmd_set_output* cmd_set_output_new(json_t* args,
return cmd; return cmd;
} }
static json_t* list_allowed_commands() static json_t* list_allowed(struct cmd_info (*list)[], size_t len)
{ {
json_t* allowed = json_array(); json_t* allowed = json_array();
for (int i = 0; i < CMD_UNKNOWN; ++i) for (int i = 0; i < len; ++i) {
json_array_append_new(allowed, json_string(cmd_list[i].name)); json_array_append_new(allowed, json_string((*list)[i].name));
}
return allowed; return allowed;
} }
static json_t* list_allowed_commands()
{
return list_allowed(&cmd_list, CMD_LIST_LEN);
}
static json_t* list_allowed_events()
{
return list_allowed(&evt_list, EVT_LIST_LEN);
}
static struct cmd* parse_command(struct jsonipc_request* ipc, static struct cmd* parse_command(struct jsonipc_request* ipc,
struct jsonipc_error* err) struct jsonipc_error* err)
{ {
@ -316,14 +368,28 @@ static json_t* client_next_object(struct ctl_client* self, struct cmd_response**
return root; return root;
} }
static struct cmd_response* generate_help_object(const char* cmd) static struct cmd_info* find_info(const char* id, struct cmd_info (*list)[],
size_t len)
{ {
enum cmd_type ctype = parse_command_name(cmd); for (int i = 0; i < len; ++i) {
struct cmd_info* info = &(*list)[i];
if (strcmp(info->name, id) == 0)
return info;
}
return NULL;
}
static struct cmd_response* generate_help_object(const char* id, bool id_is_command)
{
struct cmd_info* info = id_is_command ?
find_info(id, &cmd_list, CMD_LIST_LEN) :
find_info(id, &evt_list, EVT_LIST_LEN);
json_t* data; json_t* data;
if (ctype == CMD_UNKNOWN) { if (!info) {
data = json_pack("{s:o}", "commands", list_allowed_commands()); data = json_pack("{s:o, s:o}",
"commands", list_allowed_commands(),
"events", list_allowed_events());
} else { } else {
struct cmd_info* info = &cmd_list[ctype];
json_t* param_list = NULL; json_t* param_list = NULL;
if (info->params[0].name) { if (info->params[0].name) {
param_list = json_object(); param_list = json_object();
@ -362,7 +428,7 @@ static struct cmd_response* ctl_server_dispatch_cmd(struct ctl* self,
switch (cmd->type) { switch (cmd->type) {
case CMD_HELP:{ case CMD_HELP:{
struct cmd_help* c = (struct cmd_help*)cmd; struct cmd_help* c = (struct cmd_help*)cmd;
response = generate_help_object(c->command); response = generate_help_object(c->id, c->id_is_command);
break; break;
} }
case CMD_SET_OUTPUT: { case CMD_SET_OUTPUT: {
@ -799,7 +865,7 @@ int ctl_server_enqueue_event(struct ctl* self, const char* event_name,
return enqueued; return enqueued;
} }
void ctl_server_event_connect(struct ctl* self, static void ctl_server_event_connect(struct ctl* self,
bool connected, bool connected,
const char* client_id, const char* client_id,
const char* client_hostname, const char* client_hostname,