From e8c0ef98b1c1068783350c76b44c4e40b7534137 Mon Sep 17 00:00:00 2001 From: Roosembert Palacios Date: Sun, 5 Jun 2016 23:36:27 +0200 Subject: [PATCH 1/2] Sway: Configuration: Support for escaping line breaks. Escape line return in configuration file with the '\' character. Similar to shell scripts. Signed-off-by: Roosembert Palacios --- sway/config.c | 42 +++++++++++++++++++++++++++++++++++++++++- sway/sway.5.txt | 6 ++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/sway/config.c b/sway/config.c index 15108123..c1eec22f 100644 --- a/sway/config.c +++ b/sway/config.c @@ -455,10 +455,11 @@ bool load_include_configs(const char *path, struct sway_config *config) { bool read_config(FILE *file, struct sway_config *config) { bool success = true; + bool multiline = false; enum cmd_status block = CMD_BLOCK_END; int line_number = 0; - char *line; + char *line, *mlinebuf = NULL; while (!feof(file)) { line = read_line(file); line_number++; @@ -467,6 +468,45 @@ bool read_config(FILE *file, struct sway_config *config) { free(line); continue; } + size_t length = strlen(line); + if (line[length-1] == '\\') { + // Start of multiline + if (feof(file)){ + sway_log(L_ERROR, "Error on line %i '%s': Unexpected EOF on "\ + "multiline command", line_number, line); + free(line); + continue; + } + line[length-1] = '\0'; + multiline = true; + } else + multiline = false; + + if (multiline || mlinebuf){ + size_t mlinebuf_length; + if (mlinebuf) + mlinebuf_length = strlen(mlinebuf); + else + mlinebuf_length = 0; + + char *tmp = malloc(mlinebuf_length+length+1); // + '\0' + tmp[0]='\0'; // if mlinebuf_length==0 strncpy won't do anything. Make a null string. + strncpy(tmp, mlinebuf, mlinebuf_length); + tmp[mlinebuf_length]='\0'; // strncpy won't add '\0' at the end... + strcat(tmp, line); + if (mlinebuf) + free(mlinebuf); + free(line); + mlinebuf = tmp; + if (multiline) // The following line is part of a multi line config. + continue; + else { // This is the last line of a multi line config. + line = mlinebuf; + sway_log(L_INFO, "Processing parsed multiline command '%s'", line); + mlinebuf = NULL; + } + } + struct cmd_results *res = config_command(line, block); switch(res->status) { case CMD_FAILURE: diff --git a/sway/sway.5.txt b/sway/sway.5.txt index bd2de12d..397b6d87 100644 --- a/sway/sway.5.txt +++ b/sway/sway.5.txt @@ -16,6 +16,12 @@ on startup. These commands usually consist of setting your preferences and setting key bindings. An example config is likely present in /etc/sway/config for you to check out. +Lines in the configuration file might be extended through multiple lines by +adding a '\' character at the end of line. e.g.: + + bindsym Shift+XF86AudioRaiseVolume exec pactl set-sink-volume \ + $(pactl list sinks | grep -B 1 RUNNING | sed '1q;d' | sed 's/[^0-9]\+//g') +5% + These commands can be executed in your config file, via **sway-msg**(1), or via the bindsym command. From 230591fa4e4911ffbb38da2ee79650e62d98415f Mon Sep 17 00:00:00 2001 From: Roosembert Palacios Date: Mon, 6 Jun 2016 00:17:27 +0200 Subject: [PATCH 2/2] Common: Readline: Ignore newline on '\' escaped line ends. Escape line return when reading from a file with the '\' character. Similar to shell scripts. Signed-off-by: Roosembert Palacios --- common/readline.c | 7 +++++++ sway/config.c | 42 +----------------------------------------- 2 files changed, 8 insertions(+), 41 deletions(-) diff --git a/common/readline.c b/common/readline.c index 76ed6926..5106172c 100644 --- a/common/readline.c +++ b/common/readline.c @@ -5,17 +5,24 @@ char *read_line(FILE *file) { size_t length = 0, size = 128; char *string = malloc(size); + char lastChar = '\0'; if (!string) { return NULL; } while (1) { int c = getc(file); + if (c == '\n' && lastChar == '\\'){ + --length; // Ignore last character. + lastChar = '\0'; + continue; + } if (c == EOF || c == '\n' || c == '\0') { break; } if (c == '\r') { continue; } + lastChar = c; if (length == size) { char *new_string = realloc(string, size *= 2); if (!new_string) { diff --git a/sway/config.c b/sway/config.c index c1eec22f..15108123 100644 --- a/sway/config.c +++ b/sway/config.c @@ -455,11 +455,10 @@ bool load_include_configs(const char *path, struct sway_config *config) { bool read_config(FILE *file, struct sway_config *config) { bool success = true; - bool multiline = false; enum cmd_status block = CMD_BLOCK_END; int line_number = 0; - char *line, *mlinebuf = NULL; + char *line; while (!feof(file)) { line = read_line(file); line_number++; @@ -468,45 +467,6 @@ bool read_config(FILE *file, struct sway_config *config) { free(line); continue; } - size_t length = strlen(line); - if (line[length-1] == '\\') { - // Start of multiline - if (feof(file)){ - sway_log(L_ERROR, "Error on line %i '%s': Unexpected EOF on "\ - "multiline command", line_number, line); - free(line); - continue; - } - line[length-1] = '\0'; - multiline = true; - } else - multiline = false; - - if (multiline || mlinebuf){ - size_t mlinebuf_length; - if (mlinebuf) - mlinebuf_length = strlen(mlinebuf); - else - mlinebuf_length = 0; - - char *tmp = malloc(mlinebuf_length+length+1); // + '\0' - tmp[0]='\0'; // if mlinebuf_length==0 strncpy won't do anything. Make a null string. - strncpy(tmp, mlinebuf, mlinebuf_length); - tmp[mlinebuf_length]='\0'; // strncpy won't add '\0' at the end... - strcat(tmp, line); - if (mlinebuf) - free(mlinebuf); - free(line); - mlinebuf = tmp; - if (multiline) // The following line is part of a multi line config. - continue; - else { // This is the last line of a multi line config. - line = mlinebuf; - sway_log(L_INFO, "Processing parsed multiline command '%s'", line); - mlinebuf = NULL; - } - } - struct cmd_results *res = config_command(line, block); switch(res->status) { case CMD_FAILURE: