From 67141fb4bb904ea0d539821229d9ce1b85b5273d Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 9 Mar 2026 15:46:01 +0000 Subject: [PATCH] Add next/previous variables for windows in W: loop, from Conor Taylor in GitHub issue 4856. --- format.c | 42 ++++++++++++++++++++++++++++++++++++++++++ options-table.c | 4 ++-- tmux.1 | 19 +++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/format.c b/format.c index 2ed398c2..bdde54a3 100644 --- a/format.c +++ b/format.c @@ -4473,6 +4473,37 @@ format_window_name(struct format_expand_state *es, const char *fmt) return (xstrdup("0")); } +/* Add neighbor window variables to the format tree. */ +static void +format_add_window_neighbor(struct format_tree *nft, struct winlink *wl, + struct session *s, const char *prefix) +{ + struct options_entry *o; + const char *oname; + char *key, *prefixed, *oval; + + xasprintf(&key, "%s_window_index", prefix); + format_add(nft, key, "%u", wl->idx); + free(key); + + xasprintf(&key, "%s_window_active", prefix); + format_add(nft, key, "%d", wl == s->curw); + free(key); + + o = options_first(wl->window->options); + while (o != NULL) { + oname = options_name(o); + if (*oname == '@') { + xasprintf(&prefixed, "%s_%s", prefix, oname); + oval = options_to_string(o, -1, 1); + format_add(nft, prefixed, "%s", oval); + free(oval); + free(prefixed); + } + o = options_next(o); + } +} + /* Loop over windows. */ static char * format_loop_windows(struct format_expand_state *es, const char *fmt) @@ -4516,6 +4547,17 @@ format_loop_windows(struct format_expand_state *es, const char *fmt) nft = format_create(c, item, FORMAT_WINDOW|w->id, ft->flags|last); format_defaults(nft, ft->c, ft->s, wl, NULL); + + /* Add neighbor window data to the format tree. */ + format_add(nft, "window_after_active", "%d", + i > 0 && l[i - 1] == ft->s->curw); + format_add(nft, "window_before_active", "%d", + i + 1 < n && l[i + 1] == ft->s->curw); + if (i + 1 < n) + format_add_window_neighbor(nft, l[i + 1], ft->s, "next"); + if (i > 0) + format_add_window_neighbor(nft, l[i - 1], ft->s, "prev"); + format_copy_state(&next, es, 0); next.ft = nft; expanded = format_expand1(&next, use); diff --git a/options-table.c b/options-table.c index 78299328..2eb4f6d5 100644 --- a/options-table.c +++ b/options-table.c @@ -142,7 +142,7 @@ static const char *options_table_allow_passthrough_list[] = { "#{T:window-status-format}" \ "#[pop-default]" \ "#[norange default]" \ - "#{?loop_last_flag,,#{window-status-separator}}" \ + "#{?loop_last_flag,,#{E:window-status-separator}}" \ "," \ "#[range=window|#{window_index} list=focus " \ "#{?#{!=:#{E:window-status-current-style},default}," \ @@ -169,7 +169,7 @@ static const char *options_table_allow_passthrough_list[] = { "#{T:window-status-current-format}" \ "#[pop-default]" \ "#[norange list=on default]" \ - "#{?loop_last_flag,,#{window-status-separator}}" \ + "#{?loop_last_flag,,#{E:window-status-separator}}" \ "}" \ "#[nolist align=right range=right #{E:status-right-style}]" \ "#[push-default]" \ diff --git a/tmux.1 b/tmux.1 index 32b0c640..c404abab 100644 --- a/tmux.1 +++ b/tmux.1 @@ -6125,6 +6125,21 @@ For example, to get a list of windows formatted like the status line: #{W:#{E:window-status-format} ,#{E:window-status-current-format} } .Ed .Pp +Within the +.Ql W:\& +loop, user options +.Po +.Ql @name +.Pc +from neighboring windows are available with a +.Ql next_ +or +.Ql prev_ +prefix, for example a user option +.Ql @color +on the next window is available as +.Ql next_@color . +.Pp .Ql N:\& checks if a window (without any suffix or with the .Ql w @@ -6293,6 +6308,8 @@ The following variables are available, where appropriate: .It Li "mouse_x" Ta "" Ta "Mouse X position, if any" .It Li "mouse_y" Ta "" Ta "Mouse Y position, if any" .It Li "next_session_id" Ta "" Ta "Unique session ID for next new session" +.It Li "next_window_active" Ta "" Ta "1 if next window in W: loop is active" +.It Li "next_window_index" Ta "" Ta "Index of next window in W: loop" .It Li "origin_flag" Ta "" Ta "Pane origin flag" .It Li "pane_active" Ta "" Ta "1 if active pane" .It Li "pane_at_bottom" Ta "" Ta "1 if pane is at the bottom of window" @@ -6336,6 +6353,8 @@ The following variables are available, where appropriate: .It Li "pane_unseen_changes" Ta "" Ta "1 if there were changes in pane while in mode" .It Li "pane_width" Ta "" Ta "Width of pane" .It Li "pid" Ta "" Ta "Server PID" +.It Li "prev_window_active" Ta "" Ta "1 if previous window in W: loop is active" +.It Li "prev_window_index" Ta "" Ta "Index of previous window in W: loop" .It Li "rectangle_toggle" Ta "" Ta "1 if rectangle selection is activated" .It Li "scroll_position" Ta "" Ta "Scroll position in copy mode" .It Li "scroll_region_lower" Ta "" Ta "Bottom of scroll region in pane"