diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c index 65c3ae0a..815c2a03 100644 --- a/cmd-choose-tree.c +++ b/cmd-choose-tree.c @@ -30,8 +30,8 @@ const struct cmd_entry cmd_choose_tree_entry = { .name = "choose-tree", .alias = NULL, - .args = { "F:f:NO:st:w", 0, 1 }, - .usage = "[-Nsw] [-F format] [-f filter] [-O sort-order] " + .args = { "F:Gf:NO:st:w", 0, 1 }, + .usage = "[-GNsw] [-F format] [-f filter] [-O sort-order] " CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, diff --git a/format.c b/format.c index 04748a2f..46f1a522 100644 --- a/format.c +++ b/format.c @@ -587,8 +587,35 @@ format_cb_pane_tabs(struct format_tree *ft, struct format_entry *fe) evbuffer_add(buffer, ",", 1); evbuffer_add_printf(buffer, "%u", i); } - size = EVBUFFER_LENGTH(buffer); - xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer)); + if ((size = EVBUFFER_LENGTH(buffer)) != 0) + xasprintf(&fe->value, "%.*s", size, EVBUFFER_DATA(buffer)); + evbuffer_free(buffer); +} + +/* Callback for session_group_list. */ +static void +format_cb_session_group_list(struct format_tree *ft, struct format_entry *fe) +{ + struct session *s = ft->s; + struct session_group *sg; + struct session *loop; + struct evbuffer *buffer; + int size; + + if (s == NULL) + return; + sg = session_group_contains(s); + if (sg == NULL) + return; + + buffer = evbuffer_new(); + 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); } @@ -781,8 +808,11 @@ format_find(struct format_tree *ft, const char *key, int modifiers) found = s; goto found; } - if (fe->value == NULL && fe->cb != NULL) + if (fe->value == NULL && fe->cb != NULL) { fe->cb(ft, fe); + if (fe->value == NULL) + fe->value = xstrdup(""); + } found = fe->value; goto found; } @@ -1269,8 +1299,13 @@ format_defaults_session(struct format_tree *ft, struct session *s) sg = session_group_contains(s); format_add(ft, "session_grouped", "%d", sg != NULL); - if (sg != NULL) + if (sg != NULL) { format_add(ft, "session_group", "%s", sg->name); + format_add(ft, "session_group_size", "%u", + session_group_count (sg)); + format_add_cb(ft, "session_group_list", + format_cb_session_group_list); + } format_add_tv(ft, "session_created", &s->creation_time); format_add_tv(ft, "session_last_attached", &s->last_attached_time); diff --git a/screen.c b/screen.c index 4e234201..f6135b50 100644 --- a/screen.c +++ b/screen.c @@ -196,7 +196,8 @@ screen_resize(struct screen *s, u_int sx, u_int sy, int reflow) * is simpler and more reliable so let's do that. */ screen_reset_tabs(s); - } + } else + reflow = 0; if (sy != screen_size_y(s)) screen_resize_y(s, sy); diff --git a/session.c b/session.c index 6143807c..5b17f085 100644 --- a/session.c +++ b/session.c @@ -38,10 +38,6 @@ static struct winlink *session_next_alert(struct winlink *); static struct winlink *session_previous_alert(struct winlink *); static void session_group_remove(struct session *); -static u_int session_group_count(struct session_group *); -static void session_group_synchronize1(struct session *, struct session *); - -static u_int session_group_count(struct session_group *); static void session_group_synchronize1(struct session *, struct session *); RB_GENERATE(sessions, session, entry, session_cmp); @@ -623,7 +619,7 @@ session_group_remove(struct session *s) } /* Count number of sessions in session group. */ -static u_int +u_int session_group_count(struct session_group *sg) { struct session *s; diff --git a/tmux.1 b/tmux.1 index 9a9e5d7a..3061790d 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1432,7 +1432,7 @@ starts without the preview. This command works only if at least one client is attached. .It Xo .Ic choose-tree -.Op Fl Nsw +.Op Fl GNsw .Op Fl F Ar format .Op Fl f Ar filter .Op Fl O Ar sort-order @@ -1488,6 +1488,9 @@ If a filter would lead to an empty list, it is ignored. specifies the format for each item in the tree. .Fl N starts without the preview. +.Fl G +includes all sessions in any session groups in the tree rather than only the +first. This command works only if at least one client is attached. .It Xo .Ic display-panes @@ -3715,6 +3718,8 @@ The following variables are available, where appropriate: .It Li "session_format" Ta "" Ta "1 if format is for a session (not assuming the current)" .It Li "session_last_attached" Ta "" Ta "Time session last attached" .It Li "session_group" Ta "" Ta "Name of session group" +.It Li "session_group_size" Ta "" Ta "Size of session group" +.It Li "session_group_list" Ta "" Ta "List of sessions in group" .It Li "session_grouped" Ta "" Ta "1 if session in a group" .It Li "session_height" Ta "" Ta "Height of session" .It Li "session_id" Ta "" Ta "Unique session ID" diff --git a/tmux.h b/tmux.h index 578fbb4d..b1d12361 100644 --- a/tmux.h +++ b/tmux.h @@ -2339,6 +2339,7 @@ struct session_group *session_group_new(const char *); 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 *); void session_renumber_windows(struct session *); /* utf8.c */ diff --git a/window-tree.c b/window-tree.c index a58154b8..a1c511de 100644 --- a/window-tree.c +++ b/window-tree.c @@ -43,8 +43,10 @@ static void window_tree_key(struct window_pane *, "#{?#{==:#{window_panes},1}, \"#{pane_title}\",}" \ "," \ "#{session_windows} windows" \ - "#{?session_grouped, (group ,}" \ - "#{session_group}#{?session_grouped,),}" \ + "#{?session_grouped, " \ + "(group #{session_group}: " \ + "#{session_group_list})," \ + "}" \ "#{?session_attached, (attached),}" \ "}" \ "}" @@ -91,6 +93,7 @@ struct window_tree_modedata { struct mode_tree_data *data; char *format; char *command; + int squash_groups; struct window_tree_itemdata **item_list; u_int item_size; @@ -394,8 +397,11 @@ window_tree_build(void *modedata, u_int sort_type, uint64_t *tag, { struct window_tree_modedata *data = modedata; struct session *s, **l; + struct session_group *sg, *current; u_int n, i; + current = session_group_contains(data->fs.s); + for (i = 0; i < data->item_size; i++) window_tree_free_item(data->item_list[i]); free(data->item_list); @@ -405,6 +411,12 @@ window_tree_build(void *modedata, u_int sort_type, uint64_t *tag, l = NULL; n = 0; RB_FOREACH(s, sessions, &sessions) { + if (data->squash_groups && + (sg = session_group_contains(s)) != NULL) { + if ((sg == current && s != data->fs.s) || + (sg != current && s != TAILQ_FIRST(&sg->sessions))) + continue; + } l = xreallocarray(l, n + 1, sizeof *l); l[n++] = s; } @@ -805,6 +817,7 @@ window_tree_init(struct window_pane *wp, struct cmd_find_state *fs, data->command = xstrdup(WINDOW_TREE_DEFAULT_COMMAND); else data->command = xstrdup(args->argv[0]); + data->squash_groups = !args_has(args, 'G'); data->data = mode_tree_start(wp, args, window_tree_build, window_tree_draw, window_tree_search, data, window_tree_sort_list,