summaryrefslogtreecommitdiff
path: root/usr.bin/tmux
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2019-03-13 15:37:29 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2019-03-13 15:37:29 +0000
commit857b442d2b84fe7a15c05415eb0aa89af3fedfd0 (patch)
treeff5ccaf91b82ecf8c4cb6891976e708af0a74caa /usr.bin/tmux
parentc9b054f1c5d1477a93ac2a02c6e32c557a9364a7 (diff)
Add formats to list sessions, windows or panes.
Diffstat (limited to 'usr.bin/tmux')
-rw-r--r--usr.bin/tmux/format.c140
-rw-r--r--usr.bin/tmux/tmux.113
2 files changed, 148 insertions, 5 deletions
diff --git a/usr.bin/tmux/format.c b/usr.bin/tmux/format.c
index e3ef8d061e4..38887f4c797 100644
--- a/usr.bin/tmux/format.c
+++ b/usr.bin/tmux/format.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: format.c,v 1.171 2019/03/13 14:27:17 nicm Exp $ */
+/* $OpenBSD: format.c,v 1.172 2019/03/13 15:37:28 nicm Exp $ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -95,6 +95,9 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
#define FORMAT_QUOTE 0x8
#define FORMAT_LITERAL 0x10
#define FORMAT_EXPAND 0x20
+#define FORMAT_SESSIONS 0x40
+#define FORMAT_WINDOWS 0x80
+#define FORMAT_PANES 0x100
/* Entry in format tree. */
struct format_entry {
@@ -113,6 +116,7 @@ struct format_tree {
struct window *w;
struct window_pane *wp;
+ struct cmdq_item *item;
struct client *client;
u_int tag;
int flags;
@@ -673,6 +677,7 @@ format_create(struct client *c, struct cmdq_item *item, int tag, int flags)
ft->client = c;
ft->client->references++;
}
+ ft->item = item;
ft->tag = tag;
ft->flags = flags;
@@ -1013,7 +1018,8 @@ format_build_modifiers(struct format_tree *ft, const char **s, u_int *count)
cp++;
/* Check single character modifiers with no arguments. */
- if (strchr("lmCbdtqE", cp[0]) != NULL && format_is_end(cp[1])) {
+ if (strchr("lmCbdtqESWP", cp[0]) != NULL &&
+ format_is_end(cp[1])) {
format_add_modifier(&list, count, cp, 1, NULL, 0);
cp++;
continue;
@@ -1127,6 +1133,111 @@ format_substitute(const char *source, const char *from, const char *to)
return (copy);
}
+/* Loop over sessions. */
+static char *
+format_loop_sessions(struct format_tree *ft, const char *fmt)
+{
+ struct cmdq_item *item = ft->item;
+ char *expanded, *value;
+ size_t valuelen;
+ struct session *s;
+
+ value = xcalloc(1, 1);
+ valuelen = 1;
+
+ RB_FOREACH(s, sessions, &sessions) {
+ expanded = format_single(item, fmt, ft->c, ft->s, NULL, NULL);
+
+ valuelen += strlen(expanded);
+ value = xrealloc(value, valuelen);
+
+ strlcat(value, expanded, valuelen);
+ free(expanded);
+ }
+
+ return (value);
+}
+
+/* Loop over windows. */
+static char *
+format_loop_windows(struct format_tree *ft, const char *fmt)
+{
+ struct cmdq_item *item = ft->item;
+ char *all, *active, *use, *expanded, *value;
+ size_t valuelen;
+ struct winlink *wl;
+
+ if (ft->s == NULL)
+ return (NULL);
+
+ if (format_choose(ft, fmt, &all, &active, 0) != 0) {
+ all = xstrdup(fmt);
+ active = NULL;
+ }
+
+ value = xcalloc(1, 1);
+ valuelen = 1;
+
+ RB_FOREACH(wl, winlinks, &ft->s->windows) {
+ if (active != NULL && wl == ft->s->curw)
+ use = active;
+ else
+ use = all;
+ expanded = format_single(item, use, ft->c, ft->s, wl, NULL);
+
+ valuelen += strlen(expanded);
+ value = xrealloc(value, valuelen);
+
+ strlcat(value, expanded, valuelen);
+ free(expanded);
+ }
+
+ free(active);
+ free(all);
+
+ return (value);
+}
+
+/* Loop over panes. */
+static char *
+format_loop_panes(struct format_tree *ft, const char *fmt)
+{
+ struct cmdq_item *item = ft->item;
+ char *all, *active, *use, *expanded, *value;
+ size_t valuelen;
+ struct window_pane *wp;
+
+ if (ft->w == NULL)
+ return (NULL);
+
+ if (format_choose(ft, fmt, &all, &active, 0) != 0) {
+ all = xstrdup(fmt);
+ active = NULL;
+ }
+
+ value = xcalloc(1, 1);
+ valuelen = 1;
+
+ TAILQ_FOREACH(wp, &ft->w->panes, entry) {
+ if (active != NULL && wp == ft->w->active)
+ use = active;
+ else
+ use = all;
+ expanded = format_single(item, use, ft->c, ft->s, ft->wl, wp);
+
+ valuelen += strlen(expanded);
+ value = xrealloc(value, valuelen);
+
+ strlcat(value, expanded, valuelen);
+ free(expanded);
+ }
+
+ free(active);
+ free(all);
+
+ return (value);
+}
+
/* Replace a key. */
static int
format_replace(struct format_tree *ft, const char *key, size_t keylen,
@@ -1193,6 +1304,15 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
case 'E':
modifiers |= FORMAT_EXPAND;
break;
+ case 'S':
+ modifiers |= FORMAT_SESSIONS;
+ break;
+ case 'W':
+ modifiers |= FORMAT_WINDOWS;
+ break;
+ case 'P':
+ modifiers |= FORMAT_PANES;
+ break;
}
} else if (fm->size == 2) {
if (strcmp(fm->modifier, "||") == 0 ||
@@ -1210,8 +1330,20 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
goto done;
}
- /* Is this a comparison or a conditional? */
- if (search != NULL) {
+ /* Is this a loop, comparison or condition? */
+ if (modifiers & FORMAT_SESSIONS) {
+ value = format_loop_sessions(ft, copy);
+ if (value == NULL)
+ goto fail;
+ } else if (modifiers & FORMAT_WINDOWS) {
+ value = format_loop_windows(ft, copy);
+ if (value == NULL)
+ goto fail;
+ } else if (modifiers & FORMAT_PANES) {
+ value = format_loop_panes(ft, copy);
+ if (value == NULL)
+ goto fail;
+ } else if (search != NULL) {
/* Search in pane. */
if (wp == NULL)
value = xstrdup("0");
diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1
index 80664074e14..d50b6d75ddf 100644
--- a/usr.bin/tmux/tmux.1
+++ b/usr.bin/tmux/tmux.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.617 2019/03/13 14:19:54 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.618 2019/03/13 15:37:28 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\"
@@ -3719,6 +3719,17 @@ will expand the format twice, for example
is the result of expanding the content of the
.Ic status-left
option rather than the content itself.
+.Ql S: ,
+.Ql W:
+or
+.Ql P:
+will loop over each session, window or pane and insert the format once
+for each. For windows and panes, two comma-separated formats may be
+given, the second is used for the current window or active pane. For
+example to get a list of windows formatted like the status line:
+.Bd -literal -offset indent
+#{W:#{E:window-status-format} ,#{E:window-status-current-format} }
+.Ed
A prefix of the form
.Ql s/foo/bar/:
will substitute