Compare commits

..

3 Commits

Author SHA1 Message Date
Michael Grant
2f7429c556
Merge 76b8ee08ef244537c4050bb99346a550c7d5222d into 7e439539377e272f37d18bb10dbff374b87acee6 2025-07-02 22:29:03 +02:00
Thomas Adam
7e43953937 Merge branch 'obsd-master' 2025-07-02 12:01:08 +01:00
nicm
28481e984b Add sorting to W, P, L operators as well, and add some new session
format variables. From Michael Grant in GitHub issue 4516.
2025-07-02 08:13:09 +00:00
4 changed files with 363 additions and 31 deletions

345
format.c
View File

@ -140,7 +140,7 @@ enum format_loop_sort_type {
}; };
static struct format_loop_sort_criteria { static struct format_loop_sort_criteria {
u_int field; enum format_loop_sort_type field;
int reversed; int reversed;
} format_loop_sort_criteria; } format_loop_sort_criteria;
@ -554,6 +554,38 @@ format_cb_session_attached_list(struct format_tree *ft)
return (value); return (value);
} }
/* Callback for session_alert. */
static void *
format_cb_session_alert(struct format_tree *ft)
{
struct session *s = ft->s;
struct winlink *wl;
char alerts[1024];
int alerted = 0;
if (s == NULL)
return (NULL);
*alerts = '\0';
RB_FOREACH(wl, winlinks, &s->windows) {
if ((wl->flags & WINLINK_ALERTFLAGS) == 0)
continue;
if (~alerted & wl->flags & WINLINK_ACTIVITY) {
strlcat(alerts, "#", sizeof alerts);
alerted |= WINLINK_ACTIVITY;
}
if (~alerted & wl->flags & WINLINK_BELL) {
strlcat(alerts, "!", sizeof alerts);
alerted |= WINLINK_BELL;
}
if (~alerted & wl->flags & WINLINK_SILENCE) {
strlcat(alerts, "~", sizeof alerts);
alerted |= WINLINK_SILENCE;
}
}
return (xstrdup(alerts));
}
/* Callback for session_alerts. */ /* Callback for session_alerts. */
static void * static void *
format_cb_session_alerts(struct format_tree *ft) format_cb_session_alerts(struct format_tree *ft)
@ -1743,6 +1775,15 @@ format_cb_keypad_flag(struct format_tree *ft)
return (NULL); return (NULL);
} }
/* Callback for loop_last_flag. */
static void *
format_cb_loop_last_flag(struct format_tree *ft)
{
if (ft->flags & FORMAT_LAST)
return (xstrdup("1"));
return (xstrdup("0"));
}
/* Callback for mouse_all_flag. */ /* Callback for mouse_all_flag. */
static void * static void *
format_cb_mouse_all_flag(struct format_tree *ft) format_cb_mouse_all_flag(struct format_tree *ft)
@ -2264,6 +2305,66 @@ format_cb_server_sessions(__unused struct format_tree *ft)
return (format_printf("%u", n)); return (format_printf("%u", n));
} }
/* Callback for session_active. */
static void *
format_cb_session_active(struct format_tree *ft)
{
if (ft->s == NULL || ft->c == NULL)
return (NULL);
if (ft->c->session == ft->s)
return (xstrdup("1"));
return (xstrdup("0"));
}
/* Callback for session_activity_flag. */
static void *
format_cb_session_activity_flag(struct format_tree *ft)
{
struct winlink *wl;
if (ft->s != NULL) {
RB_FOREACH(wl, winlinks, &ft->s->windows) {
if (ft->wl->flags & WINLINK_ACTIVITY)
return (xstrdup("1"));
return (xstrdup("0"));
}
}
return (NULL);
}
/* Callback for session_bell_flag. */
static void *
format_cb_session_bell_flag(struct format_tree *ft)
{
struct winlink *wl;
if (ft->s != NULL) {
RB_FOREACH(wl, winlinks, &ft->s->windows) {
if (wl->flags & WINLINK_BELL)
return (xstrdup("1"));
return (xstrdup("0"));
}
}
return (NULL);
}
/* Callback for session_silence_flag. */
static void *
format_cb_session_silence_flag(struct format_tree *ft)
{
struct winlink *wl;
if (ft->s != NULL) {
RB_FOREACH(wl, winlinks, &ft->s->windows) {
if (ft->wl->flags & WINLINK_SILENCE)
return (xstrdup("1"));
return (xstrdup("0"));
}
}
return (NULL);
}
/* Callback for session_attached. */ /* Callback for session_attached. */
static void * static void *
format_cb_session_attached(struct format_tree *ft) format_cb_session_attached(struct format_tree *ft)
@ -3054,6 +3155,9 @@ static const struct format_table_entry format_table[] = {
{ "last_window_index", FORMAT_TABLE_STRING, { "last_window_index", FORMAT_TABLE_STRING,
format_cb_last_window_index format_cb_last_window_index
}, },
{ "loop_last_flag", FORMAT_TABLE_STRING,
format_cb_loop_last_flag
},
{ "mouse_all_flag", FORMAT_TABLE_STRING, { "mouse_all_flag", FORMAT_TABLE_STRING,
format_cb_mouse_all_flag format_cb_mouse_all_flag
}, },
@ -3234,9 +3338,18 @@ static const struct format_table_entry format_table[] = {
{ "server_sessions", FORMAT_TABLE_STRING, { "server_sessions", FORMAT_TABLE_STRING,
format_cb_server_sessions format_cb_server_sessions
}, },
{ "session_active", FORMAT_TABLE_STRING,
format_cb_session_active
},
{ "session_activity", FORMAT_TABLE_TIME, { "session_activity", FORMAT_TABLE_TIME,
format_cb_session_activity format_cb_session_activity
}, },
{ "session_activity_flag", FORMAT_TABLE_STRING,
format_cb_session_activity_flag
},
{ "session_alert", FORMAT_TABLE_STRING,
format_cb_session_alert
},
{ "session_alerts", FORMAT_TABLE_STRING, { "session_alerts", FORMAT_TABLE_STRING,
format_cb_session_alerts format_cb_session_alerts
}, },
@ -3246,6 +3359,9 @@ static const struct format_table_entry format_table[] = {
{ "session_attached_list", FORMAT_TABLE_STRING, { "session_attached_list", FORMAT_TABLE_STRING,
format_cb_session_attached_list format_cb_session_attached_list
}, },
{ "session_bell_flag", FORMAT_TABLE_STRING,
format_cb_session_bell_flag
},
{ "session_created", FORMAT_TABLE_TIME, { "session_created", FORMAT_TABLE_TIME,
format_cb_session_created format_cb_session_created
}, },
@ -3291,6 +3407,9 @@ static const struct format_table_entry format_table[] = {
{ "session_path", FORMAT_TABLE_STRING, { "session_path", FORMAT_TABLE_STRING,
format_cb_session_path format_cb_session_path
}, },
{ "session_silence_flag", FORMAT_TABLE_STRING,
format_cb_session_silence_flag
},
{ "session_stack", FORMAT_TABLE_STRING, { "session_stack", FORMAT_TABLE_STRING,
format_cb_session_stack format_cb_session_stack
}, },
@ -4044,7 +4163,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
} }
/* Now try single character with arguments. */ /* Now try single character with arguments. */
if (strchr("mCNSst=pReq", cp[0]) == NULL) if (strchr("mCLNPSst=pReqW", cp[0]) == NULL)
break; break;
c = cp[0]; c = cp[0];
@ -4243,13 +4362,14 @@ format_session_name(struct format_expand_state *es, const char *fmt)
static int static int
format_cmp_session(const void *a0, const void *b0) format_cmp_session(const void *a0, const void *b0)
{ {
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
const struct session *const *a = a0; const struct session *const *a = a0;
const struct session *const *b = b0; const struct session *const *b = b0;
const struct session *sa = *a; const struct session *sa = *a;
const struct session *sb = *b; const struct session *sb = *b;
int result = 0; int result = 0;
switch (format_loop_sort_criteria.field) { switch (sc->field) {
case FORMAT_LOOP_BY_INDEX: case FORMAT_LOOP_BY_INDEX:
result = sa->id - sb->id; result = sa->id - sb->id;
break; break;
@ -4268,7 +4388,7 @@ format_cmp_session(const void *a0, const void *b0)
break; break;
} }
if (format_loop_sort_criteria.reversed) if (sc->reversed)
result = -result; result = -result;
return (result); return (result);
} }
@ -4285,7 +4405,7 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
char *all, *active, *use, *expanded, *value; char *all, *active, *use, *expanded, *value;
size_t valuelen; size_t valuelen;
struct session *s; struct session *s;
int i, n; int i, n, last = 0;
static struct session **l = NULL; static struct session **l = NULL;
static int lsz = 0; static int lsz = 0;
@ -4315,7 +4435,9 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
use = active; use = active;
else else
use = all; use = all;
nft = format_create(c, item, FORMAT_NONE, ft->flags); if (i == n - 1)
last = FORMAT_LAST;
nft = format_create(c, item, FORMAT_NONE, ft->flags|last);
format_defaults(nft, ft->c, s, NULL, NULL); format_defaults(nft, ft->c, s, NULL, NULL);
format_copy_state(&next, es, 0); format_copy_state(&next, es, 0);
next.ft = nft; next.ft = nft;
@ -4356,6 +4478,40 @@ format_window_name(struct format_expand_state *es, const char *fmt)
return (xstrdup("0")); return (xstrdup("0"));
} }
static int
format_cmp_window(const void *a0, const void *b0)
{
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
const struct winlink *const *a = a0;
const struct winlink *const *b = b0;
const struct window *wa = (*a)->window;
const struct window *wb = (*b)->window;
int result = 0;
switch (sc->field) {
case FORMAT_LOOP_BY_INDEX:
result = wa->id - wb->id;
break;
case FORMAT_LOOP_BY_TIME:
if (timercmp(&wa->activity_time, &wb->activity_time, >)) {
result = -1;
break;
}
if (timercmp(&wa->activity_time, &wb->activity_time, <)) {
result = 1;
break;
}
/* FALLTHROUGH */
case FORMAT_LOOP_BY_NAME:
result = strcmp(wa->name, wb->name);
break;
}
if (sc->reversed)
result = -result;
return (result);
}
/* Loop over windows. */ /* Loop over windows. */
static char * static char *
format_loop_windows(struct format_expand_state *es, const char *fmt) format_loop_windows(struct format_expand_state *es, const char *fmt)
@ -4369,6 +4525,9 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
size_t valuelen; size_t valuelen;
struct winlink *wl; struct winlink *wl;
struct window *w; struct window *w;
int i, n, last = 0;
static struct winlink **l = NULL;
static int lsz = 0;
if (ft->s == NULL) { if (ft->s == NULL) {
format_log(es, "window loop but no session"); format_log(es, "window loop but no session");
@ -4380,17 +4539,32 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
active = NULL; active = NULL;
} }
n = 0;
RB_FOREACH(wl, winlinks, &ft->s->windows) {
if (lsz <= n) {
lsz += 100;
l = xreallocarray(l, lsz, sizeof *l);
}
l[n++] = wl;
}
qsort(l, n, sizeof *l, format_cmp_window);
value = xcalloc(1, 1); value = xcalloc(1, 1);
valuelen = 1; valuelen = 1;
RB_FOREACH(wl, winlinks, &ft->s->windows) { for (i = 0; i < n; i++) {
wl = l[i];
w = wl->window; w = wl->window;
format_log(es, "window loop: %u @%u", wl->idx, w->id); format_log(es, "window loop: %u @%u", wl->idx, w->id);
if (active != NULL && wl == ft->s->curw) if (active != NULL && wl == ft->s->curw)
use = active; use = active;
else else
use = all; use = all;
nft = format_create(c, item, FORMAT_WINDOW|w->id, ft->flags); if (i == n - 1)
last = FORMAT_LAST;
nft = format_create(c, item, FORMAT_WINDOW|w->id,
ft->flags|last);
format_defaults(nft, ft->c, ft->s, wl, NULL); format_defaults(nft, ft->c, ft->s, wl, NULL);
format_copy_state(&next, es, 0); format_copy_state(&next, es, 0);
next.ft = nft; next.ft = nft;
@ -4410,6 +4584,23 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
return (value); return (value);
} }
static int
format_cmp_pane(const void *a0, const void *b0)
{
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
const struct window_pane *const *a = a0;
const struct window_pane *const *b = b0;
const struct window_pane *wpa = *a;
const struct window_pane *wpb = *b;
int result = 0;
if (sc->reversed)
result = wpb->id - wpa->id;
else
result = wpa->id - wpb->id;
return (result);
}
/* Loop over panes. */ /* Loop over panes. */
static char * static char *
format_loop_panes(struct format_expand_state *es, const char *fmt) format_loop_panes(struct format_expand_state *es, const char *fmt)
@ -4422,6 +4613,9 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
char *all, *active, *use, *expanded, *value; char *all, *active, *use, *expanded, *value;
size_t valuelen; size_t valuelen;
struct window_pane *wp; struct window_pane *wp;
int i, n, last = 0;
static struct window_pane **l = NULL;
static int lsz = 0;
if (ft->w == NULL) { if (ft->w == NULL) {
format_log(es, "pane loop but no window"); format_log(es, "pane loop but no window");
@ -4433,16 +4627,31 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
active = NULL; active = NULL;
} }
n = 0;
TAILQ_FOREACH(wp, &ft->w->panes, entry) {
if (lsz <= n) {
lsz += 100;
l = xreallocarray(l, lsz, sizeof *l);
}
l[n++] = wp;
}
qsort(l, n, sizeof *l, format_cmp_pane);
value = xcalloc(1, 1); value = xcalloc(1, 1);
valuelen = 1; valuelen = 1;
TAILQ_FOREACH(wp, &ft->w->panes, entry) { for (i = 0; i < n; i++) {
wp = l[i];
format_log(es, "pane loop: %%%u", wp->id); format_log(es, "pane loop: %%%u", wp->id);
if (active != NULL && wp == ft->w->active) if (active != NULL && wp == ft->w->active)
use = active; use = active;
else else
use = all; use = all;
nft = format_create(c, item, FORMAT_PANE|wp->id, ft->flags); if (i == n - 1)
last = FORMAT_LAST;
nft = format_create(c, item, FORMAT_PANE|wp->id,
ft->flags|last);
format_defaults(nft, ft->c, ft->s, ft->wl, wp); format_defaults(nft, ft->c, ft->s, ft->wl, wp);
format_copy_state(&next, es, 0); format_copy_state(&next, es, 0);
next.ft = nft; next.ft = nft;
@ -4462,10 +4671,44 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
return (value); return (value);
} }
static int
format_cmp_client(const void *a0, const void *b0)
{
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
const struct client *const *a = a0;
const struct client *const *b = b0;
const struct client *ca = *a;
const struct client *cb = *b;
int result = 0;
switch (sc->field) {
case FORMAT_LOOP_BY_INDEX:
break;
case FORMAT_LOOP_BY_TIME:
if (timercmp(&ca->activity_time, &cb->activity_time, >)) {
result = -1;
break;
}
if (timercmp(&ca->activity_time, &cb->activity_time, <)) {
result = 1;
break;
}
/* FALLTHROUGH */
case FORMAT_LOOP_BY_NAME:
result = strcmp(ca->name, cb->name);
break;
}
if (sc->reversed)
result = -result;
return (result);
}
/* Loop over clients. */ /* Loop over clients. */
static char * static char *
format_loop_clients(struct format_expand_state *es, const char *fmt) format_loop_clients(struct format_expand_state *es, const char *fmt)
{ {
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
struct format_tree *ft = es->ft; struct format_tree *ft = es->ft;
struct client *c; struct client *c;
struct cmdq_item *item = ft->item; struct cmdq_item *item = ft->item;
@ -4473,13 +4716,41 @@ format_loop_clients(struct format_expand_state *es, const char *fmt)
struct format_expand_state next; struct format_expand_state next;
char *expanded, *value; char *expanded, *value;
size_t valuelen; size_t valuelen;
int i, n, last = 0;
static struct client **l = NULL;
static int lsz = 0;
value = xcalloc(1, 1); value = xcalloc(1, 1);
valuelen = 1; valuelen = 1;
n = 0;
TAILQ_FOREACH(c, &clients, entry) { TAILQ_FOREACH(c, &clients, entry) {
if (lsz <= n) {
lsz += 100;
l = xreallocarray(l, lsz, sizeof *l);
}
l[n++] = c;
}
if (sc->field != FORMAT_LOOP_BY_INDEX)
qsort(l, n, sizeof *l, format_cmp_client);
else {
/* Use order in the TAILQ as "index" order. */
if (sc->reversed) {
for (i = 0; i < n / 2; i++) {
c = l[i];
l[i] = l[n - 1 - i];
l[n - 1 - i] = c;
}
}
}
for (i = 0; i < n; i++) {
c = l[i];
format_log(es, "client loop: %s", c->name); format_log(es, "client loop: %s", c->name);
nft = format_create(c, item, 0, ft->flags); if (i == n - 1)
last = FORMAT_LAST;
nft = format_create(c, item, 0, ft->flags|last);
format_defaults(nft, c, ft->s, ft->wl, ft->wp); format_defaults(nft, c, ft->s, ft->wl, ft->wp);
format_copy_state(&next, es, 0); format_copy_state(&next, es, 0);
next.ft = nft; next.ft = nft;
@ -4643,6 +4914,7 @@ static int
format_replace(struct format_expand_state *es, const char *key, size_t keylen, format_replace(struct format_expand_state *es, const char *key, size_t keylen,
char **buf, size_t *len, size_t *off) char **buf, size_t *len, size_t *off)
{ {
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
struct format_tree *ft = es->ft; struct format_tree *ft = es->ft;
struct window_pane *wp = ft->wp; struct window_pane *wp = ft->wp;
const char *errstr, *copy, *cp, *cp2; const char *errstr, *copy, *cp, *cp2;
@ -4658,7 +4930,6 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
struct format_modifier *bool_op_n = NULL; struct format_modifier *bool_op_n = NULL;
u_int i, count, nsub = 0, nrep; u_int i, count, nsub = 0, nrep;
struct format_expand_state next; struct format_expand_state next;
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
/* Make a copy of the key. */ /* Make a copy of the key. */
copy = copy0 = xstrndup(key, keylen); copy = copy0 = xstrndup(key, keylen);
@ -4769,15 +5040,19 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
break; break;
case 'S': case 'S':
modifiers |= FORMAT_SESSIONS; modifiers |= FORMAT_SESSIONS;
if (fm->argc < 1) if (fm->argc < 1) {
sc->field = FORMAT_LOOP_BY_INDEX;
sc->reversed = 0;
break; break;
}
if (strchr(fm->argv[0], 'i') != NULL) if (strchr(fm->argv[0], 'i') != NULL)
sc->field = FORMAT_LOOP_BY_INDEX; sc->field = FORMAT_LOOP_BY_INDEX;
else if (strchr(fm->argv[0], 'n') != NULL) else if (strchr(fm->argv[0], 'n') != NULL)
sc->field = FORMAT_LOOP_BY_NAME; sc->field = FORMAT_LOOP_BY_NAME;
else if (strchr(fm->argv[0], 't') != NULL) else if (strchr(fm->argv[0], 't') != NULL)
sc->field = FORMAT_LOOP_BY_TIME; sc->field = FORMAT_LOOP_BY_TIME;
else sc->field = FORMAT_LOOP_BY_INDEX; else
sc->field = FORMAT_LOOP_BY_INDEX;
if (strchr(fm->argv[0], 'r') != NULL) if (strchr(fm->argv[0], 'r') != NULL)
sc->reversed = 1; sc->reversed = 1;
else else
@ -4785,12 +5060,54 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
break; break;
case 'W': case 'W':
modifiers |= FORMAT_WINDOWS; modifiers |= FORMAT_WINDOWS;
if (fm->argc < 1) {
sc->field = FORMAT_LOOP_BY_INDEX;
sc->reversed = 0;
break;
}
if (strchr(fm->argv[0], 'i') != NULL)
sc->field = FORMAT_LOOP_BY_INDEX;
else if (strchr(fm->argv[0], 'n') != NULL)
sc->field = FORMAT_LOOP_BY_NAME;
else if (strchr(fm->argv[0], 't') != NULL)
sc->field = FORMAT_LOOP_BY_TIME;
else
sc->field = FORMAT_LOOP_BY_INDEX;
if (strchr(fm->argv[0], 'r') != NULL)
sc->reversed = 1;
else
sc->reversed = 0;
break; break;
case 'P': case 'P':
modifiers |= FORMAT_PANES; modifiers |= FORMAT_PANES;
if (fm->argc < 1) {
sc->reversed = 0;
break;
}
if (strchr(fm->argv[0], 'r') != NULL)
sc->reversed = 1;
else
sc->reversed = 0;
break; break;
case 'L': case 'L':
modifiers |= FORMAT_CLIENTS; modifiers |= FORMAT_CLIENTS;
if (fm->argc < 1) {
sc->field = FORMAT_LOOP_BY_INDEX;
sc->reversed = 0;
break;
}
if (strchr(fm->argv[0], 'i') != NULL)
sc->field = FORMAT_LOOP_BY_INDEX;
else if (strchr(fm->argv[0], 'n') != NULL)
sc->field = FORMAT_LOOP_BY_NAME;
else if (strchr(fm->argv[0], 't') != NULL)
sc->field = FORMAT_LOOP_BY_TIME;
else
sc->field = FORMAT_LOOP_BY_INDEX;
if (strchr(fm->argv[0], 'r') != NULL)
sc->reversed = 1;
else
sc->reversed = 0;
break; break;
case 'R': case 'R':
modifiers |= FORMAT_REPEAT; modifiers |= FORMAT_REPEAT;

View File

@ -138,7 +138,7 @@ static const char *options_table_allow_passthrough_list[] = {
"#{T:window-status-format}" \ "#{T:window-status-format}" \
"#[pop-default]" \ "#[pop-default]" \
"#[norange default]" \ "#[norange default]" \
"#{?window_end_flag,,#{window-status-separator}}" \ "#{?loop_last_flag,,#{window-status-separator}}" \
"," \ "," \
"#[range=window|#{window_index} list=focus " \ "#[range=window|#{window_index} list=focus " \
"#{?#{!=:#{E:window-status-current-style},default}," \ "#{?#{!=:#{E:window-status-current-style},default}," \
@ -165,7 +165,7 @@ static const char *options_table_allow_passthrough_list[] = {
"#{T:window-status-current-format}" \ "#{T:window-status-current-format}" \
"#[pop-default]" \ "#[pop-default]" \
"#[norange list=on default]" \ "#[norange list=on default]" \
"#{?window_end_flag,,#{window-status-separator}}" \ "#{?loop_last_flag,,#{window-status-separator}}" \
"}" \ "}" \
"#[nolist align=right range=right #{E:status-right-style}]" \ "#[nolist align=right range=right #{E:status-right-style}]" \
"#[push-default]" \ "#[push-default]" \

18
tmux.1
View File

@ -5911,14 +5911,21 @@ or
.Ql L:\& .Ql L:\&
will loop over each session, window, pane or client and insert the format once will loop over each session, window, pane or client and insert the format once
for each. for each.
.Ql S:\& , .Ql L:\& ,
.Ql S:\&
and
.Ql W:\&
can take an optional sort argument can take an optional sort argument
.Ql /i\& , .Ql /i\& ,
.Ql /n\& , .Ql /n\& ,
.Ql /t\& .Ql /t\&
to sort by index, name, or time; or to sort by index, name, or last activity time; additionally
.Ql /r\& .Ql /r\&
to sort in reverse order. to sort in reverse order.
.Ql /r\&
can also be used with
.Ql P:\&
to reverse the sort order by pane index.
For example, For example,
.Ql S/nr:\& .Ql S/nr:\&
to sort sessions by name in reverse order. to sort sessions by name in reverse order.
@ -6070,8 +6077,10 @@ The following variables are available, where appropriate:
.It Li "insert_flag" Ta "" Ta "Pane insert flag" .It Li "insert_flag" Ta "" Ta "Pane insert flag"
.It Li "keypad_cursor_flag" Ta "" Ta "Pane keypad cursor flag" .It Li "keypad_cursor_flag" Ta "" Ta "Pane keypad cursor flag"
.It Li "keypad_flag" Ta "" Ta "Pane keypad flag" .It Li "keypad_flag" Ta "" Ta "Pane keypad flag"
.It Li "last_session_index" Ta "" Ta "Index of last session"
.It Li "last_window_index" Ta "" Ta "Index of last window in session" .It Li "last_window_index" Ta "" Ta "Index of last window in session"
.It Li "line" Ta "" Ta "Line number in the list" .It Li "line" Ta "" Ta "Line number in the list"
.It Li "loop_last_flag" Ta "" Ta "1 if last window, pane, session, client in the W:, P:, S:, or L: loop"
.It Li "mouse_all_flag" Ta "" Ta "Pane mouse all flag" .It Li "mouse_all_flag" Ta "" Ta "Pane mouse all flag"
.It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag" .It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag"
.It Li "mouse_button_flag" Ta "" Ta "Pane mouse button flag" .It Li "mouse_button_flag" Ta "" Ta "Pane mouse button flag"
@ -6143,10 +6152,13 @@ The following variables are available, where appropriate:
.It Li "selection_start_x" Ta "" Ta "X position of the start of the selection" .It Li "selection_start_x" Ta "" Ta "X position of the start of the selection"
.It Li "selection_start_y" Ta "" Ta "Y position of the start of the selection" .It Li "selection_start_y" Ta "" Ta "Y position of the start of the selection"
.It Li "server_sessions" Ta "" Ta "Number of sessions" .It Li "server_sessions" Ta "" Ta "Number of sessions"
.It Li "session_active" Ta "" Ta "1 if session active"
.It Li "session_activity" Ta "" Ta "Time of session last activity" .It Li "session_activity" Ta "" Ta "Time of session last activity"
.It Li "session_activity_flag" Ta "" Ta "1 if any window in session has activity"
.It Li "session_alerts" Ta "" Ta "List of window indexes with alerts" .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" 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_attached_list" Ta "" Ta "List of clients session is attached to"
.It Li "session_bell_flag" Ta "" Ta "1 if any window in session has bell"
.It Li "session_created" Ta "" Ta "Time session created" .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_format" Ta "" Ta "1 if format is for a session"
.It Li "session_group" Ta "" Ta "Name of session group" .It Li "session_group" Ta "" Ta "Name of session group"
@ -6157,11 +6169,13 @@ The following variables are available, where appropriate:
.It Li "session_group_size" Ta "" Ta "Size of session 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_grouped" Ta "" Ta "1 if session in a group"
.It Li "session_id" Ta "" Ta "Unique session ID" .It Li "session_id" Ta "" Ta "Unique session ID"
.It Li "session_index" Ta "" Ta "Index of session"
.It Li "session_last_attached" Ta "" Ta "Time session last attached" .It Li "session_last_attached" Ta "" Ta "Time session last attached"
.It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached" .It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached"
.It Li "session_marked" Ta "" Ta "1 if this session contains the marked pane" .It Li "session_marked" Ta "" Ta "1 if this session contains the marked pane"
.It Li "session_name" Ta "#S" Ta "Name of session" .It Li "session_name" Ta "#S" Ta "Name of session"
.It Li "session_path" Ta "" Ta "Working directory of session" .It Li "session_path" Ta "" Ta "Working directory of session"
.It Li "session_silence_flag" Ta "" Ta "1 if any window in session has silence alert"
.It Li "session_stack" Ta "" Ta "Window indexes in most recent order" .It Li "session_stack" Ta "" Ta "Window indexes in most recent order"
.It Li "session_windows" Ta "" Ta "Number of windows in session" .It Li "session_windows" Ta "" Ta "Number of windows in session"
.It Li "socket_path" Ta "" Ta "Server socket path" .It Li "socket_path" Ta "" Ta "Server socket path"

1
tmux.h
View File

@ -2304,6 +2304,7 @@ char *paste_make_sample(struct paste_buffer *);
#define FORMAT_FORCE 0x2 #define FORMAT_FORCE 0x2
#define FORMAT_NOJOBS 0x4 #define FORMAT_NOJOBS 0x4
#define FORMAT_VERBOSE 0x8 #define FORMAT_VERBOSE 0x8
#define FORMAT_LAST 0x10
#define FORMAT_NONE 0 #define FORMAT_NONE 0
#define FORMAT_PANE 0x80000000U #define FORMAT_PANE 0x80000000U
#define FORMAT_WINDOW 0x40000000U #define FORMAT_WINDOW 0x40000000U