summaryrefslogtreecommitdiff
path: root/usr.bin/tmux/format.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2018-05-22 08:49:13 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2018-05-22 08:49:13 +0000
commitdbc00665addacfb4fe58f83ac39d31508389b024 (patch)
tree222e0b93839eff80c8f3cd960a4835402c50c55a /usr.bin/tmux/format.c
parent5e9862c12ac9542c5e346abf53a9111d1cef696d (diff)
Allow escaping , and } with # in #{}; GitHub issue 1332.
Diffstat (limited to 'usr.bin/tmux/format.c')
-rw-r--r--usr.bin/tmux/format.c48
1 files changed, 31 insertions, 17 deletions
diff --git a/usr.bin/tmux/format.c b/usr.bin/tmux/format.c
index 6310e218e65..2d8a2bf69c6 100644
--- a/usr.bin/tmux/format.c
+++ b/usr.bin/tmux/format.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: format.c,v 1.154 2018/04/18 14:35:37 nicm Exp $ */
+/* $OpenBSD: format.c,v 1.155 2018/05/22 08:49:12 nicm Exp $ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -837,18 +837,22 @@ found:
return (copy);
}
-/* Skip until comma. */
-static char *
-format_skip(char *s)
+/* Skip until end. */
+static const char *
+format_skip(const char *s, char end)
{
int brackets = 0;
for (; *s != '\0'; s++) {
- if (*s == '{')
+ if (*s == '#' && s[1] == '{')
brackets++;
+ if (*s == '#' && strchr(",#{}", s[1]) != NULL) {
+ s++;
+ continue;
+ }
if (*s == '}')
brackets--;
- if (*s == ',' && brackets == 0)
+ if (*s == end && brackets == 0)
break;
}
if (*s == '\0')
@@ -862,7 +866,7 @@ format_choose(char *s, char **left, char **right)
{
char *cp;
- cp = format_skip(s);
+ cp = (char *)format_skip(s, ',');
if (cp == NULL)
return (-1);
*cp = '\0';
@@ -892,6 +896,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
size_t valuelen, newlen, fromlen, tolen, used;
long limit = 0;
int modifiers = 0, compare = 0, search = 0;
+ int literal = 0;
/* Make a copy of the key. */
copy0 = copy = xmalloc(keylen + 1);
@@ -900,6 +905,12 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
/* Is there a length limit or whatnot? */
switch (copy[0]) {
+ case 'l':
+ if (copy[1] != ':')
+ break;
+ literal = 1;
+ copy += 2;
+ break;
case 'm':
if (copy[1] != ':')
break;
@@ -988,6 +999,12 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
break;
}
+ /* Is this a literal string? */
+ if (literal) {
+ value = xstrdup(copy);
+ goto done;
+ }
+
/* Is this a comparison or a conditional? */
if (search) {
/* Search in pane. */
@@ -1019,7 +1036,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
free(left);
} else if (*copy == '?') {
/* Conditional: check first and choose second or third. */
- ptr = format_skip(copy);
+ ptr = (char *)format_skip(copy, ',');
if (ptr == NULL)
goto fail;
*ptr = '\0';
@@ -1082,6 +1099,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
}
/* Expand the buffer and copy in the value. */
+done:
valuelen = strlen(value);
while (*len - *off < valuelen + 1) {
*buf = xreallocarray(*buf, 2, *len);
@@ -1179,14 +1197,8 @@ format_expand(struct format_tree *ft, const char *fmt)
fmt += n + 1;
continue;
case '{':
- brackets = 1;
- for (ptr = fmt; *ptr != '\0'; ptr++) {
- if (*ptr == '{')
- brackets++;
- if (*ptr == '}' && --brackets == 0)
- break;
- }
- if (*ptr != '}' || brackets != 0)
+ ptr = format_skip(fmt - 2, '}');
+ if (ptr == NULL)
break;
n = ptr - fmt;
@@ -1194,12 +1206,14 @@ format_expand(struct format_tree *ft, const char *fmt)
break;
fmt += n + 1;
continue;
+ case '}':
case '#':
+ case ',':
while (len - off < 2) {
buf = xreallocarray(buf, 2, len);
len *= 2;
}
- buf[off++] = '#';
+ buf[off++] = ch;
continue;
default:
s = NULL;