From e673bcfb040b4f331e78e7b2fc29d28884fa3caf Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Thu, 19 Nov 2009 16:22:11 +0000 Subject: 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. --- usr.bin/tmux/cmd-display-message.c | 4 +- usr.bin/tmux/cmd-set-window-option.c | 36 +++++++++++- usr.bin/tmux/server-client.c | 4 +- usr.bin/tmux/status.c | 109 +++++++++++++++++++++++------------ usr.bin/tmux/tmux.1 | 25 +++++++- usr.bin/tmux/tmux.c | 4 +- usr.bin/tmux/tmux.h | 5 +- 7 files changed, 138 insertions(+), 49 deletions(-) diff --git a/usr.bin/tmux/cmd-display-message.c b/usr.bin/tmux/cmd-display-message.c index 9914f46f6b6..642ab081e92 100644 --- a/usr.bin/tmux/cmd-display-message.c +++ b/usr.bin/tmux/cmd-display-message.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-display-message.c,v 1.5 2009/11/19 10:22:06 nicm Exp $ */ +/* $OpenBSD: cmd-display-message.c,v 1.6 2009/11/19 16:22:10 nicm Exp $ */ /* * Copyright (c) 2009 Tiago Cunha @@ -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); diff --git a/usr.bin/tmux/cmd-set-window-option.c b/usr.bin/tmux/cmd-set-window-option.c index 6c6f5bb9fe2..3826982d2d1 100644 --- a/usr.bin/tmux/cmd-set-window-option.c +++ b/usr.bin/tmux/cmd-set-window-option.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-set-window-option.c,v 1.14 2009/11/13 19:53:29 nicm Exp $ */ +/* $OpenBSD: cmd-set-window-option.c,v 1.15 2009/11/19 16:22:10 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -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); } diff --git a/usr.bin/tmux/server-client.c b/usr.bin/tmux/server-client.c index cafa2182405..f649091efa8 100644 --- a/usr.bin/tmux/server-client.c +++ b/usr.bin/tmux/server-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server-client.c,v 1.22 2009/11/19 10:22:06 nicm Exp $ */ +/* $OpenBSD: server-client.c,v 1.23 2009/11/19 16:22:10 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -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); diff --git a/usr.bin/tmux/status.c b/usr.bin/tmux/status.c index b86b1e1a96f..bfbbf97f71a 100644 --- a/usr.bin/tmux/status.c +++ b/usr.bin/tmux/status.c @@ -1,4 +1,4 @@ -/* $OpenBSD: status.c,v 1.46 2009/11/19 11:38:54 nicm Exp $ */ +/* $OpenBSD: status.c,v 1.47 2009/11/19 16:22:10 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -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,11 +440,12 @@ 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; - + strftime(in, sizeof in, fmt, localtime(&t)); in[(sizeof in) - 1] = '\0'; @@ -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 = '#'; - gc->attr ^= GRID_ATTR_REVERSE; - } else if (session_alert_has(s, wl, WINDOW_BELL)) { - 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_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); } diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index bf0b5b90a0a..7e1cb1bcd17 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.124 2009/11/19 15:00:32 jmc Exp $ +.\" $OpenBSD: tmux.1,v 1.125 2009/11/19 16:22:10 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -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" diff --git a/usr.bin/tmux/tmux.c b/usr.bin/tmux/tmux.c index b2cd6806a71..0813b895d83 100644 --- a/usr.bin/tmux/tmux.c +++ b/usr.bin/tmux/tmux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.c,v 1.59 2009/11/19 14:06:34 nicm Exp $ */ +/* $OpenBSD: tmux.c,v 1.60 2009/11/19 16:22:10 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -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); diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index dd35f0ca0b9..c6768bfcc3c 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.182 2009/11/19 10:22:07 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.183 2009/11/19 16:22:10 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -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 *); -- cgit v1.2.3