When enabling 'status-text', support the ability to specify new status
lines with a delimiter -- the semi-colon ';'. Standard formatting is
supported within the string.
---
cmd-new-session.c | 14 ++++-
options-table.c | 24 +++++++++
resize.c | 5 +-
screen-redraw.c | 4 +-
server-client.c | 3 +-
status.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++------
tmux.1 | 6 +++
tmux.h | 17 ++++--
tty.c | 2 +-
9 files changed, 198 insertions(+), 28 deletions(-)
diff --git a/cmd-new-session.c b/cmd-new-session.c
index 2d671275..a0b04180 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -78,7 +78,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
char **argv, *cause, *cp, *to_free = NULL;
int detached, already_attached, idx, argc;
int is_control = 0;
- u_int sx, sy;
+ u_int sx, sy, lines;
struct environ_entry *envent;
struct cmd_find_state fs;
@@ -219,6 +219,18 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item
*item)
if (sy == 0)
sy = 1;
+ /* Adjust for status line. */
+ if (options_get_number(global_s_options, "status")) {
+ lines = 1;
+ if (*options_get_string(global_s_options, "status-text") !=
'\0')
+ lines = status_line_size(c);
+ } else
+ lines = 0;
+ if (sy > lines)
+ sy -= lines;
+ else
+ sy = 1;
+
/* Figure out the command for the new window. */
argc = -1;
argv = NULL;
diff --git a/options-table.c b/options-table.c
index c9a69271..6c00d89f 100644
--- a/options-table.c
+++ b/options-table.c
@@ -380,6 +380,18 @@ const struct options_table_entry options_table[] = {
.style = "status-style"
},
+ { .name = "status-caption",
+ .type = OPTIONS_TABLE_FLAG,
+ .scope = OPTIONS_TABLE_SESSION,
+ .default_num = 1
+ },
+
+ { .name = "status-caption-text",
+ .type = OPTIONS_TABLE_STRING,
+ .scope = OPTIONS_TABLE_SESSION,
+ .default_str = ""
+ },
+
{ .name = "status-fg",
.type = OPTIONS_TABLE_COLOUR,
.scope = OPTIONS_TABLE_SESSION,
@@ -504,6 +516,18 @@ const struct options_table_entry options_table[] = {
.default_str = "bg=green,fg=black"
},
+ { .name = "status-text",
+ .type = OPTIONS_TABLE_STRING,
+ .scope = OPTIONS_TABLE_SESSION,
+ .default_str = ""
+ },
+
+ { .name = "status-text-style",
+ .type = OPTIONS_TABLE_STYLE,
+ .scope = OPTIONS_TABLE_SESSION,
+ .default_str = "bg=green,fg=black"
+ },
+
{ .name = "update-environment",
.type = OPTIONS_TABLE_ARRAY,
.scope = OPTIONS_TABLE_SESSION,
diff --git a/resize.c b/resize.c
index 8ed359b4..bd25599d 100644
--- a/resize.c
+++ b/resize.c
@@ -53,11 +53,11 @@ recalculate_sizes(void)
int flag, is_zoomed, forced;
RB_FOREACH(s, sessions, &sessions) {
- lines = status_line_size(s);
s->attached = 0;
ssx = ssy = UINT_MAX;
TAILQ_FOREACH(c, &clients, entry) {
+ lines = status_line_size(c);
if (c->flags & CLIENT_SUSPENDED)
continue;
if ((c->flags & (CLIENT_CONTROL|CLIENT_SIZECHANGED)) ==
@@ -71,8 +71,7 @@ recalculate_sizes(void)
c->flags |= CLIENT_STATUSOFF;
if ((~c->flags & CLIENT_STATUSOFF) &&
!(c->flags & CLIENT_CONTROL) &&
- c->tty.sy > lines &&
- c->tty.sy - lines < ssy)
+ c->tty.sy > 1 && c->tty.sy - 1 < ssy)
ssy = c->tty.sy - lines;
else if (c->tty.sy < ssy)
ssy = c->tty.sy;
diff --git a/screen-redraw.c b/screen-redraw.c
index df966aff..9fc3c3b0 100644
--- a/screen-redraw.c
+++ b/screen-redraw.c
@@ -388,7 +388,7 @@ screen_redraw_screen(struct client *c, int draw_panes, int
draw_status,
if (c->flags & CLIENT_STATUSOFF)
lines = 0;
else
- lines = status_line_size(c->session);
+ lines = status_line_size(c);
if (c->message_string != NULL || c->prompt_string != NULL)
lines = (lines == 0) ? 1 : lines;
@@ -425,7 +425,7 @@ screen_redraw_pane(struct client *c, struct window_pane *wp)
yoff = wp->yoff;
if (status_at_line(c) == 0)
- yoff += status_line_size(c->session);
+ yoff += status_line_size(c);
log_debug("%s: redraw pane %%%u (at %u,%u)", c->name, wp->id,
wp->xoff, yoff);
diff --git a/server-client.c b/server-client.c
index 4bee7616..09e7d902 100644
--- a/server-client.c
+++ b/server-client.c
@@ -194,6 +194,7 @@ server_client_create(int fd)
c->tty.sy = 24;
screen_init(&c->status.status, c->tty.sx, 1, 0);
+ TAILQ_INIT(&c->status.status_lines);
c->message_string = NULL;
TAILQ_INIT(&c->message_log);
@@ -1223,7 +1224,7 @@ server_client_reset_state(struct client *c)
if (status_at_line(c) != 0)
lines = 0;
else
- lines = status_line_size(c->session);
+ lines = status_line_size(c);
if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - lines)
tty_cursor(&c->tty, 0, 0);
else
diff --git a/status.c b/status.c
index 275220c5..60033941 100644
--- a/status.c
+++ b/status.c
@@ -40,6 +40,8 @@ static char *status_replace(struct client *, struct winlink
*, const char *,
static void status_message_callback(int, short, void *);
static void status_timer_callback(int, short, void *);
+static u_int status_lines_parse(struct client *);
+
static char *status_prompt_find_history_file(void);
static const char *status_prompt_up_history(u_int *);
static const char *status_prompt_down_history(u_int *);
@@ -167,6 +169,74 @@ status_timer_callback(__unused int fd, __unused short
events, void *arg)
log_debug("client %p, status interval %d", c, (int)tv.tv_sec);
}
+static u_int
+status_lines_parse(struct client *c)
+{
+ struct status_text *st = NULL, *st1;
+ const char *st_text;
+ char *st_text1, *text;
+ u_int size = 0, line = 1;
+
+ /* Blank string to indicate tearing down the status items. */
+ st_text = options_get_string(c->session->options, "status-text");
+ if (*st_text == '\0') {
+ /* Zeroed out. No more extra lines. */
+ if (TAILQ_EMPTY(&c->status.status_lines))
+ goto out;
+
+ TAILQ_FOREACH_SAFE(st, &c->status.status_lines, entry, st1) {
+ TAILQ_REMOVE(&c->status.status_lines, st, entry);
+ free((char *)st->text);
+ free(st);
+ }
+ goto out;
+ }
+
+ st_text1 = xstrdup(st_text);
+ /* If the status_line cache is empty then add everything we know
+ * about wholesale as a special case.
+ */
+ if (TAILQ_EMPTY(&c->status.status_lines)) {
+ while ((text = strsep(&st_text1, ";")) != NULL) {
+ if (*text == '\0')
+ continue;
+
+ st = xmalloc(sizeof *st);
+ st->text = xstrdup(text);
+ st->line = line;
+ TAILQ_INSERT_HEAD(&c->status.status_lines, st, entry);
+
+ line++;
+ }
+ goto out;
+ }
+
+ /* Tear down previous entries, and add new ones. */
+ TAILQ_FOREACH_SAFE(st, &c->status.status_lines, entry, st1) {
+ TAILQ_REMOVE(&c->status.status_lines, st, entry);
+ free((char *)st->text);
+ free(st);
+ }
+
+ while ((text = strsep(&st_text1, ";")) != NULL) {
+ st = xmalloc(sizeof *st);
+ st->text = xstrdup(text);
+ st->line = line;
+ TAILQ_INSERT_TAIL(&c->status.status_lines, st, entry);
+
+ line++;
+ }
+
+out:
+ size = 0;
+ TAILQ_FOREACH(st, &c->status.status_lines, entry) {
+ size++;
+ }
+
+ /* +1 to include the status line itself. */
+ return (size + 1);
+}
+
/* Start status timer for client. */
void
status_timer_start(struct client *c)
@@ -215,7 +285,7 @@ status_at_line(struct client *c)
return (-1);
if (s->statusat != 1)
return (s->statusat);
- return (c->tty.sy - status_line_size(s));
+ return (c->tty.sy - status_line_size(c));
}
/*
@@ -224,11 +294,19 @@ status_at_line(struct client *c)
* CLIENT_STATUSOFF flag is set for this).
*/
u_int
-status_line_size(struct session *s)
+status_line_size(struct client *c)
{
- if (s->statusat == -1)
+ struct session *s = c->session;
+ u_int lines = 1;
+
+ if (s == NULL || !options_get_number(s->options, "status"))
return (0);
- return (1);
+
+ lines = status_lines_parse(c);
+
+ if (s->sy < lines)
+ return (s->sy);
+ return (lines);
}
/* Retrieve options for left string. */
@@ -307,14 +385,15 @@ status_redraw(struct client *c)
struct session *s = c->session;
struct winlink *wl;
struct screen old_status, window_list;
- struct grid_cell stdgc, lgc, rgc, gc;
+ struct grid_cell stdgc, stextgc, lgc, rgc, gc;
struct options *oo;
+ struct status_text *st;
time_t t;
- char *left, *right;
- const char *sep;
- u_int offset, needed, lines;
+ char *left, *right, *expanded;
+ const char *sl, *sep;
+ u_int offset, needed, lines, i, x;
u_int wlstart, wlwidth, wlavailable, wloffset,
wlsize;
- size_t llen, rlen, seplen;
+ size_t llen, rlen, seplen, expandedlen;
int larrow, rarrow;
/* Delete the saved status line, if any. */
@@ -325,7 +404,7 @@ status_redraw(struct client *c)
}
/* No status line? */
- lines = status_line_size(s);
+ lines = status_line_size(c);
if (c->tty.sy == 0 || lines == 0)
return (1);
left = right = NULL;
@@ -336,13 +415,16 @@ status_redraw(struct client *c)
/* Set up default colour. */
style_apply(&stdgc, s->options, "status-style");
+ style_apply(&stextgc, s->options, "status-text-style");
/* Create the target screen. */
memcpy(&old_status, &c->status.status, sizeof old_status);
screen_init(&c->status.status, c->tty.sx, lines, 0);
screen_write_start(&ctx, NULL, &c->status.status);
- for (offset = 0; offset < lines * c->tty.sx; offset++)
- screen_write_putc(&ctx, &stdgc, ' ');
+ for (i = 0; i < lines; i++) {
+ for (offset = 0; offset < c->tty.sx; offset++)
+ screen_write_putc(&ctx, &stdgc, ' ');
+ }
screen_write_stop(&ctx);
/* If the height is too small, blank status line. */
@@ -512,6 +594,34 @@ draw:
screen_write_fast_copy(&ctx, &window_list, wlstart, 0, wlwidth, 1);
screen_free(&window_list);
+ /* Draw the status text line if any. */
+ i = 1;
+ TAILQ_FOREACH(st, &c->status.status_lines, entry) {
+ sl = st->text;
+ expanded = status_replace(c, NULL, sl, t);
+ expandedlen = screen_write_cstrlen("%s", expanded);
+ switch (options_get_number(s->options, "status-justify")) {
+ case 1: /* centred */
+ if (expandedlen > c->tty.sx)
+ x = 0;
+ else
+ x = c->tty.sx / 2 - expandedlen / 2;
+ break;
+ case 2: /* right */
+ if (expandedlen > c->tty.sx)
+ x = 0;
+ else
+ x = c->tty.sx - expandedlen;
+ break;
+ default:
+ x = 0;
+ break;
+ }
+ screen_write_cursormove(&ctx, x, st->line);
+ screen_write_cnputs(&ctx, c->tty.sx, &stextgc, "%s", expanded);
+ free(expanded);
+ }
+
screen_write_stop(&ctx);
out:
@@ -592,8 +702,7 @@ status_message_set(struct client *c, const char *fmt, ...)
status_message_clear(c);
if (c->status.old_status == NULL) {
- c->status.old_status = xmalloc(sizeof
- *c->status.old_status);
+ c->status.old_status = xmalloc(sizeof *c->status.old_status);
memcpy(c->status.old_status, &c->status.status,
sizeof *c->status.old_status);
screen_init(&c->status.status, c->tty.sx, 1, 0);
@@ -661,7 +770,7 @@ status_message_redraw(struct client *c)
return (0);
memcpy(&old_status, &c->status.status, sizeof old_status);
- lines = status_line_size(c->session);
+ lines = status_line_size(c);
if (lines <= 1) {
lines = 1;
screen_init(&c->status.status, c->tty.sx, 1, 0);
@@ -678,7 +787,12 @@ status_message_redraw(struct client *c)
screen_write_cursormove(&ctx, 0, 0);
for (offset = 0; offset < lines * c->tty.sx; offset++)
screen_write_putc(&ctx, &gc, ' ');
+ if (lines > 1) {
+ screen_write_copy(&ctx, &old_status, 0, 0, c->tty.sx, lines - 1,
+ NULL, NULL);
+ }
screen_write_cursormove(&ctx, 0, lines - 1);
+
screen_write_nputs(&ctx, len, &gc, "%s", c->message_string);
screen_write_stop(&ctx);
@@ -816,7 +930,7 @@ status_prompt_redraw(struct client *c)
return (0);
memcpy(&old_status, &c->status.status, sizeof old_status);
- lines = status_line_size(c->session);
+ lines = status_line_size(c);
if (lines <= 1) {
lines = 1;
screen_init(&c->status.status, c->tty.sx, 1, 0);
@@ -840,6 +954,11 @@ status_prompt_redraw(struct client *c)
start = c->tty.sx;
screen_write_start(&ctx, NULL, &c->status.status);
+
+ if (lines > 1) {
+ screen_write_copy(&ctx, &old_status, 0, 0, c->tty.sx, lines - 1,
+ NULL, NULL);
+ }
screen_write_cursormove(&ctx, 0, 0);
for (offset = 0; offset < lines * c->tty.sx; offset++)
screen_write_putc(&ctx, &gc, ' ');
diff --git a/tmux.1 b/tmux.1
index 5387e882..91cf7250 100644
--- a/tmux.1
+++ b/tmux.1
@@ -2960,6 +2960,12 @@ For how to specify
see the
.Ic message-command-style
option.
+.It Ic status-text Ar text
+If
+.Ar text
+is not empty, the status line is shown as two lines in height with
+.Ar text
+on the second line.
.It Ic update-environment[] Ar variable
Set list of environment variables to be copied into the session environment
when a new session is created or an existing session is attached.
diff --git a/tmux.h b/tmux.h
index 8c9ba561..0800d44f 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1315,10 +1315,19 @@ struct cmd_entry {
enum cmd_retval (*exec)(struct cmd *, struct cmdq_item *);
};
+struct status_text {
+ const char *text;
+ u_int line;
+
+ TAILQ_ENTRY(status_text) entry;
+};
+
struct status_line {
- struct event timer;
- struct screen status;
- struct screen *old_status;
+ struct event timer;
+ struct screen status;
+ struct screen *old_status;
+
+ TAILQ_HEAD(, status_text) status_lines;
};
/* Client connection. */
@@ -1934,7 +1943,7 @@ void status_timer_start(struct client *);
void status_timer_start_all(void);
void status_update_saved(struct session *s);
int status_at_line(struct client *);
-u_int status_line_size(struct session *);
+u_int status_line_size(struct client *);
struct window *status_get_window_at(struct client *, u_int);
int status_redraw(struct client *);
void printflike(2, 3) status_message_set(struct client *, const char *, ...);
diff --git a/tty.c b/tty.c
index 01208a25..ce8847fc 100644
--- a/tty.c
+++ b/tty.c
@@ -1061,7 +1061,7 @@ tty_write(void (*cmdfn)(struct tty *, const struct
tty_ctx *),
ctx->xoff = wp->xoff;
ctx->yoff = wp->yoff;
if (status_at_line(c) == 0)
- ctx->yoff += status_line_size(c->session);
+ ctx->yoff += status_line_size(c);
cmdfn(&c->tty, ctx);
}
--
2.15.1
--
You received this message because you are subscribed to the Google Groups
"tmux-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.