Change execute_command to return a list of results
This matches i3's behavior of returning a list of results that contain the result of each command that was executed. Additionally, the `parse_error` attribute has been added to the IPC JSON reply.
This commit is contained in:
parent
dbf8e1cead
commit
5c6f3d7266
|
@ -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
|
* all matching containers. Otherwise, it'll run on the `con` container. If
|
||||||
* `con` is NULL then it'll run on the currently focused container.
|
* `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);
|
struct sway_container *con);
|
||||||
/**
|
/**
|
||||||
* Parse and handles a command during config file loading.
|
* 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);
|
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.
|
* 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,
|
struct cmd_results *add_color(const char *name,
|
||||||
char *buffer, const char *color);
|
char *buffer, const char *color);
|
||||||
|
|
|
@ -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) {
|
struct sway_container *con) {
|
||||||
// Even though this function will process multiple commands we will only
|
list_t *res_list = create_list();
|
||||||
// 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;
|
|
||||||
char *exec = strdup(_exec);
|
char *exec = strdup(_exec);
|
||||||
char *head = exec;
|
char *head = exec;
|
||||||
char *cmdlist;
|
char *cmdlist;
|
||||||
|
@ -254,8 +251,8 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat,
|
||||||
char *error = NULL;
|
char *error = NULL;
|
||||||
struct criteria *criteria = criteria_parse(head, &error);
|
struct criteria *criteria = criteria_parse(head, &error);
|
||||||
if (!criteria) {
|
if (!criteria) {
|
||||||
results = cmd_results_new(CMD_INVALID, head,
|
list_add(res_list, cmd_results_new(CMD_INVALID, head,
|
||||||
"%s", error);
|
"%s", error));
|
||||||
free(error);
|
free(error);
|
||||||
goto cleanup;
|
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);
|
struct cmd_handler *handler = find_handler(argv[0], NULL, 0);
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
if (results) {
|
list_add(res_list, cmd_results_new(CMD_INVALID, cmd,
|
||||||
free_cmd_results(results);
|
"Unknown/invalid command"));
|
||||||
}
|
|
||||||
results = cmd_results_new(CMD_INVALID, cmd, "Unknown/invalid command");
|
|
||||||
free_argv(argc, argv);
|
free_argv(argc, argv);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -308,29 +303,21 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat,
|
||||||
if (!config->handler_context.using_criteria) {
|
if (!config->handler_context.using_criteria) {
|
||||||
set_config_node(node);
|
set_config_node(node);
|
||||||
struct cmd_results *res = handler->handle(argc-1, argv+1);
|
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);
|
free_argv(argc, argv);
|
||||||
if (results) {
|
|
||||||
free_cmd_results(results);
|
|
||||||
}
|
|
||||||
results = res;
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
free_cmd_results(res);
|
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < views->length; ++i) {
|
for (int i = 0; i < views->length; ++i) {
|
||||||
struct sway_view *view = views->items[i];
|
struct sway_view *view = views->items[i];
|
||||||
set_config_node(&view->container->node);
|
set_config_node(&view->container->node);
|
||||||
struct cmd_results *res = handler->handle(argc-1, argv+1);
|
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);
|
free_argv(argc, argv);
|
||||||
if (results) {
|
|
||||||
free_cmd_results(results);
|
|
||||||
}
|
|
||||||
results = res;
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
free_cmd_results(res);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free_argv(argc, argv);
|
free_argv(argc, argv);
|
||||||
|
@ -339,10 +326,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat,
|
||||||
cleanup:
|
cleanup:
|
||||||
free(exec);
|
free(exec);
|
||||||
list_free(views);
|
list_free(views);
|
||||||
if (!results) {
|
return res_list;
|
||||||
results = cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is like execute_command above, except:
|
// this is like execute_command above, except:
|
||||||
|
@ -574,20 +558,25 @@ void free_cmd_results(struct cmd_results *results) {
|
||||||
free(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 *result_array = json_object_new_array();
|
||||||
|
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 *root = json_object_new_object();
|
||||||
json_object_object_add(root, "success",
|
json_object_object_add(root, "success",
|
||||||
json_object_new_boolean(results->status == CMD_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) {
|
if (results->input) {
|
||||||
json_object_object_add(
|
json_object_object_add(
|
||||||
root, "input", json_object_new_string(results->input));
|
root, "input", json_object_new_string(results->input));
|
||||||
}
|
}
|
||||||
if (results->error) {
|
|
||||||
json_object_object_add(
|
|
||||||
root, "error", json_object_new_string(results->error));
|
|
||||||
}
|
|
||||||
json_object_array_add(result_array, root);
|
json_object_array_add(result_array, root);
|
||||||
|
}
|
||||||
const char *json = json_object_to_json_string(result_array);
|
const char *json = json_object_to_json_string(result_array);
|
||||||
char *res = strdup(json);
|
char *res = strdup(json);
|
||||||
json_object_put(result_array);
|
json_object_put(result_array);
|
||||||
|
|
|
@ -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);
|
wlr_log(WLR_DEBUG, "running command for binding: %s", binding->command);
|
||||||
|
|
||||||
config->handler_context.seat = seat;
|
config->handler_context.seat = seat;
|
||||||
struct cmd_results *results = execute_command(binding->command, NULL, NULL);
|
list_t *res_list = execute_command(binding->command, NULL, NULL);
|
||||||
if (results->status == CMD_SUCCESS) {
|
bool success = true;
|
||||||
ipc_event_binding(binding);
|
while (res_list->length) {
|
||||||
} else {
|
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)",
|
wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)",
|
||||||
binding->command, results->error);
|
binding->command, results->error);
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_cmd_results(results);
|
free_cmd_results(results);
|
||||||
|
list_del(res_list, 0);
|
||||||
|
}
|
||||||
|
list_free(res_list);
|
||||||
|
if (success) {
|
||||||
|
ipc_event_binding(binding);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -597,13 +597,18 @@ void ipc_client_handle_command(struct ipc_client *client) {
|
||||||
switch (client->current_command) {
|
switch (client->current_command) {
|
||||||
case IPC_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();
|
transaction_commit_dirty();
|
||||||
char *json = cmd_results_to_json(results);
|
char *json = cmd_results_to_json(res_list);
|
||||||
int length = strlen(json);
|
int length = strlen(json);
|
||||||
client_valid = ipc_send_reply(client, json, (uint32_t)length);
|
client_valid = ipc_send_reply(client, json, (uint32_t)length);
|
||||||
free(json);
|
free(json);
|
||||||
|
while (res_list->length) {
|
||||||
|
struct cmd_results *results = res_list->items[0];
|
||||||
free_cmd_results(results);
|
free_cmd_results(results);
|
||||||
|
list_del(res_list, 0);
|
||||||
|
}
|
||||||
|
list_free(res_list);
|
||||||
goto exit_cleanup;
|
goto exit_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -392,11 +392,16 @@ int main(int argc, char **argv) {
|
||||||
wlr_log(WLR_DEBUG, "Running deferred commands");
|
wlr_log(WLR_DEBUG, "Running deferred commands");
|
||||||
while (config->cmd_queue->length) {
|
while (config->cmd_queue->length) {
|
||||||
char *line = config->cmd_queue->items[0];
|
char *line = config->cmd_queue->items[0];
|
||||||
struct cmd_results *res = execute_command(line, NULL, NULL);
|
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) {
|
if (res->status != CMD_SUCCESS) {
|
||||||
wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error);
|
wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error);
|
||||||
}
|
}
|
||||||
free_cmd_results(res);
|
free_cmd_results(res);
|
||||||
|
list_del(res_list, 0);
|
||||||
|
}
|
||||||
|
list_free(res_list);
|
||||||
free(line);
|
free(line);
|
||||||
list_del(config->cmd_queue, 0);
|
list_del(config->cmd_queue, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -437,9 +437,14 @@ void view_execute_criteria(struct sway_view *view) {
|
||||||
wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
|
wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
|
||||||
criteria->raw, view, criteria->cmdlist);
|
criteria->raw, view, criteria->cmdlist);
|
||||||
list_add(view->executed_criteria, criteria);
|
list_add(view->executed_criteria, criteria);
|
||||||
struct cmd_results *res = execute_command(
|
list_t *res_list = execute_command(
|
||||||
criteria->cmdlist, NULL, view->container);
|
criteria->cmdlist, NULL, view->container);
|
||||||
|
while (res_list->length) {
|
||||||
|
struct cmd_results *res = res_list->items[0];
|
||||||
free_cmd_results(res);
|
free_cmd_results(res);
|
||||||
|
list_del(res_list, 0);
|
||||||
|
}
|
||||||
|
list_free(res_list);
|
||||||
}
|
}
|
||||||
list_free(criterias);
|
list_free(criterias);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue