From d0342f4a0474abf42098fbaa0a4e2f2e3f006514 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 5 Dec 2008 20:04:06 +0000 Subject: [PATCH] Ability to show window title on status line. --- CHANGES | 15 ++++++- Makefile | 4 +- TODO | 2 +- cmd-set-option.c | 4 +- input.c | 6 ++- server.c | 8 ++-- status.c | 108 ++++++++++++++++++++++++++++++++++++++--------- tmux.c | 6 ++- tmux.h | 4 +- 9 files changed, 121 insertions(+), 36 deletions(-) diff --git a/CHANGES b/CHANGES index 870671e5..b3768f18 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,16 @@ +02 December 2008 + +* Add support for including the window title in status-left or status-right + strings by including the character pair "#T". This may be prefixed with + a number to specify a maximum length, for example "#24T" to use at most + 24 characters of the title. +* Introduce two new options, status-left-length and status-right-length, + control the maximum length of left and right components of the status bar. +* elinks (and possibly others) bypass the terminal and talk directly to X to + restore the window title when exiting. tmux can't know about this particular + bit of stupidity so the title ends up strange - the prefix isn't terribly + important and elinks is quite useful so just get rid of it. + 27 November 2008 * Tweaks to support Dragonfly. @@ -715,4 +728,4 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.168 2008-11-27 18:55:47 nicm Exp $ +$Id: CHANGES,v 1.169 2008-12-05 20:04:06 nicm Exp $ diff --git a/Makefile b/Makefile index 1787b919..ada7be6a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.77 2008-11-27 18:55:47 nicm Exp $ +# $Id: Makefile,v 1.78 2008-12-05 20:04:06 nicm Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean update-index.html upload-index.html @@ -11,7 +11,7 @@ REL!= uname -r DATE!= date +%Y%m%d-%H%M # This must be empty as OpenBSD includes it in default CFLAGS. -#DEBUG= +DEBUG= META?= \002 # C-b diff --git a/TODO b/TODO index 99f310c4..34dd15c4 100644 --- a/TODO +++ b/TODO @@ -51,4 +51,4 @@ - many more info() displays for various things - vi half page scroll - why do home/end work in emacs outside tmux but not inside? -- option to show window titles on status line (shorten window list and put it after) +- document status line options, title bits diff --git a/cmd-set-option.c b/cmd-set-option.c index a19be156..93896835 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -1,4 +1,4 @@ -/* $Id: cmd-set-option.c,v 1.44 2008-11-16 13:28:59 nicm Exp $ */ +/* $Id: cmd-set-option.c,v 1.45 2008-12-05 20:04:06 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -77,6 +77,8 @@ const struct set_option_entry set_option_table[NSETOPTION] = { { "status-interval", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "status-left", SET_OPTION_STRING, 0, 0, NULL }, { "status-right", SET_OPTION_STRING, 0, 0, NULL }, + { "status-left-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, + { "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, { "utf8", SET_OPTION_FLAG, 0, 0, NULL }, }; diff --git a/input.c b/input.c index 25995132..2ff1ec5e 100644 --- a/input.c +++ b/input.c @@ -1,4 +1,4 @@ -/* $Id: input.c,v 1.67 2008-11-16 13:28:59 nicm Exp $ */ +/* $Id: input.c,v 1.68 2008-12-05 20:04:06 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -462,7 +462,8 @@ input_state_string_escape(u_char ch, struct input_ctx *ictx) xfree(s); return; } - screen_set_title(ictx->ctx.s, s + 2); + screen_set_title(ictx->ctx.s, s + 2); + server_status_window(ictx->w); xfree(s); break; case STRING_APPLICATION: @@ -470,6 +471,7 @@ input_state_string_escape(u_char ch, struct input_ctx *ictx) return; s = input_get_string(ictx); screen_set_title(ictx->ctx.s, s); + server_status_window(ictx->w); xfree(s); break; case STRING_NAME: diff --git a/server.c b/server.c index 82b1f07f..33dffa91 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.84 2008-11-04 20:55:58 nicm Exp $ */ +/* $Id: server.c,v 1.85 2008-12-05 20:04:06 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -305,7 +305,7 @@ server_check_redraw(struct client *c) struct screen screen; struct grid_cell gc; u_int xx, yy, sx, sy; - char title[BUFSIZ]; + char *title; int flags; if (c == NULL || c->session == NULL) @@ -316,9 +316,7 @@ server_check_redraw(struct client *c) c->tty.flags &= ~TTY_FREEZE; if (options_get_number(&s->options, "set-titles")) { - xsnprintf(title, sizeof title, - "%s:%u:%s - \"%s\"", s->name, s->curw->idx, - s->curw->window->name, s->curw->window->base.title); + title = s->curw->window->base.title; if (c->title == NULL || strcmp(title, c->title) != 0) { if (c->title != NULL) xfree(c->title); diff --git a/status.c b/status.c index 0bc77eaf..16a558e7 100644 --- a/status.c +++ b/status.c @@ -1,4 +1,4 @@ -/* $Id: status.c,v 1.50 2008-11-16 10:10:26 nicm Exp $ */ +/* $Id: status.c,v 1.51 2008-12-05 20:04:06 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -19,12 +19,16 @@ #include #include +#include +#include #include +#include #include #include #include "tmux.h" +char *status_replace(struct session *, char *, time_t); size_t status_width(struct winlink *); char *status_print(struct session *, struct winlink *, struct grid_cell *); @@ -35,15 +39,14 @@ status_redraw(struct client *c) struct screen_redraw_ctx ctx; struct session *s = c->session; struct winlink *wl; - char *left, *right, *text, *ptr; - char lbuf[BUFSIZ], rbuf[BUFSIZ]; + char *left, *right, *text, *ptr; size_t llen, rlen, offset, xx, yy; size_t size, start, width; struct grid_cell gc; - struct tm *tm; - time_t t; int larrow, rarrow; + left = right = NULL; + if (c->sy == 0 || !options_get_number(&s->options, "status")) goto off; larrow = rarrow = 0; @@ -58,14 +61,19 @@ status_redraw(struct client *c) if (yy == 0) goto blank; - t = c->status_timer.tv_sec; - tm = localtime(&t); - left = options_get_string(&s->options, "status-left"); - strftime(lbuf, sizeof lbuf, left, tm); - llen = strlen(lbuf); - right = options_get_string(&s->options, "status-right"); - strftime(rbuf, sizeof rbuf, right, tm); - rlen = strlen(rbuf); + left = status_replace(s, options_get_string( + &s->options, "status-left"), c->status_timer.tv_sec); + llen = options_get_number(&s->options, "status-left-length"); + if (strlen(left) < llen) + llen = strlen(left); + left[llen] = '\0'; + + right = status_replace(s, options_get_string( + &s->options, "status-right"), c->status_timer.tv_sec); + rlen = options_get_number(&s->options, "status-right-length"); + if (strlen(right) < rlen) + rlen = strlen(right); + right[rlen] = '\0'; /* * Figure out how much space we have for the window list. If there isn't @@ -141,7 +149,7 @@ draw: screen_redraw_start_client(&ctx, c); if (llen != 0) { ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy); - screen_redraw_puts(&ctx, &gc, "%s ", lbuf); + screen_redraw_puts(&ctx, &gc, "%s ", left); if (larrow) screen_redraw_putc(&ctx, &gc, ' '); } else { @@ -194,7 +202,7 @@ draw: /* Draw the last item. */ if (rlen != 0) { ctx.write(ctx.data, TTY_CURSORMOVE, c->sx - rlen - 1, yy); - screen_redraw_puts(&ctx, &gc, " %s", rbuf); + screen_redraw_puts(&ctx, &gc, " %s", right); } /* Draw the arrows. */ @@ -223,8 +231,7 @@ draw: gc.attr &= ~GRID_ATTR_REVERSE; } - screen_redraw_stop(&ctx); - return; + goto out; blank: /* Just draw the whole line as blank. */ @@ -232,9 +239,8 @@ blank: ctx.write(ctx.data, TTY_CURSORMOVE, 0, yy); for (offset = 0; offset < c->sx; offset++) screen_redraw_putc(&ctx, &gc, ' '); - screen_redraw_stop(&ctx); - return; + goto out; off: /* @@ -249,9 +255,71 @@ off: screen_redraw_putc(&ctx, &gc, ' '); } else screen_redraw_lines(&ctx, c->sy - 1, 1); + +out: screen_redraw_stop(&ctx); - return; + if (left != NULL) + xfree(left); + if (right != NULL) + xfree(right); +} + +char * +status_replace(struct session *s, char *fmt, time_t t) +{ + static char out[BUFSIZ]; + char in[BUFSIZ], ch, *iptr, *optr, *ptr, *endptr; + size_t len; + long n; + + strftime(in, sizeof in, fmt, localtime(&t)); + in[(sizeof in) - 1] = '\0'; + + iptr = in; + optr = out; + + while (*iptr != '\0') { + if (optr >= out + (sizeof out) - 1) + break; + switch (ch = *iptr++) { + case '#': + errno = 0; + n = strtol(iptr, &endptr, 10); + if ((n == 0 && errno != EINVAL) || + (n == LONG_MIN && errno != ERANGE) || + (n == LONG_MAX && errno != ERANGE) || + n != 0) + iptr = endptr; + if (n <= 0) + n = LONG_MAX; + + switch (*iptr++) { + case 'T': + ptr = s->curw->window->base.title; + len = strlen(ptr); + if ((size_t) n < len) + len = n; + if (optr + len >= out + (sizeof out) - 1) + break; + while (len > 0 && *ptr != '\0') { + *optr++ = *ptr++; + len--; + } + break; + case '#': + *optr++ = '#'; + break; + } + break; + default: + *optr++ = ch; + break; + } + } + *optr = '\0'; + + return (xstrdup(out)); } size_t diff --git a/tmux.c b/tmux.c index e18ade15..36983f76 100644 --- a/tmux.c +++ b/tmux.c @@ -1,4 +1,4 @@ -/* $Id: tmux.c,v 1.81 2008-11-27 18:55:47 nicm Exp $ */ +/* $Id: tmux.c,v 1.82 2008-12-05 20:04:06 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -226,7 +226,9 @@ main(int argc, char **argv) options_set_number(&global_options, "prefix", META); options_set_string(&global_options, "status-left", "%s", ""); /* ugh */ options_set_string( - &global_options, "status-right", "%%H:%%M %%d-%%b-%%y"); + &global_options, "status-right", "\"#24T\" %%H:%%M %%d-%%b-%%y"); + options_set_number(&global_options, "status-left-length", 10); + options_set_number(&global_options, "status-right-length", 40); options_set_number(&global_options, "status-interval", 15); options_set_number(&global_options, "set-titles", 1); options_set_number(&global_options, "buffer-limit", 9); diff --git a/tmux.h b/tmux.h index 9d178a26..4975e5fb 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.199 2008-11-23 19:38:12 nicm Exp $ */ +/* $Id: tmux.h,v 1.200 2008-12-05 20:04:06 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -844,7 +844,7 @@ struct set_option_entry { const char **choices; }; extern const struct set_option_entry set_option_table[]; -#define NSETOPTION 16 +#define NSETOPTION 18 /* Edit keys. */ enum mode_key {