mirror of
https://github.com/tmux/tmux.git
synced 2025-01-07 16:28:48 +00:00
Add some number operators for formats, from Tyler Culp.
This commit is contained in:
parent
2991f4aad0
commit
c820585dd0
4
Makefile
4
Makefile
@ -130,7 +130,7 @@ CDIAGFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
|
|||||||
|
|
||||||
CFLAGS += -I${.CURDIR}
|
CFLAGS += -I${.CURDIR}
|
||||||
|
|
||||||
LDADD= -lutil -lcurses -levent
|
LDADD= -lutil -lcurses -levent -lm
|
||||||
DPADD= ${LIBUTIL} ${LIBCURSES} ${LIBEVENT}
|
DPADD= ${LIBUTIL} ${LIBCURSES} ${LIBEVENT} ${LIBM}
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
117
format.c
117
format.c
@ -23,6 +23,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <math.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -49,7 +50,6 @@ static void format_add_tv(struct format_tree *, const char *,
|
|||||||
struct timeval *);
|
struct timeval *);
|
||||||
static int format_replace(struct format_tree *, const char *, size_t,
|
static int format_replace(struct format_tree *, const char *, size_t,
|
||||||
char **, size_t *, size_t *);
|
char **, size_t *, size_t *);
|
||||||
|
|
||||||
static void format_defaults_session(struct format_tree *,
|
static void format_defaults_session(struct format_tree *,
|
||||||
struct session *);
|
struct session *);
|
||||||
static void format_defaults_client(struct format_tree *, struct client *);
|
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. */
|
/* Now try single character with arguments. */
|
||||||
if (strchr("mCs=p", cp[0]) == NULL)
|
if (strchr("mCs=pe", cp[0]) == NULL)
|
||||||
break;
|
break;
|
||||||
c = cp[0];
|
c = cp[0];
|
||||||
|
|
||||||
@ -1784,6 +1784,108 @@ format_loop_panes(struct format_tree *ft, const char *fmt)
|
|||||||
return (value);
|
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. */
|
/* Replace a key. */
|
||||||
static int
|
static 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,
|
||||||
@ -1796,7 +1898,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
|||||||
size_t valuelen;
|
size_t valuelen;
|
||||||
int modifiers = 0, limit = 0, width = 0, j;
|
int modifiers = 0, limit = 0, width = 0, j;
|
||||||
struct format_modifier *list, *fm, *cmp = NULL, *search = NULL;
|
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;
|
u_int i, count, nsub = 0;
|
||||||
|
|
||||||
/* Make a copy of the key. */
|
/* 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)
|
if (errptr != NULL)
|
||||||
width = 0;
|
width = 0;
|
||||||
break;
|
break;
|
||||||
|
case 'e':
|
||||||
|
if (fm->argc < 1 || fm->argc > 3)
|
||||||
|
break;
|
||||||
|
mexp = fm;
|
||||||
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
modifiers |= FORMAT_LITERAL;
|
modifiers |= FORMAT_LITERAL;
|
||||||
break;
|
break;
|
||||||
@ -2024,6 +2131,10 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
|||||||
|
|
||||||
free(condition);
|
free(condition);
|
||||||
free(found);
|
free(found);
|
||||||
|
} else if (mexp != NULL) {
|
||||||
|
value = format_replace_expression(mexp, ft, copy);
|
||||||
|
if (value == NULL)
|
||||||
|
value = xstrdup("");
|
||||||
} else {
|
} else {
|
||||||
/* Neither: look up directly. */
|
/* Neither: look up directly. */
|
||||||
value = format_find(ft, copy, modifiers);
|
value = format_find(ft, copy, modifiers);
|
||||||
|
34
tmux.1
34
tmux.1
@ -4107,7 +4107,7 @@ specifies an
|
|||||||
.Xr fnmatch 3
|
.Xr fnmatch 3
|
||||||
or regular expression comparison.
|
or regular expression comparison.
|
||||||
The first argument is the pattern and the second the string to compare.
|
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
|
.Ql r
|
||||||
means the pattern is a regular expression instead of the default
|
means the pattern is a regular expression instead of the default
|
||||||
.Xr fnmatch 3
|
.Xr fnmatch 3
|
||||||
@ -4134,6 +4134,38 @@ ignores case.
|
|||||||
For example:
|
For example:
|
||||||
.Ql #{C/r:^Start}
|
.Ql #{C/r:^Start}
|
||||||
.Pp
|
.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
|
A limit may be placed on the length of the resultant string by prefixing it
|
||||||
by an
|
by an
|
||||||
.Ql = ,
|
.Ql = ,
|
||||||
|
1
tmux.h
1
tmux.h
@ -1822,6 +1822,7 @@ char *paste_make_sample(struct paste_buffer *);
|
|||||||
#define FORMAT_PANE 0x80000000U
|
#define FORMAT_PANE 0x80000000U
|
||||||
#define FORMAT_WINDOW 0x40000000U
|
#define FORMAT_WINDOW 0x40000000U
|
||||||
struct format_tree;
|
struct format_tree;
|
||||||
|
struct format_modifier;
|
||||||
const char *format_skip(const char *, const char *);
|
const char *format_skip(const char *, const char *);
|
||||||
int format_true(const char *);
|
int format_true(const char *);
|
||||||
struct format_tree *format_create(struct client *, struct cmdq_item *, int,
|
struct format_tree *format_create(struct client *, struct cmdq_item *, int,
|
||||||
|
Loading…
Reference in New Issue
Block a user