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
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);
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-bg", 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-format", SET_OPTION_STRING, 0, 0, NULL },
{ "xterm-keys", SET_OPTION_FLAG, 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 options *oo;
const struct set_option_entry *entry, *opt;
struct jobs *jobs;
struct job *job, *nextjob;
u_int i;
int try_again;
if (cmd_check_flag(data->chflags, 'g'))
oo = &global_w_options;
@ -166,5 +171,34 @@ cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx)
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);
}

View File

@ -489,7 +489,7 @@ server_client_set_title(struct client *c)
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)
xfree(c->title);

105
status.c
View File

@ -31,10 +31,11 @@
char *status_job(struct client *, char **);
void status_job_callback(struct job *);
size_t status_width(struct winlink *);
char *status_print(struct session *, struct winlink *, struct grid_cell *);
void status_replace1(
struct client *, char **, char **, char *, size_t, int);
size_t status_width(struct client *, struct winlink *, time_t);
char *status_print(
struct client *, struct winlink *, time_t, struct grid_cell *);
void status_replace1(struct client *,
struct winlink *, char **, char **, char *, size_t, int);
void status_message_callback(int, short, void *);
void status_prompt_add_history(struct client *);
@ -108,14 +109,14 @@ status_redraw(struct client *c)
utf8flag = options_get_number(&s->options, "status-utf8");
/* 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);
llen = options_get_number(&s->options, "status-left-length");
llen2 = screen_write_cstrlen(utf8flag, "%s", left);
if (llen2 < llen)
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);
rlen = options_get_number(&s->options, "status-right-length");
rlen2 = screen_write_cstrlen(utf8flag, "%s", right);
@ -141,7 +142,7 @@ status_redraw(struct client *c)
*/
width = offset = 0;
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)
offset = width;
width += size;
@ -153,7 +154,7 @@ status_redraw(struct client *c)
goto draw;
/* 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
@ -226,7 +227,7 @@ draw:
offset = 0;
RB_FOREACH(wl, winlinks, &s->windows) {
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 (session_alert_has(s, wl, WINDOW_ACTIVITY))
@ -237,10 +238,13 @@ draw:
larrow = -1;
}
for (ptr = text; *ptr != '\0'; ptr++) {
if (offset >= start && offset < start + width)
screen_write_putc(&ctx, &gc, *ptr);
offset++;
ptr = text;
for (; offset < start; offset++)
ptr++; /* XXX should skip UTF-8 characters */
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) {
@ -322,15 +326,17 @@ out:
/* Replace a single special sequence (prefixed by #). */
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)
{
struct session *s = c->session;
struct winlink *wl = s->curw;
char ch, tmp[256], *ptr, *endptr, *freeptr;
size_t ptrlen;
long limit;
if (wl == NULL)
wl = s->curw;
errno = 0;
limit = strtol(*iptr, &endptr, 10);
if ((limit == 0 && errno != EINVAL) ||
@ -376,6 +382,21 @@ status_replace1(struct client *c,
case 'W':
ptr = wl->window->name;
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 '[':
/*
* Embedded style, handled at display time. Leave present and
@ -419,7 +440,8 @@ skip_to:
/* Replace special sequences in fmt. */
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];
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;
continue;
}
status_replace1(c, &iptr, &optr, out, sizeof out, jobsflag);
status_replace1(c, wl, &iptr, &optr, out, sizeof out, jobsflag);
}
*optr = '\0';
@ -522,17 +544,37 @@ status_job_callback(struct job *job)
/* Calculate winlink status line entry width. */
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. */
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;
char *text, flag;
struct session *s = c->session;
const char *fmt;
char *text;
u_char fg, bg, attr;
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");
if (attr != 0)
gc->attr = attr;
flag = ' ';
if (wl == TAILQ_FIRST(&s->lastw))
flag = '-';
fmt = options_get_string(oo, "window-status-format");
if (wl == s->curw) {
fg = options_get_number(oo, "window-status-current-fg");
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");
if (attr != 0)
gc->attr = attr;
flag = '*';
fmt = options_get_string(oo, "window-status-current-format");
}
if (session_alert_has(s, wl, WINDOW_ACTIVITY)) {
flag = '#';
if (session_alert_has(s, wl, WINDOW_ACTIVITY) ||
session_alert_has(s, wl, WINDOW_BELL) ||
session_alert_has(s, wl, WINDOW_CONTENT))
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);
}

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 "#[attributes]" Ta "Colour or attribute change"
.It Li "#H" Ta "Hostname of local host"
.It Li "#F" Ta "Current window flag"
.It Li "#I" Ta "Current window index"
.It Li "#P" Ta "Current pane index"
.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
Set status line foreground colour for a single window.
.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
Set status line attributes for the currently active window.
.Pp
@ -1794,6 +1803,11 @@ Set status line background colour for the currently active window.
.It Ic window-status-current-fg Ar colour
Set status line foreground colour for the currently active window.
.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
.Op Ic on | off
.Xc
@ -1900,8 +1914,13 @@ command, see the
and
.Ic status-right-length
options below), and a central window list.
The window list shows the index, name and (if any) flag of the windows
present in the current session in ascending numerical order.
By default, the window list shows the index, name and (if any) flag of the
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:
.Bl -column "Symbol" "Meaning" -offset indent
.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-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, "remain-on-exit", 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 */
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 status_message_clear(struct client *);
int status_message_redraw(struct client *);