mirror of
https://github.com/tmux/tmux.git
synced 2025-09-07 01:56:58 +00:00
Merge branch 'obsd-master'
This commit is contained in:
42
cfg.c
42
cfg.c
@ -81,12 +81,14 @@ int
|
|||||||
load_cfg(const char *path, struct client *c, struct cmdq_item *item, int quiet)
|
load_cfg(const char *path, struct client *c, struct cmdq_item *item, int quiet)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char delim[3] = { '\\', '\\', '\0' };
|
const char delim[3] = { '\\', '\\', '\0' };
|
||||||
u_int found;
|
u_int found = 0;
|
||||||
size_t line = 0;
|
size_t line = 0;
|
||||||
char *buf, *cause1, *p;
|
char *buf, *cause1, *p, *q, *s;
|
||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
struct cmdq_item *new_item;
|
struct cmdq_item *new_item;
|
||||||
|
int condition = 0;
|
||||||
|
struct format_tree *ft;
|
||||||
|
|
||||||
log_debug("loading %s", path);
|
log_debug("loading %s", path);
|
||||||
if ((f = fopen(path, "rb")) == NULL) {
|
if ((f = fopen(path, "rb")) == NULL) {
|
||||||
@ -96,11 +98,9 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int quiet)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
found = 0;
|
|
||||||
while ((buf = fparseln(f, NULL, &line, delim, 0)) != NULL) {
|
while ((buf = fparseln(f, NULL, &line, delim, 0)) != NULL) {
|
||||||
log_debug("%s: %s", path, buf);
|
log_debug("%s: %s", path, buf);
|
||||||
|
|
||||||
/* Skip empty lines. */
|
|
||||||
p = buf;
|
p = buf;
|
||||||
while (isspace((u_char)*p))
|
while (isspace((u_char)*p))
|
||||||
p++;
|
p++;
|
||||||
@ -108,8 +108,38 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int quiet)
|
|||||||
free(buf);
|
free(buf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
q = p + strlen(p) - 1;
|
||||||
|
while (q != p && isspace((u_char)*q))
|
||||||
|
*q-- = '\0';
|
||||||
|
|
||||||
|
if (condition != 0 && strcmp(p, "%endif") == 0) {
|
||||||
|
condition = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strncmp(p, "%if ", 4) == 0) {
|
||||||
|
if (condition != 0) {
|
||||||
|
cfg_add_cause("%s:%zu: nested %%if", path,
|
||||||
|
line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ft = format_create(NULL, FORMAT_NOJOBS);
|
||||||
|
|
||||||
|
s = p + 3;
|
||||||
|
while (isspace((u_char)*s))
|
||||||
|
s++;
|
||||||
|
s = format_expand(ft, s);
|
||||||
|
if (*s != '\0' && (s[0] != '0' || s[1] != '\0'))
|
||||||
|
condition = 1;
|
||||||
|
else
|
||||||
|
condition = -1;
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
format_free(ft);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (condition == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Parse and run the command. */
|
|
||||||
if (cmd_string_parse(p, &cmdlist, path, line, &cause1) != 0) {
|
if (cmd_string_parse(p, &cmdlist, path, line, &cause1) != 0) {
|
||||||
free(buf);
|
free(buf);
|
||||||
if (cause1 == NULL)
|
if (cause1 == NULL)
|
||||||
|
114
format.c
114
format.c
@ -727,6 +727,50 @@ found:
|
|||||||
return (copy);
|
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,
|
* 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.
|
* #{?blah,a,b} is replace with a if blah exists and is nonzero else b.
|
||||||
@ -736,10 +780,10 @@ 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, *found, *new, *value;
|
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;
|
size_t valuelen, newlen, fromlen, tolen, used;
|
||||||
long limit = 0;
|
long limit = 0;
|
||||||
int modifiers = 0, brackets;
|
int modifiers = 0, compare = 0;
|
||||||
|
|
||||||
/* Make a copy of the key. */
|
/* Make a copy of the key. */
|
||||||
copy0 = copy = xmalloc(keylen + 1);
|
copy0 = copy = xmalloc(keylen + 1);
|
||||||
@ -748,7 +792,19 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
|||||||
|
|
||||||
/* Is there a length limit or whatnot? */
|
/* Is there a length limit or whatnot? */
|
||||||
switch (copy[0]) {
|
switch (copy[0]) {
|
||||||
|
case '!':
|
||||||
|
if (copy[1] == '=' && copy[2] == ':') {
|
||||||
|
compare = -1;
|
||||||
|
copy += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case '=':
|
case '=':
|
||||||
|
if (copy[1] == '=' && copy[2] == ':') {
|
||||||
|
compare = 1;
|
||||||
|
copy += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
errno = 0;
|
errno = 0;
|
||||||
limit = strtol(copy + 1, &endptr, 10);
|
limit = strtol(copy + 1, &endptr, 10);
|
||||||
if (errno == ERANGE && (limit == LONG_MIN || limit == LONG_MAX))
|
if (errno == ERANGE && (limit == LONG_MIN || limit == LONG_MAX))
|
||||||
@ -800,39 +856,42 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Is this a comparison or a conditional? */
|
||||||
* Is this a conditional? If so, check it exists and extract either the
|
if (compare != 0) {
|
||||||
* first or second element. If not, look up the key directly.
|
/* Comparison: compare comma-separated left and right. */
|
||||||
*/
|
if (format_choose(copy, &left, &right) != 0)
|
||||||
if (*copy == '?') {
|
goto fail;
|
||||||
ptr = strchr(copy, ',');
|
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)
|
if (ptr == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
|
|
||||||
value = ptr + 1;
|
|
||||||
found = format_find(ft, copy + 1, modifiers);
|
found = format_find(ft, copy + 1, modifiers);
|
||||||
|
if (found == NULL) {
|
||||||
brackets = 0;
|
log_debug("XXX %s", copy + 1);
|
||||||
for (ptr = ptr + 1; *ptr != '\0'; ptr++) {
|
found = format_expand(ft, copy + 1);}
|
||||||
if (*ptr == '{')
|
if (format_choose(ptr + 1, &left, &right) != 0)
|
||||||
brackets++;
|
|
||||||
if (*ptr == '}')
|
|
||||||
brackets--;
|
|
||||||
if (*ptr == ',' && brackets == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (*ptr == '\0')
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (found != NULL && *found != '\0' &&
|
if (format_true(found))
|
||||||
(found[0] != '0' || found[1] != '\0')) {
|
value = format_expand(ft, left);
|
||||||
*ptr = '\0';
|
else
|
||||||
} else
|
value = format_expand(ft, right);
|
||||||
value = ptr + 1;
|
|
||||||
value = format_expand(ft, value);
|
|
||||||
free(found);
|
free(found);
|
||||||
} else {
|
} else {
|
||||||
|
/* Neither: look up directly. */
|
||||||
value = format_find(ft, copy, modifiers);
|
value = format_find(ft, copy, modifiers);
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
value = xstrdup("");
|
value = xstrdup("");
|
||||||
@ -954,6 +1013,9 @@ format_expand(struct format_tree *ft, const char *fmt)
|
|||||||
break;
|
break;
|
||||||
n = ptr - fmt;
|
n = ptr - fmt;
|
||||||
|
|
||||||
|
if (ft->flags & FORMAT_NOJOBS)
|
||||||
|
out = xstrdup("");
|
||||||
|
else
|
||||||
out = format_job_get(ft, xstrndup(fmt, n));
|
out = format_job_get(ft, xstrndup(fmt, n));
|
||||||
outlen = strlen(out);
|
outlen = strlen(out);
|
||||||
|
|
||||||
|
39
tmux.1
39
tmux.1
@ -934,6 +934,30 @@ If
|
|||||||
is given, no error will be returned if
|
is given, no error will be returned if
|
||||||
.Ar path
|
.Ar path
|
||||||
does not exist.
|
does not exist.
|
||||||
|
.Pp
|
||||||
|
Within a configuration file, commands may be made conditional by surrounding
|
||||||
|
them with
|
||||||
|
.Em %if
|
||||||
|
and
|
||||||
|
.Em %endif
|
||||||
|
lines.
|
||||||
|
The argument to
|
||||||
|
.Em %if
|
||||||
|
is expanded as a format and if it evaluates to false
|
||||||
|
.Ns ( Ql 0
|
||||||
|
or empty), subsequent lines are ignored until
|
||||||
|
.Em %endif .
|
||||||
|
For example:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
%if #{==:#{host},myhost}
|
||||||
|
set -g status-style bg=red
|
||||||
|
%endif
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Will change the status line to red if running on
|
||||||
|
.Ql myhost .
|
||||||
|
.Em %if
|
||||||
|
may not be nested.
|
||||||
.It Ic start-server
|
.It Ic start-server
|
||||||
.D1 (alias: Ic start )
|
.D1 (alias: Ic start )
|
||||||
Start the
|
Start the
|
||||||
@ -3401,6 +3425,21 @@ is enabled, or
|
|||||||
.Ql no
|
.Ql no
|
||||||
if not.
|
if not.
|
||||||
.Pp
|
.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
|
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
@ -1570,6 +1570,7 @@ char *paste_make_sample(struct paste_buffer *);
|
|||||||
/* format.c */
|
/* format.c */
|
||||||
#define FORMAT_STATUS 0x1
|
#define FORMAT_STATUS 0x1
|
||||||
#define FORMAT_FORCE 0x2
|
#define FORMAT_FORCE 0x2
|
||||||
|
#define FORMAT_NOJOBS 0x4
|
||||||
struct format_tree;
|
struct format_tree;
|
||||||
struct format_tree *format_create(struct cmdq_item *, int);
|
struct format_tree *format_create(struct cmdq_item *, int);
|
||||||
void format_free(struct format_tree *);
|
void format_free(struct format_tree *);
|
||||||
|
Reference in New Issue
Block a user