diff options
-rw-r--r-- | include/sway/commands.h | 6 | ||||
-rw-r--r-- | include/swaynag/swaynag.h | 1 | ||||
-rw-r--r-- | sway/commands.c | 68 | ||||
-rw-r--r-- | sway/commands/bind.c | 21 | ||||
-rw-r--r-- | sway/ipc-server.c | 11 | ||||
-rw-r--r-- | sway/main.c | 13 | ||||
-rw-r--r-- | sway/tree/view.c | 9 | ||||
-rw-r--r-- | swaynag/config.c | 10 | ||||
-rw-r--r-- | swaynag/swaynag.1.scd | 9 | ||||
-rw-r--r-- | swaynag/swaynag.c | 7 |
10 files changed, 92 insertions, 63 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index eb446eae..c3913c79 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -56,7 +56,7 @@ struct cmd_handler *find_handler(char *line, struct cmd_handler *cmd_handlers, * all matching containers. Otherwise, it'll run on the `con` container. If * `con` is NULL then it'll run on the currently focused container. */ -struct cmd_results *execute_command(char *command, struct sway_seat *seat, +list_t *execute_command(char *command, struct sway_seat *seat, struct sway_container *con); /** * Parse and handles a command during config file loading. @@ -82,11 +82,11 @@ struct cmd_results *cmd_results_new(enum cmd_status status, const char* input, c */ void free_cmd_results(struct cmd_results *results); /** - * Serializes cmd_results to a JSON string. + * Serializes a list of cmd_results to a JSON string. * * Free the JSON string later on. */ -char *cmd_results_to_json(struct cmd_results *results); +char *cmd_results_to_json(list_t *res_list); struct cmd_results *add_color(const char *name, char *buffer, const char *color); diff --git a/include/swaynag/swaynag.h b/include/swaynag/swaynag.h index a32d1503..0fd1eb50 100644 --- a/include/swaynag/swaynag.h +++ b/include/swaynag/swaynag.h @@ -44,6 +44,7 @@ struct swaynag_button { int y; int width; int height; + bool terminal; }; struct swaynag_details { diff --git a/sway/commands.c b/sway/commands.c index bffc18f6..1203f63a 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -215,12 +215,9 @@ static void set_config_node(struct sway_node *node) { } } -struct cmd_results *execute_command(char *_exec, struct sway_seat *seat, +list_t *execute_command(char *_exec, struct sway_seat *seat, struct sway_container *con) { - // Even though this function will process multiple commands we will only - // return the last error, if any (for now). (Since we have access to an - // error string we could e.g. concatenate all errors there.) - struct cmd_results *results = NULL; + list_t *res_list = create_list(); char *exec = strdup(_exec); char *head = exec; char *cmdlist; @@ -254,8 +251,8 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat, char *error = NULL; struct criteria *criteria = criteria_parse(head, &error); if (!criteria) { - results = cmd_results_new(CMD_INVALID, head, - "%s", error); + list_add(res_list, cmd_results_new(CMD_INVALID, head, + "%s", error)); free(error); goto cleanup; } @@ -291,10 +288,8 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat, } struct cmd_handler *handler = find_handler(argv[0], NULL, 0); if (!handler) { - if (results) { - free_cmd_results(results); - } - results = cmd_results_new(CMD_INVALID, cmd, "Unknown/invalid command"); + list_add(res_list, cmd_results_new(CMD_INVALID, cmd, + "Unknown/invalid command")); free_argv(argc, argv); goto cleanup; } @@ -308,29 +303,21 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat, if (!config->handler_context.using_criteria) { set_config_node(node); struct cmd_results *res = handler->handle(argc-1, argv+1); - if (res->status != CMD_SUCCESS) { + list_add(res_list, res); + if (res->status == CMD_INVALID) { free_argv(argc, argv); - if (results) { - free_cmd_results(results); - } - results = res; goto cleanup; } - free_cmd_results(res); } else { for (int i = 0; i < views->length; ++i) { struct sway_view *view = views->items[i]; set_config_node(&view->container->node); struct cmd_results *res = handler->handle(argc-1, argv+1); - if (res->status != CMD_SUCCESS) { + list_add(res_list, res); + if (res->status == CMD_INVALID) { free_argv(argc, argv); - if (results) { - free_cmd_results(results); - } - results = res; goto cleanup; } - free_cmd_results(res); } } free_argv(argc, argv); @@ -339,10 +326,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat, cleanup: free(exec); list_free(views); - if (!results) { - results = cmd_results_new(CMD_SUCCESS, NULL, NULL); - } - return results; + return res_list; } // this is like execute_command above, except: @@ -420,6 +404,7 @@ struct cmd_results *config_command(char *exec) { // Strip quotes and unescape the string for (int i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) { if (handler->handle != cmd_exec && handler->handle != cmd_exec_always + && handler->handle != cmd_mode && handler->handle != cmd_bindsym && handler->handle != cmd_bindcode && handler->handle != cmd_set @@ -574,20 +559,25 @@ void free_cmd_results(struct cmd_results *results) { free(results); } -char *cmd_results_to_json(struct cmd_results *results) { +char *cmd_results_to_json(list_t *res_list) { json_object *result_array = json_object_new_array(); - json_object *root = json_object_new_object(); - json_object_object_add(root, "success", - json_object_new_boolean(results->status == CMD_SUCCESS)); - if (results->input) { - json_object_object_add( - root, "input", json_object_new_string(results->input)); - } - if (results->error) { - json_object_object_add( - root, "error", json_object_new_string(results->error)); + for (int i = 0; i < res_list->length; ++i) { + struct cmd_results *results = res_list->items[i]; + json_object *root = json_object_new_object(); + json_object_object_add(root, "success", + json_object_new_boolean(results->status == CMD_SUCCESS)); + if (results->error) { + json_object_object_add(root, "parse_error", + json_object_new_boolean(results->status == CMD_INVALID)); + json_object_object_add( + root, "error", json_object_new_string(results->error)); + } + if (results->input) { + json_object_object_add( + root, "input", json_object_new_string(results->input)); + } + json_object_array_add(result_array, root); } - json_object_array_add(result_array, root); const char *json = json_object_to_json_string(result_array); char *res = strdup(json); json_object_put(result_array); diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 08acbe7a..34881b0f 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -289,13 +289,20 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) wlr_log(WLR_DEBUG, "running command for binding: %s", binding->command); config->handler_context.seat = seat; - struct cmd_results *results = execute_command(binding->command, NULL, NULL); - if (results->status == CMD_SUCCESS) { + list_t *res_list = execute_command(binding->command, NULL, NULL); + bool success = true; + while (res_list->length) { + struct cmd_results *results = res_list->items[0]; + if (results->status != CMD_SUCCESS) { + wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", + binding->command, results->error); + success = false; + } + free_cmd_results(results); + list_del(res_list, 0); + } + list_free(res_list); + if (success) { ipc_event_binding(binding); - } else { - wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", - binding->command, results->error); } - - free_cmd_results(results); } diff --git a/sway/ipc-server.c b/sway/ipc-server.c index aa0f0fad..95433d97 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -597,13 +597,18 @@ void ipc_client_handle_command(struct ipc_client *client) { switch (client->current_command) { case IPC_COMMAND: { - struct cmd_results *results = execute_command(buf, NULL, NULL); + list_t *res_list = execute_command(buf, NULL, NULL); transaction_commit_dirty(); - char *json = cmd_results_to_json(results); + char *json = cmd_results_to_json(res_list); int length = strlen(json); client_valid = ipc_send_reply(client, json, (uint32_t)length); free(json); - free_cmd_results(results); + while (res_list->length) { + struct cmd_results *results = res_list->items[0]; + free_cmd_results(results); + list_del(res_list, 0); + } + list_free(res_list); goto exit_cleanup; } diff --git a/sway/main.c b/sway/main.c index a21970e2..a74183fe 100644 --- a/sway/main.c +++ b/sway/main.c @@ -392,11 +392,16 @@ int main(int argc, char **argv) { wlr_log(WLR_DEBUG, "Running deferred commands"); while (config->cmd_queue->length) { char *line = config->cmd_queue->items[0]; - struct cmd_results *res = execute_command(line, NULL, NULL); - if (res->status != CMD_SUCCESS) { - wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error); + list_t *res_list = execute_command(line, NULL, NULL); + while (res_list->length) { + struct cmd_results *res = res_list->items[0]; + if (res->status != CMD_SUCCESS) { + wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error); + } + free_cmd_results(res); + list_del(res_list, 0); } - free_cmd_results(res); + list_free(res_list); free(line); list_del(config->cmd_queue, 0); } diff --git a/sway/tree/view.c b/sway/tree/view.c index f7af841c..0edefc8e 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -437,9 +437,14 @@ void view_execute_criteria(struct sway_view *view) { wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'", criteria->raw, view, criteria->cmdlist); list_add(view->executed_criteria, criteria); - struct cmd_results *res = execute_command( + list_t *res_list = execute_command( criteria->cmdlist, NULL, view->container); - free_cmd_results(res); + while (res_list->length) { + struct cmd_results *res = res_list->items[0]; + free_cmd_results(res); + list_del(res_list, 0); + } + list_free(res_list); } list_free(criterias); } diff --git a/swaynag/config.c b/swaynag/config.c index 63808ce4..e724aa0c 100644 --- a/swaynag/config.c +++ b/swaynag/config.c @@ -52,6 +52,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, static struct option opts[] = { {"button", required_argument, NULL, 'b'}, + {"button-no-terminal", required_argument, NULL, 'B'}, {"config", required_argument, NULL, 'c'}, {"debug", no_argument, NULL, 'd'}, {"edge", required_argument, NULL, 'e'}, @@ -86,7 +87,10 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, "Usage: swaynag [options...]\n" "\n" " -b, --button <text> <action> Create a button with text that " - "executes action when pressed. Multiple buttons can be defined.\n" + "executes action in a terminal when pressed. Multiple buttons can " + "be defined.\n" + " -B, --button-no-terminal <text> <action> Like --button, but does" + "not run the action in a terminal.\n" " -c, --config <path> Path to config file.\n" " -d, --debug Enable debugging.\n" " -e, --edge top|bottom Set the edge to use.\n" @@ -117,12 +121,13 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, optind = 1; while (1) { - int c = getopt_long(argc, argv, "b:c:de:f:hlL:m:o:s:t:v", opts, NULL); + int c = getopt_long(argc, argv, "b:B:c:de:f:hlL:m:o:s:t:v", opts, NULL); if (c == -1) { break; } switch (c) { case 'b': // Button + case 'B': // Button (No Terminal) if (swaynag) { if (optind >= argc) { fprintf(stderr, "Missing action for button %s\n", optarg); @@ -133,6 +138,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, button->text = strdup(optarg); button->type = SWAYNAG_ACTION_COMMAND; button->action = strdup(argv[optind]); + button->terminal = c == 'b'; list_add(swaynag->buttons, button); } optind++; diff --git a/swaynag/swaynag.1.scd b/swaynag/swaynag.1.scd index bb69e47d..b25568a0 100644 --- a/swaynag/swaynag.1.scd +++ b/swaynag/swaynag.1.scd @@ -12,7 +12,14 @@ _swaynag_ [options...] *-b, --button* <text> <action> Create a button with the text _text_ that executes _action_ when pressed. - Multiple buttons can be defined by providing the flag multiple times. + If the environment variable `TERMINAL` is set, _action_ will be run inside + the terminal. Otherwise, it will fallback to running directly. Multiple + buttons can be defined by providing the flag multiple times. + +*-B, --button-no-terminal* <text> <action> + Create a button with the text _text_ that executes _action_ when pressed. + _action_ will be run directly instead of in a terminal. Multiple buttons + can be defined by providing the flag multiple times. *-c, --config* <path> The config file to use. By default, the following paths are checked: diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index 74e127b6..a2a0b412 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c @@ -49,14 +49,17 @@ static void swaynag_button_execute(struct swaynag *swaynag, if (fork() == 0) { // Child of the child. Will be reparented to the init process char *terminal = getenv("TERMINAL"); - if (terminal && strlen(terminal)) { + if (button->terminal && terminal && strlen(terminal)) { wlr_log(WLR_DEBUG, "Found $TERMINAL: %s", terminal); if (!terminal_execute(terminal, button->action)) { swaynag_destroy(swaynag); exit(EXIT_FAILURE); } } else { - wlr_log(WLR_DEBUG, "$TERMINAL not found. Running directly"); + if (button->terminal) { + wlr_log(WLR_DEBUG, + "$TERMINAL not found. Running directly"); + } execl("/bin/sh", "/bin/sh", "-c", button->action, NULL); } } |