mirror of
https://github.com/tmux/tmux.git
synced 2025-01-07 16:28:48 +00:00
Permit embedded colour and attributes in status-left and status-right using new
#[] special characters, for example #[fg=red,bg=blue,blink].
This commit is contained in:
parent
ffab22bb35
commit
e97006b102
172
screen-write.c
172
screen-write.c
@ -52,6 +52,41 @@ screen_write_putc(
|
|||||||
screen_write_cell(ctx, gc, NULL);
|
screen_write_cell(ctx, gc, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate string length, with embedded formatting. */
|
||||||
|
size_t printflike2
|
||||||
|
screen_write_cstrlen(int utf8flag, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char *msg, *msg2, *ptr, *ptr2;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
xvasprintf(&msg, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
msg2 = xmalloc(strlen(msg) + 1);
|
||||||
|
|
||||||
|
ptr = msg;
|
||||||
|
ptr2 = msg2;
|
||||||
|
while (*ptr != '\0') {
|
||||||
|
if (ptr[0] == '#' && ptr[1] == '[') {
|
||||||
|
while (*ptr != ']' && *ptr != '\0')
|
||||||
|
ptr++;
|
||||||
|
if (*ptr == ']')
|
||||||
|
ptr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*ptr2++ = *ptr++;
|
||||||
|
}
|
||||||
|
*ptr2 = '\0';
|
||||||
|
|
||||||
|
size = screen_write_strlen(utf8flag, "%s", msg2);
|
||||||
|
|
||||||
|
xfree(msg);
|
||||||
|
xfree(msg2);
|
||||||
|
|
||||||
|
return (size);
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate string length. */
|
/* Calculate string length. */
|
||||||
size_t printflike2
|
size_t printflike2
|
||||||
screen_write_strlen(int utf8flag, const char *fmt, ...)
|
screen_write_strlen(int utf8flag, const char *fmt, ...)
|
||||||
@ -177,6 +212,143 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
|
|||||||
xfree(msg);
|
xfree(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write string, similar to nputs, but with embedded formatting (#[]). */
|
||||||
|
void printflike5
|
||||||
|
screen_write_cnputs(struct screen_write_ctx *ctx,
|
||||||
|
ssize_t maxlen, struct grid_cell *gc, int utf8flag, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
struct grid_cell lgc;
|
||||||
|
va_list ap;
|
||||||
|
char *msg;
|
||||||
|
u_char *ptr, *last, utf8buf[4];
|
||||||
|
size_t left, size = 0;
|
||||||
|
int width;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
xvasprintf(&msg, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
memcpy(&lgc, gc, sizeof lgc);
|
||||||
|
|
||||||
|
ptr = msg;
|
||||||
|
while (*ptr != '\0') {
|
||||||
|
if (ptr[0] == '#' && ptr[1] == '[') {
|
||||||
|
ptr += 2;
|
||||||
|
last = ptr + strcspn(ptr, "]");
|
||||||
|
if (*last == '\0') {
|
||||||
|
/* No ]. Not much point in doing anything. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*last = '\0';
|
||||||
|
|
||||||
|
screen_write_parsestyle(gc, &lgc, ptr);
|
||||||
|
ptr = last + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (utf8flag && *ptr > 0x7f) {
|
||||||
|
memset(utf8buf, 0xff, sizeof utf8buf);
|
||||||
|
|
||||||
|
left = strlen(ptr);
|
||||||
|
if (*ptr >= 0xc2 && *ptr <= 0xdf && left >= 2) {
|
||||||
|
memcpy(utf8buf, ptr, 2);
|
||||||
|
ptr += 2;
|
||||||
|
} else if (*ptr >= 0xe0 && *ptr <= 0xef && left >= 3) {
|
||||||
|
memcpy(utf8buf, ptr, 3);
|
||||||
|
ptr += 3;
|
||||||
|
} else if (*ptr >= 0xf0 && *ptr <= 0xf4 && left >= 4) {
|
||||||
|
memcpy(utf8buf, ptr, 4);
|
||||||
|
ptr += 4;
|
||||||
|
} else {
|
||||||
|
*utf8buf = *ptr;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
width = utf8_width(utf8buf);
|
||||||
|
if (maxlen > 0 && size + width > (size_t) maxlen) {
|
||||||
|
while (size < (size_t) maxlen) {
|
||||||
|
screen_write_putc(ctx, gc, ' ');
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size += width;
|
||||||
|
|
||||||
|
lgc.flags |= GRID_FLAG_UTF8;
|
||||||
|
screen_write_cell(ctx, &lgc, utf8buf);
|
||||||
|
lgc.flags &= ~GRID_FLAG_UTF8;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (maxlen > 0 && size + 1 > (size_t) maxlen)
|
||||||
|
break;
|
||||||
|
|
||||||
|
size++;
|
||||||
|
screen_write_putc(ctx, &lgc, *ptr);
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse an embedded style of the form "fg=colour,bg=colour,bright,...". */
|
||||||
|
void
|
||||||
|
screen_write_parsestyle(
|
||||||
|
struct grid_cell *defgc, struct grid_cell *gc, const char *in)
|
||||||
|
{
|
||||||
|
const char delimiters[] = " ,";
|
||||||
|
char tmp[32];
|
||||||
|
int val;
|
||||||
|
size_t end;
|
||||||
|
u_char fg, bg, attr;
|
||||||
|
|
||||||
|
if (*in == '\0')
|
||||||
|
return;
|
||||||
|
if (strchr(delimiters, in[strlen(in) - 1]) != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fg = gc->fg;
|
||||||
|
bg = gc->bg;
|
||||||
|
attr = 0;
|
||||||
|
do {
|
||||||
|
end = strcspn(in, delimiters);
|
||||||
|
if (end > (sizeof tmp) - 1)
|
||||||
|
return;
|
||||||
|
memcpy(tmp, in, end);
|
||||||
|
tmp[end] = '\0';
|
||||||
|
|
||||||
|
if (strcasecmp(tmp, "default") == 0) {
|
||||||
|
fg = defgc->fg;
|
||||||
|
bg = defgc->bg;
|
||||||
|
attr = defgc->attr;
|
||||||
|
} else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
|
||||||
|
if ((val = colour_fromstring(tmp + 3)) == -1)
|
||||||
|
return;
|
||||||
|
if (*in == 'f' || *in == 'F') {
|
||||||
|
if (val != 8)
|
||||||
|
fg = val;
|
||||||
|
else
|
||||||
|
fg = defgc->fg;
|
||||||
|
} else if (*in == 'b' || *in == 'B') {
|
||||||
|
if (val != 8)
|
||||||
|
bg = val;
|
||||||
|
else
|
||||||
|
bg = defgc->bg;
|
||||||
|
} else
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if ((val = attributes_fromstring(tmp)) == -1)
|
||||||
|
return;
|
||||||
|
attr |= val;
|
||||||
|
}
|
||||||
|
|
||||||
|
in += end + strspn(in + end, delimiters);
|
||||||
|
} while (*in != '\0');
|
||||||
|
gc->fg = fg;
|
||||||
|
gc->bg = bg;
|
||||||
|
gc->attr = attr;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy from another screen. */
|
/* Copy from another screen. */
|
||||||
void
|
void
|
||||||
screen_write_copy(struct screen_write_ctx *ctx,
|
screen_write_copy(struct screen_write_ctx *ctx,
|
||||||
|
22
status.c
22
status.c
@ -107,14 +107,14 @@ status_redraw(struct client *c)
|
|||||||
left = status_replace(s, options_get_string(
|
left = status_replace(s, options_get_string(
|
||||||
&s->options, "status-left"), c->status_timer.tv_sec);
|
&s->options, "status-left"), c->status_timer.tv_sec);
|
||||||
llen = options_get_number(&s->options, "status-left-length");
|
llen = options_get_number(&s->options, "status-left-length");
|
||||||
llen2 = screen_write_strlen(utf8flag, "%s", left);
|
llen2 = screen_write_cstrlen(utf8flag, "%s", left);
|
||||||
if (llen2 < llen)
|
if (llen2 < llen)
|
||||||
llen = llen2;
|
llen = llen2;
|
||||||
|
|
||||||
right = status_replace(s, options_get_string(
|
right = status_replace(s, options_get_string(
|
||||||
&s->options, "status-right"), c->status_timer.tv_sec);
|
&s->options, "status-right"), c->status_timer.tv_sec);
|
||||||
rlen = options_get_number(&s->options, "status-right-length");
|
rlen = options_get_number(&s->options, "status-right-length");
|
||||||
rlen2 = screen_write_strlen(utf8flag, "%s", right);
|
rlen2 = screen_write_cstrlen(utf8flag, "%s", right);
|
||||||
if (rlen2 < rlen)
|
if (rlen2 < rlen)
|
||||||
rlen = rlen2;
|
rlen = rlen2;
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ draw:
|
|||||||
screen_write_start(&ctx, NULL, &c->status);
|
screen_write_start(&ctx, NULL, &c->status);
|
||||||
if (llen != 0) {
|
if (llen != 0) {
|
||||||
screen_write_cursormove(&ctx, 0, yy);
|
screen_write_cursormove(&ctx, 0, yy);
|
||||||
screen_write_nputs(&ctx, llen, &sl_stdgc, utf8flag, "%s", left);
|
screen_write_cnputs(&ctx, llen, &sl_stdgc, utf8flag, "%s", left);
|
||||||
screen_write_putc(&ctx, &stdgc, ' ');
|
screen_write_putc(&ctx, &stdgc, ' ');
|
||||||
if (larrow)
|
if (larrow)
|
||||||
screen_write_putc(&ctx, &stdgc, ' ');
|
screen_write_putc(&ctx, &stdgc, ' ');
|
||||||
@ -266,7 +266,7 @@ draw:
|
|||||||
if (rlen != 0) {
|
if (rlen != 0) {
|
||||||
screen_write_cursormove(&ctx, c->tty.sx - rlen - 1, yy);
|
screen_write_cursormove(&ctx, c->tty.sx - rlen - 1, yy);
|
||||||
screen_write_putc(&ctx, &stdgc, ' ');
|
screen_write_putc(&ctx, &stdgc, ' ');
|
||||||
screen_write_nputs(&ctx, rlen, &sr_stdgc, utf8flag, "%s", right);
|
screen_write_cnputs(&ctx, rlen, &sr_stdgc, utf8flag, "%s", right);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw the arrows. */
|
/* Draw the arrows. */
|
||||||
@ -400,6 +400,20 @@ status_replace(struct session *s, const char *fmt, time_t t)
|
|||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case '[':
|
||||||
|
/*
|
||||||
|
* Embedded style, handled at display time.
|
||||||
|
* Leave present and skip input until ].
|
||||||
|
*/
|
||||||
|
*optr++ = '#';
|
||||||
|
|
||||||
|
iptr--; /* include [ */
|
||||||
|
while (*iptr != ']' && *iptr != '\0') {
|
||||||
|
if (optr >= out + (sizeof out) - 1)
|
||||||
|
break;
|
||||||
|
*optr++ = *iptr++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case '#':
|
case '#':
|
||||||
*optr++ = '#';
|
*optr++ = '#';
|
||||||
break;
|
break;
|
||||||
|
20
tmux.1
20
tmux.1
@ -1316,10 +1316,11 @@ will be passed through
|
|||||||
before being used.
|
before being used.
|
||||||
By default, the session name is shown.
|
By default, the session name is shown.
|
||||||
.Ar string
|
.Ar string
|
||||||
may contain any of the following special character pairs:
|
may contain any of the following special character sequences:
|
||||||
.Bl -column "Character pair" "Replaced with" -offset indent
|
.Bl -column "Character pair" "Replaced with" -offset indent
|
||||||
.It Sy "Character pair" Ta Sy "Replaced with"
|
.It Sy "Character pair" Ta Sy "Replaced with"
|
||||||
.It Li "#(command)" Ta "First line of command's output"
|
.It Li "#(command)" Ta "First line of command's output"
|
||||||
|
.It Li "#[attributes]" Ta "Colour or attribute change"
|
||||||
.It Li "#H" Ta "Hostname of local host"
|
.It Li "#H" Ta "Hostname of local host"
|
||||||
.It Li "#I" Ta "Current window index"
|
.It Li "#I" Ta "Current window index"
|
||||||
.It Li "#P" Ta "Current pane index"
|
.It Li "#P" Ta "Current pane index"
|
||||||
@ -1329,6 +1330,23 @@ may contain any of the following special character pairs:
|
|||||||
.It Li "##" Ta "A literal" Ql #
|
.It Li "##" Ta "A literal" Ql #
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
|
The #(command) form executes
|
||||||
|
.Ql command
|
||||||
|
as a shell command and inserts the first line of its output.
|
||||||
|
#[attributes] allows a comma-separated list of attributes to be specified,
|
||||||
|
these may be
|
||||||
|
.Ql fg=colour
|
||||||
|
to set the foreground colour,
|
||||||
|
.Ql bg=colour
|
||||||
|
to set the background colour, or one of the attributes described under the
|
||||||
|
.Ic message-attr
|
||||||
|
option.
|
||||||
|
Examples are:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
#(sysctl vm.loadavg)
|
||||||
|
#[fg=yellow,bold]#(apm -l)%%#[default] [#S]
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
Where appropriate, these may be prefixed with a number to specify the maximum
|
Where appropriate, these may be prefixed with a number to specify the maximum
|
||||||
length, for example
|
length, for example
|
||||||
.Ql #24T .
|
.Ql #24T .
|
||||||
|
5
tmux.h
5
tmux.h
@ -1533,6 +1533,9 @@ char *grid_view_string_cells(struct grid *, u_int, u_int, u_int);
|
|||||||
void screen_write_start(
|
void screen_write_start(
|
||||||
struct screen_write_ctx *, struct window_pane *, struct screen *);
|
struct screen_write_ctx *, struct window_pane *, struct screen *);
|
||||||
void screen_write_stop(struct screen_write_ctx *);
|
void screen_write_stop(struct screen_write_ctx *);
|
||||||
|
size_t printflike2 screen_write_cstrlen(int, const char *, ...);
|
||||||
|
void printflike5 screen_write_cnputs(struct screen_write_ctx *,
|
||||||
|
ssize_t, struct grid_cell *, int, const char *, ...);
|
||||||
size_t printflike2 screen_write_strlen(int, const char *, ...);
|
size_t printflike2 screen_write_strlen(int, const char *, ...);
|
||||||
void printflike3 screen_write_puts(struct screen_write_ctx *,
|
void printflike3 screen_write_puts(struct screen_write_ctx *,
|
||||||
struct grid_cell *, const char *, ...);
|
struct grid_cell *, const char *, ...);
|
||||||
@ -1540,6 +1543,8 @@ void printflike5 screen_write_nputs(struct screen_write_ctx *,
|
|||||||
ssize_t, struct grid_cell *, int, const char *, ...);
|
ssize_t, struct grid_cell *, int, const char *, ...);
|
||||||
void screen_write_vnputs(struct screen_write_ctx *,
|
void screen_write_vnputs(struct screen_write_ctx *,
|
||||||
ssize_t, struct grid_cell *, int, const char *, va_list);
|
ssize_t, struct grid_cell *, int, const char *, va_list);
|
||||||
|
void screen_write_parsestyle(
|
||||||
|
struct grid_cell *, struct grid_cell *, const char *);
|
||||||
void screen_write_putc(
|
void screen_write_putc(
|
||||||
struct screen_write_ctx *, struct grid_cell *, u_char);
|
struct screen_write_ctx *, struct grid_cell *, u_char);
|
||||||
void screen_write_copy(struct screen_write_ctx *,
|
void screen_write_copy(struct screen_write_ctx *,
|
||||||
|
Loading…
Reference in New Issue
Block a user