config: allow string values to be quoted

* Both double and single quotes are recognized. There’s no difference
  in how they are handled.
* The entire string must be quoted:
  - “a quoted string” - OK
  - quotes “in the middle” of a string - NOT ok
* Two escape characters are regonized:
  - Backslash
  - The quote character itself
This commit is contained in:
Daniel Eklöf 2022-12-01 15:00:44 +01:00
parent 1486c57bdb
commit 051e862420
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 43 additions and 1 deletions

View file

@ -49,6 +49,8 @@
* Support (optional) for utmp logging with libutempter.
* `kxIN` and `kxOUT` (focus in/out events) to terminfo.
* `name` capability to `XTGETTCAP`.
* String values in `foot.ini` may now be quoted. This can be used to
set a value to the empty string, for example.
[1136]: https://codeberg.org/dnkl/foot/issues/1136

View file

@ -502,8 +502,48 @@ value_to_double(struct context *ctx, float *res)
static bool NOINLINE
value_to_str(struct context *ctx, char **res)
{
char *copy = xstrdup(ctx->value);
char *end = copy + strlen(copy) - 1;
/* Un-quote
*
* Note: this is very simple; we only support the *entire* value
* being quoted. That is, no mid-value quotes. Both double and
* single quotes are supported.
*
* - key="value" OK
* - key=abc "quote" def NOT OK
* - key=value OK
*
* Finally, we support escaping the quote character, and the
* escape character itself:
*
* - key="value \"quotes\""
* - key="backslash: \\"
*
* ONLY the "current" quote character can be escaped:
*
* key="value \'" NOt OK (both backslash and single quote is kept)
*/
if ((copy[0] == '"' && *end == '"') ||
(copy[0] == '\'' && *end == '\''))
{
const char quote = copy[0];
*end = '\0';
memmove(copy, copy + 1, end - copy);
/* Un-escape */
for (char *p = copy; *p != '\0'; p++) {
if (p[0] == '\\' && (p[1] == '\\' || p[1] == quote)) {
memmove(p, p + 1, end - p);
}
}
}
free(*res);
*res = xstrdup(ctx->value);
*res = copy;
return true;
}