mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	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:
		@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										107
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								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 = '#';
 | 
			
		||||
	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
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								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"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								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);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								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 *);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user