diff --git a/include/ctl-client.h b/include/ctl-client.h index 4a26873c..fd9c72ea 100644 --- a/include/ctl-client.h +++ b/include/ctl-client.h @@ -26,6 +26,7 @@ struct ctl_client* ctl_client_new(const char* socket_path, void* userdata); void ctl_client_destroy(struct ctl_client*); void* ctl_client_userdata(struct ctl_client*); +#define PRINT_JSON 0x00000001 int ctl_client_run_command(struct ctl_client* self, - int argc, char* argv[]); + int argc, char* argv[], unsigned flags); diff --git a/src/ctl-client.c b/src/ctl-client.c index d74159f0..6f036bf6 100644 --- a/src/ctl-client.c +++ b/src/ctl-client.c @@ -245,20 +245,104 @@ static struct jsonipc_response* ctl_client_wait_for_response(struct ctl_client* return response; } +static void print_error(struct jsonipc_response* response, const char* method) +{ + printf("Error (%d)", response->code); + if (!response->data) + goto out; + json_t* data = response->data; + if (json_is_string(data)) + printf(": %s", json_string_value(data)); + else if (json_is_object(data) && + json_is_string(json_object_get(data, "error"))) + printf(": %s", json_string_value(json_object_get(data, "error"))); + else + json_dumpf(response->data, stdout, JSON_INDENT(2)); +out: + printf("\n"); +} + +static void print_help(json_t* data) +{ + if (json_object_get(data, "commands")) { + printf("Allowed commands:\n"); + json_t* cmd_list = json_object_get(data, "commands"); + size_t index; + json_t *value; + + json_array_foreach(cmd_list, index, value) { + printf(" - %s\n", json_string_value(value)); + } + printf("\nRun 'wayvncctl command-name --help' for command-specific details.\n"); + return; + } + const char *key; + json_t *value; + + json_object_foreach(data, key, value) { + char *desc = NULL; + json_t* params = NULL; + json_unpack(value, "{s:s, s?o}", "description", &desc, + "params", ¶ms); + 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)); + } + } + } +} + +static void pretty_version(json_t* data) +{ + printf("wayvnc is running:\n"); + const char *key; + json_t *value; + json_object_foreach(data, key, value) + printf(" %s: %s\n", key, json_string_value(value)); +} + +static void pretty_print(json_t* data, const char* method) +{ + if (strcmp(method, "help") == 0) + print_help(data); + else if (strcmp(method, "version") == 0) + pretty_version(data); + else + json_dumpf(data, stdout, JSON_INDENT(2)); +} + +static void print_compact_json(json_t* data) +{ + json_dumpf(data, stdout, JSON_COMPACT); + printf("\n"); +} + static int ctl_client_print_response(struct ctl_client* self, - struct jsonipc_response* response) + struct jsonipc_request* request, + struct jsonipc_response* response, + unsigned flags) { DEBUG("Response code: %d", response->code); if (response->data) { - char* data = json_dumps(response->data, JSON_INDENT(4)); - printf("%s\n", data); - free(data); + if (flags & PRINT_JSON) + print_compact_json(response->data); + else if (response->code == 0) + pretty_print(response->data, request->method); + else + print_error(response, request->method); } return response->code; } int ctl_client_run_command(struct ctl_client* self, - int argc, char* argv[]) + int argc, char* argv[], unsigned flags) { int result = -1; struct jsonipc_request* request = ctl_client_parse_args(self, argc, argv); @@ -272,7 +356,7 @@ int ctl_client_run_command(struct ctl_client* self, if (!response) goto receive_failure; - result = ctl_client_print_response(self, response); + result = ctl_client_print_response(self, request, response, flags); jsonipc_response_destroy(response); receive_failure: diff --git a/src/wayvncctl.c b/src/wayvncctl.c index e7f75619..12cfecf6 100644 --- a/src/wayvncctl.c +++ b/src/wayvncctl.c @@ -51,6 +51,7 @@ static int wayvncctl_usage(FILE* stream, int rc) "Try the \"help\" command for a list of available commands.\n" "\n" " -S,--socket= Wayvnc control socket path.\n" +" -j,--json Output json on stdout.\n" " Default: $XDG_RUNTIME_DIR/wayvncctl\n" " -V,--version Show version info.\n" " -v,--verbose Be more verbose.\n" @@ -72,13 +73,16 @@ int main(int argc, char* argv[]) { struct wayvncctl self = { 0 }; - static const char* shortopts = "+S:hVv"; + static const char* shortopts = "+S:hVvj"; bool verbose = false; const char* socket_path = NULL; + unsigned flags = 0; + static const struct option longopts[] = { { "socket", required_argument, NULL, 'S' }, + { "json", no_argument, NULL, 'j' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { "verbose", no_argument, NULL, 'v' }, @@ -94,6 +98,9 @@ int main(int argc, char* argv[]) case 'S': socket_path = optarg; break; + case 'j': + flags |= PRINT_JSON; + break; case 'v': verbose = true; break; @@ -113,7 +120,7 @@ int main(int argc, char* argv[]) if (!self.ctl) goto ctl_client_failure; - int result = ctl_client_run_command(self.ctl, argc, argv); + int result = ctl_client_run_command(self.ctl, argc, argv, flags); ctl_client_destroy(self.ctl); diff --git a/wayvncctl.scd b/wayvncctl.scd index c2d20d7a..d00ac3b6 100644 --- a/wayvncctl.scd +++ b/wayvncctl.scd @@ -14,6 +14,9 @@ wayvncctl - A control client for wayvnc(1) Set wayvnc control socket path. Default: $XDG_RUNTIME_DIR/wayvncctl or /tmp/wayvncctl-$UID +*-j, --json* + Produce json output to stdout. + *-V, --version* Show version info. @@ -38,30 +41,25 @@ Query the server for all available command names: ``` $ wayvncctl help -{ - "commands": [ - "help", - "version", - "set-output", - ... - ] -} +Allowed commands: + - help + - version + - set-output + +Run 'wayvncctl command-name --help' for command-specific details. ``` Get help on the "help" command: ``` -$ wayvncctl help --command help -{ - "help": { - "description": "List all commands, or show usage of a specific command", - "params": [ - { - "command": "The command to show (optional)" - } - ] - } -} +$ wayvncctl help --help +Usage: wayvncctl [options] help [params] + +List all commands, or show usage of a specific command + +Parameters: + --command=... + The command to show (optional) ``` Cycle to the next active output: