aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/commands.h6
-rw-r--r--include/swaynag/swaynag.h1
-rw-r--r--sway/commands.c68
-rw-r--r--sway/commands/bind.c21
-rw-r--r--sway/ipc-server.c11
-rw-r--r--sway/main.c13
-rw-r--r--sway/tree/view.c9
-rw-r--r--swaynag/config.c10
-rw-r--r--swaynag/swaynag.1.scd9
-rw-r--r--swaynag/swaynag.c7
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);
}
}