diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2017-01-09 21:03:26 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2017-01-09 21:03:26 +0000 |
commit | 6b544ed0aef6350d522dda46bce4c74d5877eb48 (patch) | |
tree | 4df258ec78d2103864623831f9e7b1e020dbf5dc /usr.bin | |
parent | 3095b0d9d204466e8d789384075b8b0ddf165676 (diff) |
Add simple comparisons in formats: #{==:a,b} and #{!=:a,b} ("a" and "b"
are expanded so can compare formats). And expand the condition to
#{?a,b,c} (the "a" part) if it doesn't work as a simple lookup.
Also add FORMAT_NOJOBS flag to disable jobs in a format.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tmux/format.c | 118 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.1 | 17 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 3 |
3 files changed, 108 insertions, 30 deletions
diff --git a/usr.bin/tmux/format.c b/usr.bin/tmux/format.c index 0b3ccd06259..a8b39ae3713 100644 --- a/usr.bin/tmux/format.c +++ b/usr.bin/tmux/format.c @@ -1,4 +1,4 @@ -/* $OpenBSD: format.c,v 1.113 2016/11/17 10:06:08 nicm Exp $ */ +/* $OpenBSD: format.c,v 1.114 2017/01/09 21:03:25 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -707,6 +707,50 @@ found: return (copy); } +/* Skip until comma. */ +static char * +format_skip(char *s) +{ + int brackets = 0; + + for (; *s != '\0'; s++) { + if (*s == '{') + brackets++; + if (*s == '}') + brackets--; + if (*s == ',' && brackets == 0) + break; + } + if (*s == '\0') + return (NULL); + return (s); +} + +/* Return left and right alternatives separated by commas. */ +static int +format_choose(char *s, char **left, char **right) +{ + char *cp; + + cp = format_skip(s); + if (cp == NULL) + return (-1); + *cp = '\0'; + + *left = s; + *right = cp + 1; + return (0); +} + +/* Is this true? */ +static int +format_true(const char *s) +{ + if (s != NULL && *s != '\0' && (s[0] != '0' || s[1] != '\0')) + return (1); + return (0); +} + /* * Replace a key/value pair in buffer. #{blah} is expanded directly, * #{?blah,a,b} is replace with a if blah exists and is nonzero else b. @@ -716,10 +760,10 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen, char **buf, size_t *len, size_t *off) { char *copy, *copy0, *endptr, *ptr, *found, *new, *value; - char *from = NULL, *to = NULL; + char *from = NULL, *to = NULL, *left, *right; size_t valuelen, newlen, fromlen, tolen, used; long limit = 0; - int modifiers = 0, brackets; + int modifiers = 0, compare = 0; /* Make a copy of the key. */ copy0 = copy = xmalloc(keylen + 1); @@ -728,7 +772,19 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen, /* Is there a length limit or whatnot? */ switch (copy[0]) { + case '!': + if (copy[1] == '=' && copy[2] == ':') { + compare = -1; + copy += 3; + break; + } + break; case '=': + if (copy[1] == '=' && copy[2] == ':') { + compare = 1; + copy += 3; + break; + } errno = 0; limit = strtol(copy + 1, &endptr, 10); if (errno == ERANGE && (limit == LONG_MIN || limit == LONG_MAX)) @@ -780,39 +836,42 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen, break; } - /* - * Is this a conditional? If so, check it exists and extract either the - * first or second element. If not, look up the key directly. - */ - if (*copy == '?') { - ptr = strchr(copy, ','); + /* Is this a comparison or a conditional? */ + if (compare != 0) { + /* Comparison: compare comma-separated left and right. */ + if (format_choose(copy, &left, &right) != 0) + goto fail; + left = format_expand(ft, left); + right = format_expand(ft, right); + if (compare == 1 && strcmp(left, right) == 0) + value = xstrdup("1"); + else if (compare == -1 && strcmp(left, right) != 0) + value = xstrdup("1"); + else + value = xstrdup("0"); + free(right); + free(left); + } else if (*copy == '?') { + /* Conditional: check first and choose second or third. */ + ptr = format_skip(copy); if (ptr == NULL) goto fail; *ptr = '\0'; - value = ptr + 1; found = format_find(ft, copy + 1, modifiers); - - brackets = 0; - for (ptr = ptr + 1; *ptr != '\0'; ptr++) { - if (*ptr == '{') - brackets++; - if (*ptr == '}') - brackets--; - if (*ptr == ',' && brackets == 0) - break; - } - if (*ptr == '\0') + if (found == NULL) { + log_debug("XXX %s", copy + 1); + found = format_expand(ft, copy + 1);} + if (format_choose(ptr + 1, &left, &right) != 0) goto fail; - if (found != NULL && *found != '\0' && - (found[0] != '0' || found[1] != '\0')) { - *ptr = '\0'; - } else - value = ptr + 1; - value = format_expand(ft, value); + if (format_true(found)) + value = format_expand(ft, left); + else + value = format_expand(ft, right); free(found); } else { + /* Neither: look up directly. */ value = format_find(ft, copy, modifiers); if (value == NULL) value = xstrdup(""); @@ -934,7 +993,10 @@ format_expand(struct format_tree *ft, const char *fmt) break; n = ptr - fmt; - out = format_job_get(ft, xstrndup(fmt, n)); + if (ft->flags & FORMAT_NOJOBS) + out = xstrdup(""); + else + out = format_job_get(ft, xstrndup(fmt, n)); outlen = strlen(out); while (len - off < outlen + 1) { diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 4b7b4b6d468..b319537efa4 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.519 2017/01/09 19:27:00 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.520 2017/01/09 21:03:25 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> .\" @@ -3397,6 +3397,21 @@ is enabled, or .Ql no if not. .Pp +Simple comparisons may be expressed by prefixing two comma-separated +alternatives by +.Ql == +or +.Ql != +and a colon. +For example +.Ql #{==,#{host},myhost} +will be replaced by +.Ql 1 +if running on +.Ql myhost , +otherwise by +.Ql 0. +.Pp A limit may be placed on the length of the resultant string by prefixing it by an .Ql = , diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 816c049325a..e3064da4456 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.686 2017/01/09 19:27:00 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.687 2017/01/09 21:03:25 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -1568,6 +1568,7 @@ char *paste_make_sample(struct paste_buffer *); /* format.c */ #define FORMAT_STATUS 0x1 #define FORMAT_FORCE 0x2 +#define FORMAT_NOJOBS 0x4 struct format_tree; struct format_tree *format_create(struct cmdq_item *, int); void format_free(struct format_tree *); |