On Mon, Feb 21, 2011 at 07:25:32PM -0800, Felix Rosencrantz wrote:
> > What would be really nice would be a way to represent their output in a
> > general internal form that could be output nicely, eg we translate a
> > window into a list of key,value pairs such as:
> >
> > [index=7, name=abc, width=159, height=48, layout=3fdf,159x48,0,0]
> That would work for me.

Please try this against CVS HEAD.

- Only lsp, lsw, ls at the moment.

- Only stuff that was already there so eg no pane_title yet.

- Use -F to specify an alternate format. For example:

        $ ./tmux lsw -F '#{window_index},#{window_name},#{window_active}'
        0,ksh,1
        1,ksh,0
        2,ksh,0

- Ultimately will want similar for choose-*, lsb and so on. Also would
  be nice to use this for status-*, display but that'll need some
  twiddling for backwards compatibility.

Index: Makefile.am
===================================================================
RCS file: /cvsroot/tmux/tmux/Makefile.am,v
retrieving revision 1.10
diff -u -p -r1.10 Makefile.am
--- Makefile.am 14 Feb 2011 20:39:40 -0000      1.10
+++ Makefile.am 28 Mar 2011 22:43:20 -0000
@@ -140,6 +140,7 @@ dist_tmux_SOURCES = \
        cmd.c \
        colour.c \
        environ.c \
+       format.c \
        grid-utf8.c \
        grid-view.c \
        grid.c \
Index: cmd-list-panes.c
===================================================================
RCS file: /cvsroot/tmux/tmux/cmd-list-panes.c,v
retrieving revision 1.7
diff -u -p -r1.7 cmd-list-panes.c
--- cmd-list-panes.c    7 Jan 2011 14:45:34 -0000       1.7
+++ cmd-list-panes.c    28 Mar 2011 22:43:20 -0000
@@ -30,8 +30,8 @@ int   cmd_list_panes_exec(struct cmd *, st
 
 const struct cmd_entry cmd_list_panes_entry = {
        "list-panes", "lsp",
-       "t:", 0, 0,
-       CMD_TARGET_WINDOW_USAGE,
+       "F:t:", 0, 0,
+       "[-F format] " CMD_TARGET_WINDOW_USAGE,
        0,
        NULL,
        NULL,
@@ -44,30 +44,35 @@ cmd_list_panes_exec(struct cmd *self, st
        struct args             *args = self->args;
        struct winlink          *wl;
        struct window_pane      *wp;
-       struct grid             *gd;
-       struct grid_line        *gl;
-       u_int                    i, n;
-       unsigned long long       size;
+       struct session          *s;
+       u_int                    n;
+       struct format_tree      *ft;
+       const char              *template;
+       char                    *line;
 
-       if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
+       if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL)
                return (-1);
 
+       template = args_get(args, 'F');
+       if (template == NULL) {
+               template = "#{line}: [#{pane_width}x#{pane_height}] [history "
+                   "#{history_size}/#{history_limit}, #{history_bytes} bytes]"
+                   "#{?pane_active, (active),}#{?pane_dead, (dead),}";
+       }
+
        n = 0;
        TAILQ_FOREACH(wp, &wl->window->panes, entry) {
-               gd = wp->base.grid;
+               ft = format_create();
+               format_add(ft, "line", "%u", n);
+               format_session(ft, s);
+               format_winlink(ft, s, wl);
+               format_window_pane(ft, wp);
+
+               line = format_expand(ft, template);
+               ctx->print(ctx, "%s", line);
+               xfree(line);
 
-               size = 0;
-               for (i = 0; i < gd->hsize; i++) {
-                       gl = &gd->linedata[i];
-                       size += gl->cellsize * sizeof *gl->celldata;
-                       size += gl->utf8size * sizeof *gl->utf8data;
-               }
-               size += gd->hsize * sizeof *gd->linedata;
-
-               ctx->print(ctx, "%u: [%ux%u] [history %u/%u, %llu bytes]%s%s",
-                   n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size,
-                   wp == wp->window->active ? " (active)" : "",
-                   wp->fd == -1 ? " (dead)" : "");
+               format_free(ft);
                n++;
        }
 
Index: cmd-list-sessions.c
===================================================================
RCS file: /cvsroot/tmux/tmux/cmd-list-sessions.c,v
retrieving revision 1.27
diff -u -p -r1.27 cmd-list-sessions.c
--- cmd-list-sessions.c 7 Jan 2011 14:45:34 -0000       1.27
+++ cmd-list-sessions.c 28 Mar 2011 22:43:20 -0000
@@ -31,40 +31,45 @@ int cmd_list_sessions_exec(struct cmd *,
 
 const struct cmd_entry cmd_list_sessions_entry = {
        "list-sessions", "ls",
-       "", 0, 0,
-       "",
+       "F:", 0, 0,
+       "[-F format]",
        0,
        NULL,
        NULL,
        cmd_list_sessions_exec
 };
 
-/* ARGSUSED */
 int
-cmd_list_sessions_exec(unused struct cmd *self, struct cmd_ctx *ctx)
+cmd_list_sessions_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
+       struct args             *args = self->args;
        struct session          *s;
-       struct session_group    *sg;
-       char                    *tim, tmp[64];
-       u_int                    idx;
-       time_t                   t;
+       u_int                    n;
+       struct format_tree      *ft;
+       const char              *template;
+       char                    *line;
 
+       template = args_get(args, 'F');
+       if (template == NULL) {
+               template = "#{session_name}: #{session_windows} windows "
+                   "(created #{session_created_string}) [#{session_width}x"
+                   "#{session_height}]#{?session_grouped, (group ,}"
+                   "#{session_group}#{?session_grouped,),}"
+                   "#{?session_attached, (attached),}";
+       }
+
+       n = 0;
        RB_FOREACH(s, sessions, &sessions) {
-               sg = session_group_find(s);
-               if (sg == NULL)
-                       *tmp = '\0';
-               else {
-                       idx = session_group_index(sg);
-                       xsnprintf(tmp, sizeof tmp, " (group %u)", idx);
-               }
-
-               t = s->creation_time.tv_sec;
-               tim = ctime(&t);
-               *strchr(tim, '\n') = '\0';
-
-               ctx->print(ctx, "%s: %u windows (created %s) [%ux%u]%s%s",
-                   s->name, winlink_count(&s->windows), tim, s->sx, s->sy,
-                   tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)");
+               ft = format_create();
+               format_add(ft, "line", "%u", n);
+               format_session(ft, s);
+
+               line = format_expand(ft, template);
+               ctx->print(ctx, "%s", line);
+               xfree(line);
+
+               format_free(ft);
+               n++;
        }
 
        return (0);
Index: cmd-list-windows.c
===================================================================
RCS file: /cvsroot/tmux/tmux/cmd-list-windows.c,v
retrieving revision 1.45
diff -u -p -r1.45 cmd-list-windows.c
--- cmd-list-windows.c  7 Jan 2011 14:45:34 -0000       1.45
+++ cmd-list-windows.c  28 Mar 2011 22:43:20 -0000
@@ -30,8 +30,8 @@ int   cmd_list_windows_exec(struct cmd *, 
 
 const struct cmd_entry cmd_list_windows_entry = {
        "list-windows", "lsw",
-       "t:", 0, 0,
-       CMD_TARGET_SESSION_USAGE,
+       "F:t:", 0, 0,
+       "[-F format] " CMD_TARGET_SESSION_USAGE,
        0,
        NULL,
        NULL,
@@ -41,20 +41,37 @@ const struct cmd_entry cmd_list_windows_
 int
 cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
 {
-       struct args     *args = self->args;
-       struct session  *s;
-       struct winlink  *wl;
-       char            *layout;
+       struct args             *args = self->args;
+       struct session          *s;
+       struct winlink          *wl;
+       u_int                    n;
+       struct format_tree      *ft;
+       const char              *template;
+       char                    *line;
 
        if ((s = cmd_find_session(ctx, args_get(args, 't'))) == NULL)
                return (-1);
 
+       template = args_get(args, 'F');
+       if (template == NULL) {
+               template = "#{window_index}: #{window_name} "
+                   "[#{window_width}x#{window_height}] "
+                   "[layout #{window_layout}]#{?window_active, (active),}";
+       }
+
+       n = 0;
        RB_FOREACH(wl, winlinks, &s->windows) {
-               layout = layout_dump(wl->window);
-               ctx->print(ctx, "%d: %s [%ux%u] [layout %s]%s",
-                   wl->idx, wl->window->name, wl->window->sx, wl->window->sy,
-                   layout, wl == s->curw ? " (active)" : "");
-               xfree(layout);
+               ft = format_create();
+               format_add(ft, "line", "%u", n);
+               format_session(ft, s);
+               format_winlink(ft, s, wl);
+
+               line = format_expand(ft, template);
+               ctx->print(ctx, "%s", line);
+               xfree(line);
+
+               format_free(ft);
+               n++;
        }
 
        return (0);
Index: format.c
===================================================================
RCS file: format.c
diff -N format.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ format.c    28 Mar 2011 22:43:21 -0000
@@ -0,0 +1,277 @@
+/* $Id: tmux.h,v 1.612 2011/03/19 23:30:37 tcunha Exp $ */
+
+/*
+ * Copyright (c) 2011 Nicholas Marriott <n...@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <string.h>
+
+#include "tmux.h"
+
+/*
+ * Code to build a list of key-value pairs and use them to expand #{key}
+ * entries in a string.
+ */
+
+int    format_replace(struct format_tree *,
+           const char *, size_t, char **, size_t *, size_t *);
+
+/* Format replacement entry. */
+RB_GENERATE(format_tree, format_entry, entry, format_cmp);
+
+/* Format tree comparison function. */
+int
+format_cmp(struct format_entry *fe1, struct format_entry *fe2)
+{
+       return (strcmp(fe1->key, fe2->key));
+}
+
+/* Create a new tree. */
+struct format_tree *
+format_create(void)
+{
+       struct format_tree      *ft;
+
+       ft = xmalloc(sizeof *ft);
+       RB_INIT(ft);
+
+       return (ft);
+}
+
+/* Free a tree. */
+void
+format_free(struct format_tree *ft)
+{
+       struct format_entry     *fe, *fe_next;
+
+       fe_next = RB_MIN(format_tree, ft);
+       while (fe_next != NULL) {
+               fe = fe_next;
+               fe_next = RB_NEXT(format_tree, ft, fe);
+
+               RB_REMOVE(format_tree, ft, fe);
+               xfree(fe->value);
+               xfree(fe->key);
+               xfree(fe);
+       }
+}
+
+/* Add a key-value pair. */
+void
+format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
+{
+       struct format_entry     *fe;
+       va_list                  ap;
+
+       fe = xmalloc(sizeof *fe);
+       fe->key = xstrdup(key);
+
+       va_start(ap, fmt);
+       xvasprintf(&fe->value, fmt, ap);
+       va_end(ap);
+
+       RB_INSERT(format_tree, ft, fe);
+}
+
+/* Find a format entry. */
+const char *
+format_find(struct format_tree *ft, const char *key)
+{
+       struct format_entry     *fe, fe_find;
+
+       fe_find.key = (char *) key;
+       fe = RB_FIND(format_tree, ft, &fe_find);
+       if (fe == NULL)
+               return (NULL);
+       return (fe->value);
+}
+
+/*
+ * Replace a key/value pair in buffer. #{blah} is expanded directly,
+ * #{?blah,a,b} is replace with a if blah exists else b.
+ */
+int
+format_replace(struct format_tree *ft,
+    const char *key, size_t keylen, char **buf, size_t *len, size_t *off)
+{
+       char            *copy, *ptr;
+       const char      *value;
+       size_t           valuelen;
+
+       /* Make a copy of the key. */
+       copy = xmalloc(keylen + 1);
+       memcpy(copy, key, keylen);
+       copy[keylen] = '\0';
+
+       /*
+        * Is this a conditional? If so, check it exists and extract either the
+        * first or second element. If not, look up the key directly.
+        */
+       if (*copy == '?') {
+               ptr = strchr(copy, ',');
+               if (ptr == NULL)
+                       goto fail;
+               *ptr = '\0';
+
+               value = format_find(ft, copy + 1);
+               if (value != NULL && (value[0] != '0' || value[1] != '\0')) {
+                       value = ptr + 1;
+                       ptr = strchr(value, ',');
+                       if (ptr == NULL)
+                               goto fail;
+                       *ptr = '\0';
+               } else {
+                       ptr = strchr(ptr + 1, ',');
+                       if (ptr == NULL)
+                               goto fail;
+                       value = ptr + 1;
+               }
+       } else {
+               value = format_find(ft, copy);
+               if (value == NULL)
+                       value = "";
+       }
+       valuelen = strlen(value);
+
+       /* Expand the buffer and copy in the value. */
+       while (*len - *off < valuelen + 1) {
+               *buf = xrealloc(*buf, 2, *len);
+               *len *= 2;
+       }
+       memcpy(*buf + *off, value, valuelen);
+       *off += valuelen;
+
+       xfree(copy);
+       return (0);
+
+fail:
+       xfree(copy);
+       return (1);
+}
+
+/* Expand keys in a template. */
+char *
+format_expand(struct format_tree *ft, const char *fmt)
+{
+       char    *buf, *ptr;
+       size_t   off, len, n;
+
+       len = 64;
+       buf = xmalloc(len);
+       off = 0;
+
+       while (*fmt != '\0') {
+               if (fmt[0] == '#' && fmt[1] == '{') {
+                       fmt += 2;
+
+                       ptr = strchr(fmt, '}');
+                       if (ptr == NULL)
+                               break;
+                       n = ptr - fmt;
+
+                       if (format_replace(ft, fmt, n, &buf, &len, &off) != 0)
+                               break;
+                       fmt += n + 1;
+                       continue;
+               }
+
+               while (len - off < 2) {
+                       buf = xrealloc(buf, 2, len);
+                       len *= 2;
+               }
+               buf[off++] = *fmt++;
+       }
+       buf[off] = '\0';
+
+       return (buf);
+}
+
+/* Set default format keys for a session. */
+void
+format_session(struct format_tree *ft, struct session *s)
+{
+       struct session_group    *sg;
+       char                    *tim;
+       time_t                   t;
+
+       format_add(ft, "session_name", "%s", s->name);
+       format_add(ft, "session_windows", "%u", winlink_count(&s->windows));
+       format_add(ft, "session_width", "%u", s->sx);
+       format_add(ft, "session_height", "%u", s->sy);
+
+       sg = session_group_find(s);
+       format_add(ft, "session_grouped", "%d", sg != NULL);
+       if (sg != NULL)
+               format_add(ft, "session_group", "%u", session_group_index(sg));
+
+       t = s->creation_time.tv_sec;
+       format_add(ft, "session_created", "%ld", (long) t);
+       tim = ctime(&t);
+       *strchr(tim, '\n') = '\0';
+       format_add(ft, "session_created_string", "%s", tim);
+
+       if (s->flags & SESSION_UNATTACHED)
+               format_add(ft, "session_attached", "%d", 0);
+       else
+               format_add(ft, "session_attached", "%d", 1);
+}
+
+/* Set default format keys for a winlink. */
+void
+format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl)
+{
+       struct window   *w = wl->window;
+       char            *layout;
+
+       layout = layout_dump(w);
+
+       format_add(ft, "window_index", "%d", wl->idx);
+       format_add(ft, "window_name", "%s", w->name);
+       format_add(ft, "window_width", "%u", w->sx);
+       format_add(ft, "window_height", "%u", w->sy);
+       format_add(ft, "window_layout", "%s", layout);
+       format_add(ft, "window_active", "%d", wl == s->curw);
+
+       xfree(layout);
+}
+
+/* Set default format keys for a window pane. */
+void
+format_window_pane(struct format_tree *ft, struct window_pane *wp)
+{
+       struct grid             *gd = wp->base.grid;
+       struct grid_line        *gl;
+       unsigned long long       size;
+       u_int                    i;
+
+       size = 0;
+       for (i = 0; i < gd->hsize; i++) {
+               gl = &gd->linedata[i];
+               size += gl->cellsize * sizeof *gl->celldata;
+               size += gl->utf8size * sizeof *gl->utf8data;
+       }
+       size += gd->hsize * sizeof *gd->linedata;
+
+       format_add(ft, "pane_width", "%u", wp->sx);
+       format_add(ft, "pane_height", "%u", wp->sy);
+       format_add(ft, "history_size", "%u", gd->hsize);
+       format_add(ft, "history_limit", "%u", gd->hlimit);
+       format_add(ft, "history_bytes", "%llu", size);
+       format_add(ft, "pane_active", "%d", wp == wp->window->active);
+       format_add(ft, "pane_dead", "%d", wp->fd == -1);
+}
Index: tmux.h
===================================================================
RCS file: /cvsroot/tmux/tmux/tmux.h,v
retrieving revision 1.612
diff -u -p -r1.612 tmux.h
--- tmux.h      19 Mar 2011 23:30:37 -0000      1.612
+++ tmux.h      28 Mar 2011 22:43:21 -0000
@@ -1273,6 +1273,15 @@ struct options_table_entry {
        long long               default_num;
 };
 
+/* Tree of format entries. */
+struct format_entry {
+       char                   *key;
+       char                   *value;
+
+       RB_ENTRY(format_entry)  entry;
+};
+RB_HEAD(format_tree, format_entry);
+
 /* List of configuration causes. */
 ARRAY_DECL(causelist, char *);
 
@@ -1315,6 +1324,20 @@ extern struct causelist cfg_causes;
 void printflike2 cfg_add_cause(struct causelist *, const char *, ...);
 int             load_cfg(const char *, struct cmd_ctx *, struct causelist *);
 
+/* format.c */
+int             format_cmp(struct format_entry *, struct format_entry *);
+RB_PROTOTYPE(format_tree, format_entry, entry, format_cmp);
+struct format_tree *format_create(void);
+void            format_free(struct format_tree *);
+void            format_add(
+                    struct format_tree *, const char *, const char *, ...);
+const char     *format_find(struct format_tree *, const char *);
+char           *format_expand(struct format_tree *, const char *);
+void            format_session(struct format_tree *, struct session *);
+void            format_winlink(
+                    struct format_tree *, struct session *, struct winlink *);
+void            format_window_pane(struct format_tree *, struct window_pane *);
+
 /* mode-key.c */
 extern const struct mode_key_table mode_key_tables[];
 extern struct mode_key_tree mode_key_tree_vi_edit;

------------------------------------------------------------------------------
Create and publish websites with WebMatrix
Use the most popular FREE web apps or write code yourself; 
WebMatrix provides all the features you need to develop and publish 
your website. http://p.sf.net/sfu/ms-webmatrix-sf
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to