Add s/foo/bar/: prefix for formats to substitute bar for foo.

pull/210/head
nicm 2015-11-18 14:13:55 +00:00
parent 64571368dc
commit 5a5b950e8b
2 changed files with 73 additions and 14 deletions

View File

@ -99,6 +99,7 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
#define FORMAT_TIMESTRING 0x1 #define FORMAT_TIMESTRING 0x1
#define FORMAT_BASENAME 0x2 #define FORMAT_BASENAME 0x2
#define FORMAT_DIRNAME 0x4 #define FORMAT_DIRNAME 0x4
#define FORMAT_SUBSTITUTE 0x8
/* Entry in format tree. */ /* Entry in format tree. */
struct format_entry { struct format_entry {
@ -682,8 +683,9 @@ int
format_replace(struct format_tree *ft, const char *key, size_t keylen, format_replace(struct format_tree *ft, const char *key, size_t keylen,
char **buf, size_t *len, size_t *off) char **buf, size_t *len, size_t *off)
{ {
char *copy, *copy0, *endptr, *ptr, *saved, *trimmed, *value; char *copy, *copy0, *endptr, *ptr, *found, *new, *value;
size_t valuelen; char *from = NULL, *to = NULL;
size_t valuelen, newlen, fromlen, tolen, used;
u_long limit = 0; u_long limit = 0;
int modifiers = 0, brackets; int modifiers = 0, brackets;
@ -721,6 +723,29 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
modifiers |= FORMAT_TIMESTRING; modifiers |= FORMAT_TIMESTRING;
copy += 2; copy += 2;
break; break;
case 's':
if (copy[1] != '/')
break;
from = copy + 2;
for (copy = from; *copy != '\0' && *copy != '/'; copy++)
/* nothing */;
if (copy[0] != '/' || copy == from) {
copy = copy0;
break;
}
copy[0] = '\0';
to = copy + 1;
for (copy = to; *copy != '\0' && *copy != '/'; copy++)
/* nothing */;
if (copy[0] != '/' || copy[1] != ':') {
copy = copy0;
break;
}
copy[0] = '\0';
modifiers |= FORMAT_SUBSTITUTE;
copy += 2;
break;
} }
/* /*
@ -734,7 +759,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
*ptr = '\0'; *ptr = '\0';
value = ptr + 1; value = ptr + 1;
saved = format_find(ft, copy + 1, modifiers); found = format_find(ft, copy + 1, modifiers);
brackets = 0; brackets = 0;
for (ptr = ptr + 1; *ptr != '\0'; ptr++) { for (ptr = ptr + 1; *ptr != '\0'; ptr++) {
@ -748,29 +773,56 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
if (*ptr == '\0') if (*ptr == '\0')
goto fail; goto fail;
if (saved != NULL && *saved != '\0' && if (found != NULL && *found != '\0' &&
(saved[0] != '0' || saved[1] != '\0')) { (found[0] != '0' || found[1] != '\0')) {
*ptr = '\0'; *ptr = '\0';
} else } else
value = ptr + 1; value = ptr + 1;
value = format_expand(ft, value); value = format_expand(ft, value);
free(saved); free(found);
saved = value;
} else { } else {
saved = value = format_find(ft, copy, modifiers); value = format_find(ft, copy, modifiers);
if (value == NULL) if (value == NULL)
saved = value = xstrdup(""); value = xstrdup("");
}
/* Perform substitution if any. */
if (modifiers & FORMAT_SUBSTITUTE) {
fromlen = strlen(from);
tolen = strlen(to);
newlen = strlen(value) + 1;
copy = new = xmalloc(newlen);
for (ptr = value; *ptr != '\0'; /* nothing */) {
if (strncmp(ptr, from, fromlen) != 0) {
*new++ = *ptr++;
continue;
}
used = new - copy;
newlen += tolen;
copy = xrealloc(copy, newlen);
new = copy + used;
memcpy(new, to, tolen);
new += tolen;
ptr += fromlen;
}
*new = '\0';
free(value);
value = copy;
} }
/* Truncate the value if needed. */ /* Truncate the value if needed. */
if (limit != 0) { if (limit != 0) {
value = trimmed = utf8_trimcstr(value, limit); new = utf8_trimcstr(value, limit);
free(saved); free(value);
saved = trimmed; value = new;
} }
valuelen = strlen(value);
/* Expand the buffer and copy in the value. */ /* Expand the buffer and copy in the value. */
valuelen = strlen(value);
while (*len - *off < valuelen + 1) { while (*len - *off < valuelen + 1) {
*buf = xreallocarray(*buf, 2, *len); *buf = xreallocarray(*buf, 2, *len);
*len *= 2; *len *= 2;
@ -778,7 +830,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
memcpy(*buf + *off, value, valuelen); memcpy(*buf + *off, value, valuelen);
*off += valuelen; *off += valuelen;
free(saved); free(value);
free(copy0); free(copy0);
return (0); return (0);

7
tmux.1
View File

@ -3311,6 +3311,13 @@ prefixes are
and and
.Xr dirname 3 .Xr dirname 3
of the variable respectively. of the variable respectively.
A prefix of the form
.Ql s/foo/bar/:
will substitute
.Ql foo
with
.Ql bar
throughout.
.Pp .Pp
In addition, the first line of a shell command's output may be inserted using In addition, the first line of a shell command's output may be inserted using
.Ql #() . .Ql #() .