summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2009-11-19 16:22:10 +0000
committerNicholas Marriott <nicm@openbsd.org>2009-11-19 16:22:10 +0000
commit543fb99bc60a82eeb8c1e3fa47cdcb86a1e2fb33 (patch)
treed786032c6ea64b79aaea5ff7eb3a4b89047aee62
parent8b8a2111852e9c2ce0cbc5e867d29ca78d4948a5 (diff)
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.
-rw-r--r--cmd-display-message.c2
-rw-r--r--cmd-set-window-option.c34
-rw-r--r--server-client.c2
-rw-r--r--status.c107
-rw-r--r--tmux.123
-rw-r--r--tmux.c2
-rw-r--r--tmux.h3
7 files changed, 131 insertions, 42 deletions
diff --git a/cmd-display-message.c b/cmd-display-message.c
index be39857d..aa4fd5db 100644
--- a/cmd-display-message.c
+++ b/cmd-display-message.c
@@ -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/cmd-set-window-option.c b/cmd-set-window-option.c
index 1d7b8cc5..0ad1025e 100644
--- a/cmd-set-window-option.c
+++ b/cmd-set-window-option.c
@@ -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/server-client.c b/server-client.c
index 7334d4b4..e6560931 100644
--- a/server-client.c
+++ b/server-client.c
@@ -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/status.c b/status.c
index 134e8717..39e824c1 100644
--- a/status.c
+++ b/status.c
@@ -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/tmux.1 b/tmux.1
index de86a728..0a34712e 100644
--- a/tmux.1
+++ b/tmux.1
@@ -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/tmux.c b/tmux.c
index f3f764e1..f339b729 100644
--- a/tmux.c
+++ b/tmux.c
@@ -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/tmux.h b/tmux.h
index 78869274..0dda8cff 100644
--- a/tmux.h
+++ b/tmux.h
@@ -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 *);