mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Add s/foo/bar/: prefix for formats to substitute bar for foo.
This commit is contained in:
		
							
								
								
									
										80
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										80
									
								
								format.c
									
									
									
									
									
								
							@@ -99,6 +99,7 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
 | 
			
		||||
#define FORMAT_TIMESTRING 0x1
 | 
			
		||||
#define FORMAT_BASENAME 0x2
 | 
			
		||||
#define FORMAT_DIRNAME 0x4
 | 
			
		||||
#define FORMAT_SUBSTITUTE 0x8
 | 
			
		||||
 | 
			
		||||
/* Entry in format tree. */
 | 
			
		||||
struct format_entry {
 | 
			
		||||
@@ -682,8 +683,9 @@ int
 | 
			
		||||
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, *saved, *trimmed, *value;
 | 
			
		||||
	size_t		 valuelen;
 | 
			
		||||
	char		*copy, *copy0, *endptr, *ptr, *found, *new, *value;
 | 
			
		||||
	char		*from = NULL, *to = NULL;
 | 
			
		||||
	size_t		 valuelen, newlen, fromlen, tolen, used;
 | 
			
		||||
	u_long		 limit = 0;
 | 
			
		||||
	int		 modifiers = 0, brackets;
 | 
			
		||||
 | 
			
		||||
@@ -721,6 +723,29 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
		modifiers |= FORMAT_TIMESTRING;
 | 
			
		||||
		copy += 2;
 | 
			
		||||
		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';
 | 
			
		||||
 | 
			
		||||
		value = ptr + 1;
 | 
			
		||||
		saved = format_find(ft, copy + 1, modifiers);
 | 
			
		||||
		found = format_find(ft, copy + 1, modifiers);
 | 
			
		||||
 | 
			
		||||
		brackets = 0;
 | 
			
		||||
		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')
 | 
			
		||||
			goto fail;
 | 
			
		||||
 | 
			
		||||
		if (saved != NULL && *saved != '\0' &&
 | 
			
		||||
		    (saved[0] != '0' || saved[1] != '\0')) {
 | 
			
		||||
		if (found != NULL && *found != '\0' &&
 | 
			
		||||
		    (found[0] != '0' || found[1] != '\0')) {
 | 
			
		||||
			*ptr = '\0';
 | 
			
		||||
		} else
 | 
			
		||||
			value = ptr + 1;
 | 
			
		||||
		value = format_expand(ft, value);
 | 
			
		||||
		free(saved);
 | 
			
		||||
		saved = value;
 | 
			
		||||
		free(found);
 | 
			
		||||
	} else {
 | 
			
		||||
		saved = value = format_find(ft, copy, modifiers);
 | 
			
		||||
		value = format_find(ft, copy, modifiers);
 | 
			
		||||
		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. */
 | 
			
		||||
	if (limit != 0) {
 | 
			
		||||
		value = trimmed = utf8_trimcstr(value, limit);
 | 
			
		||||
		free(saved);
 | 
			
		||||
		saved = trimmed;
 | 
			
		||||
		new = utf8_trimcstr(value, limit);
 | 
			
		||||
		free(value);
 | 
			
		||||
		value = new;
 | 
			
		||||
	}
 | 
			
		||||
	valuelen = strlen(value);
 | 
			
		||||
 | 
			
		||||
	/* Expand the buffer and copy in the value. */
 | 
			
		||||
	valuelen = strlen(value);
 | 
			
		||||
	while (*len - *off < valuelen + 1) {
 | 
			
		||||
		*buf = xreallocarray(*buf, 2, *len);
 | 
			
		||||
		*len *= 2;
 | 
			
		||||
@@ -778,7 +830,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
	memcpy(*buf + *off, value, valuelen);
 | 
			
		||||
	*off += valuelen;
 | 
			
		||||
 | 
			
		||||
	free(saved);
 | 
			
		||||
	free(value);
 | 
			
		||||
	free(copy0);
 | 
			
		||||
	return (0);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user