diff --git a/include/commands.h b/include/commands.h index 8fb0c1d8..e521306c 100644 --- a/include/commands.h +++ b/include/commands.h @@ -15,6 +15,8 @@ struct cmd_handler { struct cmd_handler *find_handler(char *line); bool handle_command(char *command); +// Handles commands during config +bool config_command(char *command); void remove_view_from_scratchpad(); diff --git a/sway/commands.c b/sway/commands.c index 44407bfa..edc56466 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -835,7 +835,7 @@ static int compare_set(const void *_l, const void *_r) { } static bool cmd_set(int argc, char **argv) { - if (!checkarg(argc, "set", EXPECTED_EQUAL_TO, 2)) { + if (!checkarg(argc, "set", EXPECTED_AT_LEAST, 2)) { return false; } struct sway_variable *var = NULL; @@ -856,7 +856,7 @@ static bool cmd_set(int argc, char **argv) { list_add(config->symbols, var); list_sort(config->symbols, compare_set); } - var->value = strdup(argv[1]); + var->value = join_args(argv + 1, argc - 1); return true; } @@ -1067,17 +1067,54 @@ bool handle_command(char *exec) { } struct cmd_handler *handler = find_handler(argv[0]); bool exec_success = false; - if (handler) { - int i; - // Skip var replacement for first value of cmd_set - for (i = (handler->handle == cmd_set ? 2 : 1); i < argc; ++i) { - argv[i] = do_var_replacement(argv[i]); - } - exec_success = handler->handle(argc - 1, argv + 1); - } - if (exec_success == false) { + if (handler && !(handler->handle(argc - 1, argv + 1))) { sway_log(L_ERROR, "Command failed: %s", argv[0]); } free_argv(argc, argv); return exec_success; } + +bool config_command(char *exec) { + sway_log(L_INFO, "handling config command '%s'", exec); + struct cmd_handler *handler; + int argc; + char **argv = split_args(exec, &argc); + bool res = false; + if (!argc) { + return true; + } + //TODO make this better, it only handles modes right now, and very + //simply at that + if (strncmp(argv[0], "}", 1) == 0) { + config->current_mode = config->modes->items[0]; + res = true; + goto cleanup; + } + if ((handler = find_handler(argv[0]))) { + int i = 1, e = argc; + // dont var replace first argument + if (handler->handle == cmd_set) { + i = 2; + } + for (; i < e; ++i) { + argv[i] = do_var_replacement(argv[i]); + } + if (handler->config_type == CMD_KEYBIND) { + sway_log(L_ERROR, "Invalid command during config `%s'", exec); + } else if (handler->config_type == CMD_COMPOSITOR_READY && !config->active) { + sway_log(L_DEBUG, "Defferring command `%s'", exec); + char *cmd = join_args(argv, argc); + list_add(config->cmd_queue, cmd); + res = true; + } else if (!handler->handle(argc-1, argv+1)) { + sway_log(L_DEBUG, "Config load failed for line `%s'", exec); + } else { + res = true; + } + } else { + sway_log(L_ERROR, "Unknown command `%s'", exec); + } + cleanup: + free_argv(argc, argv); + return res; +} diff --git a/sway/config.c b/sway/config.c index 6d445ec6..7d3104c7 100644 --- a/sway/config.c +++ b/sway/config.c @@ -231,34 +231,9 @@ bool read_config(FILE *file, bool is_active) { while (!feof(file)) { line = read_line(file); line = strip_comments(line); - list_t *args = split_string(line, whitespace); - if (!args->length) { - goto cleanup; + if (!config_command(line)) { + success = false; } - //TODO make this better, it only handles modes right now, and very - //simply at that - if (strncmp(args->items[0], "}", 1) == 0) { - config->current_mode = default_mode; - goto cleanup; - } - struct cmd_handler *handler; - if ((handler = find_handler(args->items[0]))) { - if (handler->config_type == CMD_KEYBIND) { - sway_log(L_ERROR, "Invalid command during config ``%s''", line); - } else if (handler->config_type == CMD_COMPOSITOR_READY && !is_active) { - sway_log(L_DEBUG, "Deferring command ``%s''", line); - char *cmd = strdup(line); - list_add(config->cmd_queue, cmd); - } else if (!handle_command(line)) { - sway_log(L_DEBUG, "Config load failed for line ``%s''", line); - success = false; - config->failed = true; - } - } else { - sway_log(L_ERROR, "Invalid command ``%s''", line); - } - cleanup: - free_flat_list(args); free(line); } diff --git a/sway/stringop.c b/sway/stringop.c index 1ba54ec6..7de6eded 100644 --- a/sway/stringop.c +++ b/sway/stringop.c @@ -179,76 +179,82 @@ int unescape_string(char *string) { int i; for (i = 0; string[i]; ++i) { if (string[i] == '\\') { - --len; - int shift = 0; switch (string[++i]) { case '0': string[i - 1] = '\0'; - shift = 1; - break; + return i - 1; case 'a': string[i - 1] = '\a'; - shift = 1; + string[i] = '\0'; break; case 'b': string[i - 1] = '\b'; - shift = 1; + string[i] = '\0'; break; case 'f': string[i - 1] = '\f'; - shift = 1; + string[i] = '\0'; break; case 'n': string[i - 1] = '\n'; - shift = 1; + string[i] = '\0'; break; case 'r': string[i - 1] = '\r'; - shift = 1; + string[i] = '\0'; break; case 't': string[i - 1] = '\t'; - shift = 1; + string[i] = '\0'; break; case 'v': string[i - 1] = '\v'; - shift = 1; + string[i] = '\0'; break; case '\\': - shift = 1; + string[i] = '\0'; break; case '\'': string[i - 1] = '\''; - shift = 1; + string[i] = '\0'; break; case '\"': string[i - 1] = '\"'; - shift = 1; + string[i] = '\0'; break; case '?': string[i - 1] = '?'; - shift = 1; + string[i] = '\0'; break; case 'x': { unsigned char c = 0; - shift = 1; if (string[i+1] >= '0' && string[i+1] <= '9') { - shift = 2; c = string[i+1] - '0'; if (string[i+2] >= '0' && string[i+2] <= '9') { - shift = 3; c *= 0x10; c += string[i+2] - '0'; + string[i+2] = '\0'; } + string[i+1] = '\0'; } + string[i] = '\0'; string[i - 1] = c; } } - memmove(string + i, string + i + shift, len - i + 1); } } - return len; + // Shift characters over nullspaces + int shift = 0; + for (i = 0; i < len; ++i) { + if (string[i] == 0) { + shift++; + continue; + } + string[i-shift] = string[i]; + } + string[len - shift] = 0; + return len - shift; } char *join_args(char **argv, int argc) {