diff --git a/format.c b/format.c index e74de9c1..8ee4fa61 100644 --- a/format.c +++ b/format.c @@ -456,6 +456,35 @@ format_cb_pid(__unused struct format_tree *ft, struct format_entry *fe) xasprintf(&fe->value, "%ld", (long)getpid()); } +/* Callback for session_attached_list. */ +static void +format_cb_session_attached_list(struct format_tree *ft, struct format_entry *fe) +{ + struct session *s = ft->s; + struct client *loop; + struct evbuffer *buffer; + int size; + + if (s == NULL) + return; + + buffer = evbuffer_new(); + if (buffer == NULL) + fatalx("out of memory"); + + TAILQ_FOREACH(loop, &clients, entry) { + if (loop->session == s) { + if (EVBUFFER_LENGTH(buffer) > 0) + evbuffer_add(buffer, ",", 1); + evbuffer_add_printf(buffer, "%s", loop->name); + } + } + + if ((size = EVBUFFER_LENGTH(buffer)) != 0) + xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer)); + evbuffer_free(buffer); +} + /* Callback for session_alerts. */ static void format_cb_session_alerts(struct format_tree *ft, struct format_entry *fe) @@ -528,6 +557,128 @@ format_cb_window_stack_index(struct format_tree *ft, struct format_entry *fe) fe->value = xstrdup("0"); } +/* Callback for window_linked_sessions_list. */ +static void +format_cb_window_linked_sessions_list(struct format_tree *ft, + struct format_entry *fe) +{ + struct window *w = ft->wl->window; + struct winlink *wl; + struct evbuffer *buffer; + int size; + + buffer = evbuffer_new(); + if (buffer == NULL) + fatalx("out of memory"); + + TAILQ_FOREACH(wl, &w->winlinks, wentry) { + if (EVBUFFER_LENGTH(buffer) > 0) + evbuffer_add(buffer, ",", 1); + evbuffer_add_printf(buffer, "%s", wl->session->name); + } + + if ((size = EVBUFFER_LENGTH(buffer)) != 0) + xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer)); + evbuffer_free(buffer); +} + +/* Callback for window_active_sessions. */ +static void +format_cb_window_active_sessions(struct format_tree *ft, + struct format_entry *fe) +{ + struct window *w = ft->wl->window; + struct winlink *wl; + u_int n = 0; + + TAILQ_FOREACH(wl, &w->winlinks, wentry) { + if (wl->session->curw == wl) + n++; + } + + xasprintf(&fe->value, "%u", n); +} + +/* Callback for window_active_sessions_list. */ +static void +format_cb_window_active_sessions_list(struct format_tree *ft, + struct format_entry *fe) +{ + struct window *w = ft->wl->window; + struct winlink *wl; + struct evbuffer *buffer; + int size; + + buffer = evbuffer_new(); + if (buffer == NULL) + fatalx("out of memory"); + + TAILQ_FOREACH(wl, &w->winlinks, wentry) { + if (wl->session->curw == wl) { + if (EVBUFFER_LENGTH(buffer) > 0) + evbuffer_add(buffer, ",", 1); + evbuffer_add_printf(buffer, "%s", wl->session->name); + } + } + + if ((size = EVBUFFER_LENGTH(buffer)) != 0) + xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer)); + evbuffer_free(buffer); +} + +/* Callback for window_active_clients. */ +static void +format_cb_window_active_clients(struct format_tree *ft, struct format_entry *fe) +{ + struct window *w = ft->wl->window; + struct client *loop; + struct session *client_session; + u_int n = 0; + + TAILQ_FOREACH(loop, &clients, entry) { + client_session = loop->session; + if (client_session == NULL) + continue; + + if (w == client_session->curw->window) + n++; + } + + xasprintf(&fe->value, "%u", n); +} + +/* Callback for window_active_clients_list. */ +static void +format_cb_window_active_clients_list(struct format_tree *ft, + struct format_entry *fe) +{ + struct window *w = ft->wl->window; + struct client *loop; + struct session *client_session; + struct evbuffer *buffer; + int size; + + buffer = evbuffer_new(); + if (buffer == NULL) + fatalx("out of memory"); + + TAILQ_FOREACH(loop, &clients, entry) { + client_session = loop->session; + if (client_session == NULL) + continue; + + if (w == client_session->curw->window) { + if (EVBUFFER_LENGTH(buffer) > 0) + evbuffer_add(buffer, ",", 1); + evbuffer_add_printf(buffer, "%s", loop->name); + } + } + + if ((size = EVBUFFER_LENGTH(buffer)) != 0) + xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer)); + evbuffer_free(buffer); +} + /* Callback for window_layout. */ static void format_cb_window_layout(struct format_tree *ft, struct format_entry *fe) @@ -662,11 +813,52 @@ format_cb_session_group_list(struct format_tree *ft, struct format_entry *fe) buffer = evbuffer_new(); if (buffer == NULL) fatalx("out of memory"); + TAILQ_FOREACH(loop, &sg->sessions, gentry) { if (EVBUFFER_LENGTH(buffer) > 0) evbuffer_add(buffer, ",", 1); evbuffer_add_printf(buffer, "%s", loop->name); } + + if ((size = EVBUFFER_LENGTH(buffer)) != 0) + xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer)); + evbuffer_free(buffer); +} + +/* Callback for session_group_attached_list. */ +static void +format_cb_session_group_attached_list(struct format_tree *ft, + struct format_entry *fe) +{ + struct session *s = ft->s, *client_session, *session_loop; + struct session_group *sg; + struct client *loop; + struct evbuffer *buffer; + int size; + + if (s == NULL) + return; + sg = session_group_contains(s); + if (sg == NULL) + return; + + buffer = evbuffer_new(); + if (buffer == NULL) + fatalx("out of memory"); + + TAILQ_FOREACH(loop, &clients, entry) { + client_session = loop->session; + if (client_session == NULL) + continue; + TAILQ_FOREACH(session_loop, &sg->sessions, gentry) { + if (session_loop == client_session){ + if (EVBUFFER_LENGTH(buffer) > 0) + evbuffer_add(buffer, ",", 1); + evbuffer_add_printf(buffer, "%s", loop->name); + } + } + } + if ((size = EVBUFFER_LENGTH(buffer)) != 0) xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer)); evbuffer_free(buffer); @@ -2125,8 +2317,14 @@ format_defaults_session(struct format_tree *ft, struct session *s) format_add(ft, "session_group", "%s", sg->name); format_add(ft, "session_group_size", "%u", session_group_count (sg)); + format_add(ft, "session_group_attached", "%u", + session_group_attached_count (sg)); + format_add(ft, "session_group_many_attached", "%u", + session_group_attached_count (sg) > 1); format_add_cb(ft, "session_group_list", format_cb_session_group_list); + format_add_cb(ft, "session_group_attached_list", + format_cb_session_group_attached_list); } format_add_tv(ft, "session_created", &s->creation_time); @@ -2135,6 +2333,8 @@ format_defaults_session(struct format_tree *ft, struct session *s) format_add(ft, "session_attached", "%u", s->attached); format_add(ft, "session_many_attached", "%d", s->attached > 1); + format_add_cb(ft, "session_attached_list", + format_cb_session_attached_list); format_add_cb(ft, "session_alerts", format_cb_session_alerts); format_add_cb(ft, "session_stack", format_cb_session_stack); @@ -2249,6 +2449,14 @@ format_defaults_winlink(struct format_tree *ft, struct winlink *wl) format_add_cb(ft, "window_stack_index", format_cb_window_stack_index); format_add(ft, "window_flags", "%s", window_printable_flags(wl)); format_add(ft, "window_active", "%d", wl == s->curw); + format_add_cb(ft, "window_active_sessions", + format_cb_window_active_sessions); + format_add_cb(ft, "window_active_sessions_list", + format_cb_window_active_sessions_list); + format_add_cb(ft, "window_active_clients", + format_cb_window_active_clients); + format_add_cb(ft, "window_active_clients_list", + format_cb_window_active_clients_list); format_add(ft, "window_start_flag", "%d", !!(wl == RB_MIN(winlinks, &s->windows))); @@ -2269,6 +2477,11 @@ format_defaults_winlink(struct format_tree *ft, struct winlink *wl) format_add(ft, "window_last_flag", "%d", !!(wl == TAILQ_FIRST(&s->lastw))); format_add(ft, "window_linked", "%d", session_is_linked(s, wl->window)); + + format_add_cb(ft, "window_linked_sessions_list", + format_cb_window_linked_sessions_list); + format_add(ft, "window_linked_sessions", "%u", + wl->window->references); } /* Set default format keys for a window pane. */ diff --git a/session.c b/session.c index b1f49e41..be9c8e07 100644 --- a/session.c +++ b/session.c @@ -569,7 +569,20 @@ session_group_count(struct session_group *sg) n = 0; TAILQ_FOREACH(s, &sg->sessions, gentry) - n++; + n++; + return (n); +} + +/* Count number of clients attached to sessions in session group. */ +u_int +session_group_attached_count(struct session_group *sg) +{ + struct session *s; + u_int n; + + n = 0; + TAILQ_FOREACH(s, &sg->sessions, gentry) + n += s->attached; return (n); } diff --git a/tmux.1 b/tmux.1 index ce882193..ef288e5a 100644 --- a/tmux.1 +++ b/tmux.1 @@ -4310,10 +4310,14 @@ The following variables are available, where appropriate: .It Li "session_activity" Ta "" Ta "Time of session last activity" .It Li "session_alerts" Ta "" Ta "List of window indexes with alerts" .It Li "session_attached" Ta "" Ta "Number of clients session is attached to" +.It Li "session_attached_list" Ta "" Ta "List of clients session is attached to" .It Li "session_created" Ta "" Ta "Time session created" .It Li "session_format" Ta "" Ta "1 if format is for a session" .It Li "session_group" Ta "" Ta "Name of session group" +.It Li "session_group_attached" Ta "" Ta "Number of clients sessions in group are attached to" +.It Li "session_group_attached_list" Ta "" Ta "List of clients sessions in group are attached to" .It Li "session_group_list" Ta "" Ta "List of sessions in group" +.It Li "session_group_many_attached" Ta "" Ta "1 if multiple clients attached to sessions in group" .It Li "session_group_size" Ta "" Ta "Size of session group" .It Li "session_grouped" Ta "" Ta "1 if session in a group" .It Li "session_id" Ta "" Ta "Unique session ID" @@ -4325,6 +4329,10 @@ The following variables are available, where appropriate: .It Li "socket_path" Ta "" Ta "Server socket path" .It Li "start_time" Ta "" Ta "Server start time" .It Li "window_active" Ta "" Ta "1 if window active" +.It Li "window_active_clients" Ta "" Ta "Number of clients viewing this window" +.It Li "window_active_clients_list" Ta "" Ta "List of clients viewing this window" +.It Li "window_active_sessions" Ta "" Ta "Number of sessions on which this window is active" +.It Li "window_active_sessions_list" Ta "" Ta "List of sessions on which this window is active" .It Li "window_activity" Ta "" Ta "Time of window last activity" .It Li "window_activity_flag" Ta "" Ta "1 if window has activity" .It Li "window_bell_flag" Ta "" Ta "1 if window has bell" @@ -4340,6 +4348,8 @@ The following variables are available, where appropriate: .It Li "window_last_flag" Ta "" Ta "1 if window is the last used" .It Li "window_layout" Ta "" Ta "Window layout description, ignoring zoomed window panes" .It Li "window_linked" Ta "" Ta "1 if window is linked across sessions" +.It Li "window_linked_sessions" Ta "" Ta "Number of sessions this window is linked to" +.It Li "window_linked_sessions_list" Ta "" Ta "List of sessions this window is linked to" .It Li "window_marked_flag" Ta "" Ta "1 if window contains the marked pane" .It Li "window_name" Ta "#W" Ta "Name of window" .It Li "window_offset_x" Ta "" Ta "X offset into window if larger than client" diff --git a/tmux.h b/tmux.h index 72be101b..2315f643 100644 --- a/tmux.h +++ b/tmux.h @@ -2689,6 +2689,7 @@ void session_group_add(struct session_group *, struct session *); void session_group_synchronize_to(struct session *); void session_group_synchronize_from(struct session *); u_int session_group_count(struct session_group *); +u_int session_group_attached_count(struct session_group *); void session_renumber_windows(struct session *); /* utf8.c */