mirror of
https://github.com/tmux/tmux.git
synced 2025-01-05 23:38:48 +00:00
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.
This commit is contained in:
parent
561b5c6fdb
commit
844f2eacf4
116
format.c
116
format.c
@ -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) {
|
||||
|
15
tmux.1
15
tmux.1
@ -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 = ,
|
||||
|
Loading…
Reference in New Issue
Block a user