mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Merge pull request #3204 from RedSoxFan/cmd-res-list
Change execute_command to return a list of results
This commit is contained in:
		
						commit
						048b96a56d
					
				
					 6 changed files with 70 additions and 59 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			@ -575,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));
 | 
			
		||||
	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);
 | 
			
		||||
	}
 | 
			
		||||
	if (results->error) {
 | 
			
		||||
		json_object_object_add(
 | 
			
		||||
				root, "error", json_object_new_string(results->error));
 | 
			
		||||
	}
 | 
			
		||||
	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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
		ipc_event_binding(binding);
 | 
			
		||||
	} else {
 | 
			
		||||
		wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)",
 | 
			
		||||
			binding->command, results->error);
 | 
			
		||||
	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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	free_cmd_results(results);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								sway/main.c
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								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);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue