mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 01:34:18 +00:00 
			
		
		
		
	Add some number operators for formats, from Tyler Culp.
This commit is contained in:
		
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							@@ -130,7 +130,7 @@ CDIAGFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
 | 
			
		||||
 | 
			
		||||
CFLAGS += -I${.CURDIR}
 | 
			
		||||
 | 
			
		||||
LDADD=  -lutil -lcurses -levent
 | 
			
		||||
DPADD=  ${LIBUTIL} ${LIBCURSES} ${LIBEVENT}
 | 
			
		||||
LDADD=  -lutil -lcurses -levent -lm
 | 
			
		||||
DPADD=  ${LIBUTIL} ${LIBCURSES} ${LIBEVENT} ${LIBM}
 | 
			
		||||
 | 
			
		||||
.include <bsd.prog.mk>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										117
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								format.c
									
									
									
									
									
								
							@@ -23,6 +23,7 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fnmatch.h>
 | 
			
		||||
#include <libgen.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
@@ -49,7 +50,6 @@ static void	 format_add_tv(struct format_tree *, const char *,
 | 
			
		||||
		     struct timeval *);
 | 
			
		||||
static int	 format_replace(struct format_tree *, const char *, size_t,
 | 
			
		||||
		     char **, size_t *, size_t *);
 | 
			
		||||
 | 
			
		||||
static void	 format_defaults_session(struct format_tree *,
 | 
			
		||||
		     struct session *);
 | 
			
		||||
static void	 format_defaults_client(struct format_tree *, struct client *);
 | 
			
		||||
@@ -1528,7 +1528,7 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Now try single character with arguments. */
 | 
			
		||||
		if (strchr("mCs=p", cp[0]) == NULL)
 | 
			
		||||
		if (strchr("mCs=pe", cp[0]) == NULL)
 | 
			
		||||
			break;
 | 
			
		||||
		c = cp[0];
 | 
			
		||||
 | 
			
		||||
@@ -1784,6 +1784,108 @@ format_loop_panes(struct format_tree *ft, const char *fmt)
 | 
			
		||||
	return (value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
format_replace_expression(struct format_modifier *mexp, struct format_tree *ft,
 | 
			
		||||
    const char *copy)
 | 
			
		||||
{
 | 
			
		||||
	int		 argc = mexp->argc;
 | 
			
		||||
	const char	*errstr;
 | 
			
		||||
	char		*endch, *value, *left = NULL, *right = NULL;
 | 
			
		||||
	int		 use_fp = 0;
 | 
			
		||||
	u_int		 prec = 0;
 | 
			
		||||
	double		 mleft, mright, result;
 | 
			
		||||
	enum { ADD, SUBTRACT, MULTIPLY, DIVIDE, MODULUS } operator;
 | 
			
		||||
 | 
			
		||||
	if (strcmp(mexp->argv[0], "+") == 0)
 | 
			
		||||
		operator = ADD;
 | 
			
		||||
	else if (strcmp(mexp->argv[0], "-") == 0)
 | 
			
		||||
		operator = SUBTRACT;
 | 
			
		||||
	else if (strcmp(mexp->argv[0], "*") == 0)
 | 
			
		||||
		operator = MULTIPLY;
 | 
			
		||||
	else if (strcmp(mexp->argv[0], "/") == 0)
 | 
			
		||||
		operator = DIVIDE;
 | 
			
		||||
	else if (strcmp(mexp->argv[0], "%") == 0 ||
 | 
			
		||||
	    strcmp(mexp->argv[0], "m") == 0)
 | 
			
		||||
		operator = MODULUS;
 | 
			
		||||
	else {
 | 
			
		||||
		format_log(ft, "expression has no valid operator: '%s'",
 | 
			
		||||
		    mexp->argv[0]);
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* The second argument may be flags. */
 | 
			
		||||
	if (argc >= 2 && strchr(mexp->argv[1], 'f') != NULL) {
 | 
			
		||||
		use_fp = 1;
 | 
			
		||||
		prec = 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* The third argument may be precision. */
 | 
			
		||||
	if (argc >= 3) {
 | 
			
		||||
		prec = strtonum(mexp->argv[2], INT_MIN, INT_MAX, &errstr);
 | 
			
		||||
		if (errstr != NULL) {
 | 
			
		||||
			format_log (ft, "expression precision %s: %s", errstr,
 | 
			
		||||
			    mexp->argv[2]);
 | 
			
		||||
			goto fail;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (format_choose(ft, copy, &left, &right, 1) != 0) {
 | 
			
		||||
		format_log(ft, "expression syntax error");
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mleft = strtod(left, &endch);
 | 
			
		||||
	if (*endch != '\0') {
 | 
			
		||||
		format_log(ft, "expression left side is invalid: %s", left);
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mright = strtod(right, &endch);
 | 
			
		||||
	if (*endch != '\0') {
 | 
			
		||||
		format_log(ft, "expression right side is invalid: %s", right);
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!use_fp) {
 | 
			
		||||
		mleft = (long long)mleft;
 | 
			
		||||
		mright = (long long)mright;
 | 
			
		||||
	}
 | 
			
		||||
	format_log(ft, "expression left side is: %.*f", prec, mleft);
 | 
			
		||||
	format_log(ft, "expression right side is:  %.*f", prec, mright);
 | 
			
		||||
 | 
			
		||||
	switch (operator) {
 | 
			
		||||
	case ADD:
 | 
			
		||||
		result = mleft + mright;
 | 
			
		||||
		break;
 | 
			
		||||
	case SUBTRACT:
 | 
			
		||||
		result = mleft - mright;
 | 
			
		||||
		break;
 | 
			
		||||
	case MULTIPLY:
 | 
			
		||||
		result = mleft * mright;
 | 
			
		||||
		break;
 | 
			
		||||
	case DIVIDE:
 | 
			
		||||
		result = mleft / mright;
 | 
			
		||||
		break;
 | 
			
		||||
	case MODULUS:
 | 
			
		||||
		result = fmod(mleft, mright);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	if (use_fp)
 | 
			
		||||
		xasprintf(&value, "%.*f", prec, result);
 | 
			
		||||
	else
 | 
			
		||||
		xasprintf(&value, "%.*f", prec, (double)(long long)result);
 | 
			
		||||
	format_log(ft, "expression result is %s", value);
 | 
			
		||||
 | 
			
		||||
	free(right);
 | 
			
		||||
	free(left);
 | 
			
		||||
	return value;
 | 
			
		||||
 | 
			
		||||
fail:
 | 
			
		||||
	free(right);
 | 
			
		||||
	free(left);
 | 
			
		||||
	return (NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Replace a key. */
 | 
			
		||||
static int
 | 
			
		||||
format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
@@ -1796,7 +1898,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
	size_t			  valuelen;
 | 
			
		||||
	int			  modifiers = 0, limit = 0, width = 0, j;
 | 
			
		||||
	struct format_modifier   *list, *fm, *cmp = NULL, *search = NULL;
 | 
			
		||||
	struct format_modifier	**sub = NULL;
 | 
			
		||||
	struct format_modifier	**sub = NULL, *mexp = NULL;
 | 
			
		||||
	u_int			  i, count, nsub = 0;
 | 
			
		||||
 | 
			
		||||
	/* Make a copy of the key. */
 | 
			
		||||
@@ -1848,6 +1950,11 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
				if (errptr != NULL)
 | 
			
		||||
					width = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			case 'e':
 | 
			
		||||
				if (fm->argc < 1 || fm->argc > 3)
 | 
			
		||||
					break;
 | 
			
		||||
			    mexp = fm;
 | 
			
		||||
				break;
 | 
			
		||||
			case 'l':
 | 
			
		||||
				modifiers |= FORMAT_LITERAL;
 | 
			
		||||
				break;
 | 
			
		||||
@@ -2024,6 +2131,10 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
 | 
			
		||||
 | 
			
		||||
		free(condition);
 | 
			
		||||
		free(found);
 | 
			
		||||
	} else if (mexp != NULL) {
 | 
			
		||||
		value = format_replace_expression(mexp, ft, copy);
 | 
			
		||||
		if (value == NULL)
 | 
			
		||||
			value = xstrdup("");
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Neither: look up directly. */
 | 
			
		||||
		value = format_find(ft, copy, modifiers);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								tmux.1
									
									
									
									
									
								
							@@ -4107,7 +4107,7 @@ specifies an
 | 
			
		||||
.Xr fnmatch 3
 | 
			
		||||
or regular expression comparison.
 | 
			
		||||
The first argument is the pattern and the second the string to compare.
 | 
			
		||||
An optional third argument specifies flags:
 | 
			
		||||
An optional argument specifies flags:
 | 
			
		||||
.Ql r
 | 
			
		||||
means the pattern is a regular expression instead of the default
 | 
			
		||||
.Xr fnmatch 3
 | 
			
		||||
@@ -4134,6 +4134,38 @@ ignores case.
 | 
			
		||||
For example:
 | 
			
		||||
.Ql #{C/r:^Start}
 | 
			
		||||
.Pp
 | 
			
		||||
Numeric operators may be performed by prefixing two comma-separated alternatives with an
 | 
			
		||||
.Ql e
 | 
			
		||||
and an operator.
 | 
			
		||||
An optional
 | 
			
		||||
.Ql f
 | 
			
		||||
flag may be given after the operator to use floating point numbers, otherwise integers are used.
 | 
			
		||||
This may be followed by a number giving the number of decimal places to use for the result.
 | 
			
		||||
The available operators are:
 | 
			
		||||
addition
 | 
			
		||||
.Ql + ,
 | 
			
		||||
subtraction
 | 
			
		||||
.Ql - ,
 | 
			
		||||
multiplication
 | 
			
		||||
.Ql * ,
 | 
			
		||||
division
 | 
			
		||||
.Ql / ,
 | 
			
		||||
and modulus
 | 
			
		||||
.Ql m
 | 
			
		||||
or
 | 
			
		||||
.Ql %
 | 
			
		||||
(note that
 | 
			
		||||
.Ql %
 | 
			
		||||
must be escaped as
 | 
			
		||||
.Ql %%
 | 
			
		||||
in formats which are also expanded by
 | 
			
		||||
.Xr strftime 3 ) .
 | 
			
		||||
For example,
 | 
			
		||||
.Ql #{e|*|f|4:5.5,3}
 | 
			
		||||
multiplies 5.5 by 3 for a result with four decimal places and
 | 
			
		||||
.Ql #{e|%%:7,3}
 | 
			
		||||
returns the modulus of 7 and 3.
 | 
			
		||||
.Pp
 | 
			
		||||
A limit may be placed on the length of the resultant string by prefixing it
 | 
			
		||||
by an
 | 
			
		||||
.Ql = ,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1822,6 +1822,7 @@ char		*paste_make_sample(struct paste_buffer *);
 | 
			
		||||
#define FORMAT_PANE 0x80000000U
 | 
			
		||||
#define FORMAT_WINDOW 0x40000000U
 | 
			
		||||
struct format_tree;
 | 
			
		||||
struct format_modifier;
 | 
			
		||||
const char	*format_skip(const char *, const char *);
 | 
			
		||||
int		 format_true(const char *);
 | 
			
		||||
struct format_tree *format_create(struct client *, struct cmdq_item *, int,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user