diff --git a/common/readline.c b/common/readline.c index ed5801de..abe986c4 100644 --- a/common/readline.c +++ b/common/readline.c @@ -48,6 +48,20 @@ char *read_line(FILE *file) { return string; } +char *peek_line(FILE *file, int offset) { + int pos = ftell(file); + char *line = NULL; + for (int i = 0; i <= offset; i++) { + free(line); + line = read_line(file); + if (!line) { + break; + } + } + fseek(file, pos, SEEK_SET); + return line; +} + char *read_line_buffer(FILE *file, char *string, size_t string_len) { size_t length = 0; if (!string) { diff --git a/include/readline.h b/include/readline.h index b3e06d4b..3f63e917 100644 --- a/include/readline.h +++ b/include/readline.h @@ -4,6 +4,7 @@ #include char *read_line(FILE *file); +char *peek_line(FILE *file, int offset); char *read_line_buffer(FILE *file, char *string, size_t string_len); #endif diff --git a/sway/config.c b/sway/config.c index 26e6f3e3..edb10bd7 100644 --- a/sway/config.c +++ b/sway/config.c @@ -513,6 +513,49 @@ bool load_include_configs(const char *path, struct sway_config *config) { return true; } +static int detect_brace_on_following_line(FILE *file, char *line, + int line_number) { + int lines = 0; + if (line[strlen(line) - 1] != '{' && line[strlen(line) - 1] != '}') { + char *peeked = NULL; + do { + wlr_log(L_DEBUG, "Peeking line %d", line_number + lines + 1); + free(peeked); + peeked = peek_line(file, lines); + if (peeked) { + peeked = strip_whitespace(peeked); + } + lines++; + } while (peeked && strlen(peeked) == 0); + + if (peeked && strlen(peeked) == 1 && peeked[0] == '{') { + for (int i = 0; i < lines; i++) { + free(peeked); + peeked = read_line(file); + } + } else { + lines = 0; + } + free(peeked); + } + return lines; +} + +static char *expand_line(char *block, char *line, bool add_brace) { + int size = (block ? strlen(block) + 1 : 0) + strlen(line) + + (add_brace ? 2 : 0) + 1; + char *expanded = calloc(1, size); + if (!expanded) { + wlr_log(L_ERROR, "Cannot allocate expanded line buffer"); + return NULL; + } + strcat(expanded, block ? block : ""); + strcat(expanded, block ? " " : ""); + strcat(expanded, line); + strcat(expanded, add_brace ? " {" : ""); + return expanded; +} + bool read_config(FILE *file, struct sway_config *config) { bool success = true; int line_number = 0; @@ -535,19 +578,27 @@ bool read_config(FILE *file, struct sway_config *config) { free(line); continue; } - char *full = calloc(strlen(block ? block : "") + strlen(line) + 2, 1); - strcat(full, block ? block : ""); - strcat(full, block ? " " : ""); - strcat(full, line); - wlr_log(L_DEBUG, "Expanded line: %s", full); + int brace_detected = detect_brace_on_following_line(file, line, + line_number); + if (brace_detected > 0) { + line_number += brace_detected; + wlr_log(L_DEBUG, "Detected open brace on line %d", line_number); + } + char *expanded = expand_line(block, line, brace_detected > 0); + if (!expanded) { + return false; + } + wlr_log(L_DEBUG, "Expanded line: %s", expanded); struct cmd_results *res; if (block && strcmp(block, "") == 0) { // Special case - res = config_commands_command(full); + res = config_commands_command(expanded); } else { - res = config_command(full); + wlr_log(L_DEBUG, "Entering c_c"); + res = config_command(expanded); + wlr_log(L_DEBUG, "Exiting c_c"); } - free(full); + free(expanded); switch(res->status) { case CMD_FAILURE: case CMD_INVALID: