Two new options, window-status-format and window-status-current-format, which

allow the format of each window in the status line window list to be controlled
using similar # sequences as status-left/right.

This diff also moves part of the way towards UTF-8 support in window names but
it isn't quite there yet.
This commit is contained in:
Nicholas Marriott 2009-11-19 16:22:10 +00:00
parent 8b8a211185
commit 543fb99bc6
7 changed files with 131 additions and 42 deletions

View File

@ -55,7 +55,7 @@ cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx)
else else
template = data->arg; template = data->arg;
msg = status_replace(c, template, time(NULL), 0); msg = status_replace(c, NULL, template, time(NULL), 0);
status_message_set(c, "%s", msg); status_message_set(c, "%s", msg);
xfree(msg); xfree(msg);

View File

@ -71,7 +71,9 @@ const struct set_option_entry set_window_option_table[] = {
{ "window-status-current-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, { "window-status-current-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "window-status-current-bg", SET_OPTION_COLOUR, 0, 0, NULL }, { "window-status-current-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-current-fg", SET_OPTION_COLOUR, 0, 0, NULL }, { "window-status-current-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-current-format", SET_OPTION_STRING, 0, 0, NULL },
{ "window-status-fg", SET_OPTION_COLOUR, 0, 0, NULL }, { "window-status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-format", SET_OPTION_STRING, 0, 0, NULL },
{ "xterm-keys", SET_OPTION_FLAG, 0, 0, NULL }, { "xterm-keys", SET_OPTION_FLAG, 0, 0, NULL },
{ NULL, 0, 0, 0, NULL } { NULL, 0, 0, 0, NULL }
}; };
@ -84,7 +86,10 @@ cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx)
struct client *c; struct client *c;
struct options *oo; struct options *oo;
const struct set_option_entry *entry, *opt; const struct set_option_entry *entry, *opt;
struct jobs *jobs;
struct job *job, *nextjob;
u_int i; u_int i;
int try_again;
if (cmd_check_flag(data->chflags, 'g')) if (cmd_check_flag(data->chflags, 'g'))
oo = &global_w_options; oo = &global_w_options;
@ -166,5 +171,34 @@ cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_client(c); server_redraw_client(c);
} }
/*
* Special-case: kill all persistent jobs if window-status-format has
* changed. Persistent jobs are only used by the status line at the
* moment so this works XXX.
*/
if (strcmp(entry->name, "window-status-format") == 0) {
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
jobs = &c->status_jobs;
do {
try_again = 0;
job = RB_ROOT(jobs);
while (job != NULL) {
nextjob = RB_NEXT(jobs, jobs, job);
if (job->flags & JOB_PERSIST) {
job_remove(jobs, job);
try_again = 1;
break;
}
job = nextjob;
}
} while (try_again);
server_redraw_client(c);
}
}
return (0); return (0);
} }

View File

@ -489,7 +489,7 @@ server_client_set_title(struct client *c)
template = options_get_string(&s->options, "set-titles-string"); template = options_get_string(&s->options, "set-titles-string");
title = status_replace(c, template, time(NULL), 1); title = status_replace(c, NULL, template, time(NULL), 1);
if (c->title == NULL || strcmp(title, c->title) != 0) { if (c->title == NULL || strcmp(title, c->title) != 0) {
if (c->title != NULL) if (c->title != NULL)
xfree(c->title); xfree(c->title);

105
status.c
View File

@ -31,10 +31,11 @@
char *status_job(struct client *, char **); char *status_job(struct client *, char **);
void status_job_callback(struct job *); void status_job_callback(struct job *);
size_t status_width(struct winlink *); size_t status_width(struct client *, struct winlink *, time_t);
char *status_print(struct session *, struct winlink *, struct grid_cell *); char *status_print(
void status_replace1( struct client *, struct winlink *, time_t, struct grid_cell *);
struct client *, char **, char **, char *, size_t, int); void status_replace1(struct client *,
struct winlink *, char **, char **, char *, size_t, int);
void status_message_callback(int, short, void *); void status_message_callback(int, short, void *);
void status_prompt_add_history(struct client *); void status_prompt_add_history(struct client *);
@ -108,14 +109,14 @@ status_redraw(struct client *c)
utf8flag = options_get_number(&s->options, "status-utf8"); utf8flag = options_get_number(&s->options, "status-utf8");
/* Work out the left and right strings. */ /* Work out the left and right strings. */
left = status_replace(c, options_get_string( left = status_replace(c, NULL, options_get_string(
&s->options, "status-left"), c->status_timer.tv_sec, 1); &s->options, "status-left"), c->status_timer.tv_sec, 1);
llen = options_get_number(&s->options, "status-left-length"); llen = options_get_number(&s->options, "status-left-length");
llen2 = screen_write_cstrlen(utf8flag, "%s", left); llen2 = screen_write_cstrlen(utf8flag, "%s", left);
if (llen2 < llen) if (llen2 < llen)
llen = llen2; llen = llen2;
right = status_replace(c, options_get_string( right = status_replace(c, NULL, options_get_string(
&s->options, "status-right"), c->status_timer.tv_sec, 1); &s->options, "status-right"), c->status_timer.tv_sec, 1);
rlen = options_get_number(&s->options, "status-right-length"); rlen = options_get_number(&s->options, "status-right-length");
rlen2 = screen_write_cstrlen(utf8flag, "%s", right); rlen2 = screen_write_cstrlen(utf8flag, "%s", right);
@ -141,7 +142,7 @@ status_redraw(struct client *c)
*/ */
width = offset = 0; width = offset = 0;
RB_FOREACH(wl, winlinks, &s->windows) { RB_FOREACH(wl, winlinks, &s->windows) {
size = status_width(wl) + 1; size = status_width(c, wl, c->status_timer.tv_sec) + 1;
if (wl == s->curw) if (wl == s->curw)
offset = width; offset = width;
width += size; width += size;
@ -153,7 +154,7 @@ status_redraw(struct client *c)
goto draw; goto draw;
/* Find size of current window text. */ /* Find size of current window text. */
size = status_width(s->curw); size = status_width(c, s->curw, c->status_timer.tv_sec);
/* /*
* If the offset is already on screen, we're good to draw from the * If the offset is already on screen, we're good to draw from the
@ -226,7 +227,7 @@ draw:
offset = 0; offset = 0;
RB_FOREACH(wl, winlinks, &s->windows) { RB_FOREACH(wl, winlinks, &s->windows) {
memcpy(&gc, &stdgc, sizeof gc); memcpy(&gc, &stdgc, sizeof gc);
text = status_print(s, wl, &gc); text = status_print(c, wl, c->status_timer.tv_sec, &gc);
if (larrow == 1 && offset < start) { if (larrow == 1 && offset < start) {
if (session_alert_has(s, wl, WINDOW_ACTIVITY)) if (session_alert_has(s, wl, WINDOW_ACTIVITY))
@ -237,10 +238,13 @@ draw:
larrow = -1; larrow = -1;
} }
for (ptr = text; *ptr != '\0'; ptr++) { ptr = text;
if (offset >= start && offset < start + width) for (; offset < start; offset++)
screen_write_putc(&ctx, &gc, *ptr); ptr++; /* XXX should skip UTF-8 characters */
offset++; if (offset < start + width) {
screen_write_cnputs(&ctx,
start + width - offset, &gc, utf8flag, "%s", text);
offset += screen_write_cstrlen(utf8flag, "%s", text);
} }
if (rarrow == 1 && offset > start + width) { if (rarrow == 1 && offset > start + width) {
@ -322,15 +326,17 @@ out:
/* Replace a single special sequence (prefixed by #). */ /* Replace a single special sequence (prefixed by #). */
void void
status_replace1(struct client *c, status_replace1(struct client *c,struct winlink *wl,
char **iptr, char **optr, char *out, size_t outsize, int jobsflag) char **iptr, char **optr, char *out, size_t outsize, int jobsflag)
{ {
struct session *s = c->session; struct session *s = c->session;
struct winlink *wl = s->curw;
char ch, tmp[256], *ptr, *endptr, *freeptr; char ch, tmp[256], *ptr, *endptr, *freeptr;
size_t ptrlen; size_t ptrlen;
long limit; long limit;
if (wl == NULL)
wl = s->curw;
errno = 0; errno = 0;
limit = strtol(*iptr, &endptr, 10); limit = strtol(*iptr, &endptr, 10);
if ((limit == 0 && errno != EINVAL) || if ((limit == 0 && errno != EINVAL) ||
@ -376,6 +382,21 @@ status_replace1(struct client *c,
case 'W': case 'W':
ptr = wl->window->name; ptr = wl->window->name;
goto do_replace; goto do_replace;
case 'F':
tmp[0] = ' ';
if (session_alert_has(s, wl, WINDOW_CONTENT))
tmp[0] = '+';
else if (session_alert_has(s, wl, WINDOW_BELL))
tmp[0] = '!';
else if (session_alert_has(s, wl, WINDOW_ACTIVITY))
tmp[0] = '#';
else if (wl == s->curw)
tmp[0] = '*';
else if (wl == TAILQ_FIRST(&s->lastw))
tmp[0] = '-';
tmp[1] = '\0';
ptr = tmp;
goto do_replace;
case '[': case '[':
/* /*
* Embedded style, handled at display time. Leave present and * Embedded style, handled at display time. Leave present and
@ -419,7 +440,8 @@ skip_to:
/* Replace special sequences in fmt. */ /* Replace special sequences in fmt. */
char * char *
status_replace(struct client *c, const char *fmt, time_t t, int jobsflag) status_replace(struct client *c,
struct winlink *wl, const char *fmt, time_t t, int jobsflag)
{ {
static char out[BUFSIZ]; static char out[BUFSIZ];
char in[BUFSIZ], ch, *iptr, *optr; char in[BUFSIZ], ch, *iptr, *optr;
@ -439,7 +461,7 @@ status_replace(struct client *c, const char *fmt, time_t t, int jobsflag)
*optr++ = ch; *optr++ = ch;
continue; continue;
} }
status_replace1(c, &iptr, &optr, out, sizeof out, jobsflag); status_replace1(c, wl, &iptr, &optr, out, sizeof out, jobsflag);
} }
*optr = '\0'; *optr = '\0';
@ -522,17 +544,37 @@ status_job_callback(struct job *job)
/* Calculate winlink status line entry width. */ /* Calculate winlink status line entry width. */
size_t size_t
status_width(struct winlink *wl) status_width(struct client *c, struct winlink *wl, time_t t)
{ {
return (xsnprintf(NULL, 0, "%d:%s ", wl->idx, wl->window->name)); struct options *oo = &wl->window->options;
struct session *s = c->session;
const char *fmt;
char *text;
size_t size;
int utf8flag;
utf8flag = options_get_number(&s->options, "status-utf8");
fmt = options_get_string(&wl->window->options, "window-status-format");
if (wl == s->curw)
fmt = options_get_string(oo, "window-status-current-format");
text = status_replace(c, wl, fmt, t, 1);
size = screen_write_cstrlen(utf8flag, "%s", text);
xfree(text);
return (size);
} }
/* Return winlink status line entry and adjust gc as necessary. */ /* Return winlink status line entry and adjust gc as necessary. */
char * char *
status_print(struct session *s, struct winlink *wl, struct grid_cell *gc) status_print(
struct client *c, struct winlink *wl, time_t t, struct grid_cell *gc)
{ {
struct options *oo = &wl->window->options; struct options *oo = &wl->window->options;
char *text, flag; struct session *s = c->session;
const char *fmt;
char *text;
u_char fg, bg, attr; u_char fg, bg, attr;
fg = options_get_number(oo, "window-status-fg"); fg = options_get_number(oo, "window-status-fg");
@ -544,10 +586,7 @@ status_print(struct session *s, struct winlink *wl, struct grid_cell *gc)
attr = options_get_number(oo, "window-status-attr"); attr = options_get_number(oo, "window-status-attr");
if (attr != 0) if (attr != 0)
gc->attr = attr; gc->attr = attr;
fmt = options_get_string(oo, "window-status-format");
flag = ' ';
if (wl == TAILQ_FIRST(&s->lastw))
flag = '-';
if (wl == s->curw) { if (wl == s->curw) {
fg = options_get_number(oo, "window-status-current-fg"); fg = options_get_number(oo, "window-status-current-fg");
if (fg != 8) if (fg != 8)
@ -558,21 +597,15 @@ status_print(struct session *s, struct winlink *wl, struct grid_cell *gc)
attr = options_get_number(oo, "window-status-current-attr"); attr = options_get_number(oo, "window-status-current-attr");
if (attr != 0) if (attr != 0)
gc->attr = attr; gc->attr = attr;
flag = '*'; fmt = options_get_string(oo, "window-status-current-format");
} }
if (session_alert_has(s, wl, WINDOW_ACTIVITY)) { if (session_alert_has(s, wl, WINDOW_ACTIVITY) ||
flag = '#'; session_alert_has(s, wl, WINDOW_BELL) ||
session_alert_has(s, wl, WINDOW_CONTENT))
gc->attr ^= GRID_ATTR_REVERSE; gc->attr ^= GRID_ATTR_REVERSE;
} else if (session_alert_has(s, wl, WINDOW_BELL)) {
flag = '!';
gc->attr ^= GRID_ATTR_REVERSE;
} else if (session_alert_has(s, wl, WINDOW_CONTENT)) {
flag = '+';
gc->attr ^= GRID_ATTR_REVERSE;
}
xasprintf(&text, "%d:%s%c", wl->idx, wl->window->name, flag); text = status_replace(c, wl, fmt, t, 1);
return (text); return (text);
} }

23
tmux.1
View File

@ -1477,6 +1477,7 @@ may contain any of the following special character sequences:
.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 "#[attributes]" Ta "Colour or attribute change"
.It Li "#H" Ta "Hostname of local host" .It Li "#H" Ta "Hostname of local host"
.It Li "#F" Ta "Current window flag"
.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"
.It Li "#S" Ta "Session name" .It Li "#S" Ta "Session name"
@ -1785,6 +1786,14 @@ Set status line background colour for a single window.
.It Ic window-status-fg Ar colour .It Ic window-status-fg Ar colour
Set status line foreground colour for a single window. Set status line foreground colour for a single window.
.Pp .Pp
.It Ic window-status-format Ar string
Set the format in which the window is displayed in the status line window list.
See the
.Ar status-left
option for details of special character sequences available.
The default is
.Ql #I:#W#F .
.Pp
.It Ic window-status-current-attr Ar attributes .It Ic window-status-current-attr Ar attributes
Set status line attributes for the currently active window. Set status line attributes for the currently active window.
.Pp .Pp
@ -1794,6 +1803,11 @@ Set status line background colour for the currently active window.
.It Ic window-status-current-fg Ar colour .It Ic window-status-current-fg Ar colour
Set status line foreground colour for the currently active window. Set status line foreground colour for the currently active window.
.Pp .Pp
.It Ic window-status-current-format Ar string
Like
.Ar window-status-format ,
but is the format used when the window is the current window.
.Pp
.It Xo Ic xterm-keys .It Xo Ic xterm-keys
.Op Ic on | off .Op Ic on | off
.Xc .Xc
@ -1900,8 +1914,13 @@ command, see the
and and
.Ic status-right-length .Ic status-right-length
options below), and a central window list. options below), and a central window list.
The window list shows the index, name and (if any) flag of the windows By default, the window list shows the index, name and (if any) flag of the
present in the current session in ascending numerical order. windows present in the current session in ascending numerical order.
It may be customised with the
.Ar window-status-format
and
.Ar window-status-current-format
options.
The flag is one of the following symbols appended to the window name: The flag is one of the following symbols appended to the window name:
.Bl -column "Symbol" "Meaning" -offset indent .Bl -column "Symbol" "Meaning" -offset indent
.It Sy "Symbol" Ta Sy "Meaning" .It Sy "Symbol" Ta Sy "Meaning"

2
tmux.c
View File

@ -391,6 +391,8 @@ main(int argc, char **argv)
options_set_number(wo, "window-status-current-bg", 8); options_set_number(wo, "window-status-current-bg", 8);
options_set_number(wo, "window-status-current-fg", 8); options_set_number(wo, "window-status-current-fg", 8);
options_set_number(wo, "window-status-fg", 8); options_set_number(wo, "window-status-fg", 8);
options_set_string(wo, "window-status-format", "#I:#W#F");
options_set_string(wo, "window-status-current-format", "#I:#W#F");
options_set_number(wo, "xterm-keys", 0); options_set_number(wo, "xterm-keys", 0);
options_set_number(wo, "remain-on-exit", 0); options_set_number(wo, "remain-on-exit", 0);
options_set_number(wo, "synchronize-panes", 0); options_set_number(wo, "synchronize-panes", 0);

3
tmux.h
View File

@ -1617,7 +1617,8 @@ void server_update_event(struct client *);
/* status.c */ /* status.c */
int status_redraw(struct client *); int status_redraw(struct client *);
char *status_replace(struct client *, const char *, time_t, int); char *status_replace(
struct client *, struct winlink *, const char *, time_t, int);
void printflike2 status_message_set(struct client *, const char *, ...); void printflike2 status_message_set(struct client *, const char *, ...);
void status_message_clear(struct client *); void status_message_clear(struct client *);
int status_message_redraw(struct client *); int status_message_redraw(struct client *);