Extend the modifiers allowed before formats: as well as the existing
authornicm <nicm@openbsd.org>
Sun, 25 Oct 2015 22:29:17 +0000 (22:29 +0000)
committernicm <nicm@openbsd.org>
Sun, 25 Oct 2015 22:29:17 +0000 (22:29 +0000)
#{=10:...}  length limit, add #{t:...} to convert a time_t format to a
string, #{b:...} for basename and #{d:...} for dirname. Remove all the
foo_string time formats as they can now be replaced by "t:", for example
#{window_activity_string} becomes #{t:window_activity}.

usr.bin/tmux/cmd-choose-client.c
usr.bin/tmux/cmd-list-sessions.c
usr.bin/tmux/format.c
usr.bin/tmux/tmux.1
usr.bin/tmux/tmux.h

index e118117..b184b50 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-choose-client.c,v 1.24 2015/04/27 16:25:57 nicm Exp $ */
+/* $OpenBSD: cmd-choose-client.c,v 1.25 2015/10/25 22:29:17 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,7 +31,7 @@
        "#{client_tty}: #{session_name} "                       \
        "[#{client_width}x#{client_height} #{client_termname}]" \
        "#{?client_utf8, (utf8),}#{?client_readonly, (ro),} "   \
-       "(last used #{client_activity_string})"
+       "(last used #{t:client_activity})"
 
 enum cmd_retval         cmd_choose_client_exec(struct cmd *, struct cmd_q *);
 
index 64d3361..32ef986 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-list-sessions.c,v 1.19 2015/02/05 10:29:43 nicm Exp $ */
+/* $OpenBSD: cmd-list-sessions.c,v 1.20 2015/10/25 22:29:17 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,7 +30,7 @@
 
 #define LIST_SESSIONS_TEMPLATE                         \
        "#{session_name}: #{session_windows} windows "  \
-       "(created #{session_created_string}) "          \
+       "(created #{t:session_created}) "               \
        "[#{session_width}x#{session_height}]"          \
        "#{?session_grouped, (group ,}"                 \
        "#{session_group}#{?session_grouped,),}"        \
index cea81da..2a65422 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: format.c,v 1.86 2015/10/25 08:59:26 nicm Exp $ */
+/* $OpenBSD: format.c,v 1.87 2015/10/25 22:29:17 nicm Exp $ */
 
 /*
  * Copyright (c) 2011 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -21,6 +21,7 @@
 
 #include <ctype.h>
 #include <errno.h>
+#include <libgen.h>
 #include <netdb.h>
 #include <stdarg.h>
 #include <stdlib.h>
@@ -52,7 +53,9 @@ void   format_cb_current_command(struct format_tree *, struct format_entry *);
 void    format_cb_history_bytes(struct format_tree *, struct format_entry *);
 void    format_cb_pane_tabs(struct format_tree *, struct format_entry *);
 
+char   *format_find(struct format_tree *, const char *, int);
 void    format_add_cb(struct format_tree *, const char *, format_cb);
+void    format_add_tv(struct format_tree *, const char *, struct timeval *);
 int     format_replace(struct format_tree *, const char *, size_t, char **,
             size_t *, size_t *);
 char   *format_time_string(time_t);
@@ -90,10 +93,16 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
        return (strcmp(fj1->cmd, fj2->cmd));
 }
 
+/* Format modifiers. */
+#define FORMAT_TIMESTRING 0x1
+#define FORMAT_BASENAME 0x2
+#define FORMAT_DIRNAME 0x4
+
 /* Entry in format tree. */
 struct format_entry {
        char                    *key;
        char                    *value;
+       time_t                   t;
        format_cb                cb;
        RB_ENTRY(format_entry)   entry;
 };
@@ -503,12 +512,37 @@ format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
        }
 
        fe->cb = NULL;
+       fe->t = 0;
 
        va_start(ap, fmt);
        xvasprintf(&fe->value, fmt, ap);
        va_end(ap);
 }
 
+/* Add a key and time. */
+void
+format_add_tv(struct format_tree *ft, const char *key, struct timeval *tv)
+{
+       struct format_entry     *fe;
+       struct format_entry     *fe_now;
+
+       fe = xmalloc(sizeof *fe);
+       fe->key = xstrdup(key);
+
+       fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
+       if (fe_now != NULL) {
+               free(fe->key);
+               free(fe);
+               free(fe_now->value);
+               fe = fe_now;
+       }
+
+       fe->cb = NULL;
+       fe->t = tv->tv_sec;
+
+       fe->value = NULL;
+}
+
 /* Add a key and function. */
 void
 format_add_cb(struct format_tree *ft, const char *key, format_cb cb)
@@ -528,57 +562,99 @@ format_add_cb(struct format_tree *ft, const char *key, format_cb cb)
        }
 
        fe->cb = cb;
+       fe->t = 0;
 
        fe->value = NULL;
 }
 
 /* Find a format entry. */
-const char *
-format_find(struct format_tree *ft, const char *key)
+char *
+format_find(struct format_tree *ft, const char *key, int modifiers)
 {
        struct format_entry     *fe, fe_find;
        struct options_entry    *o;
        struct environ_entry    *envent;
-       static char              s[16];
-
-       o = options_find(&global_options, key);
-       if (o == NULL && ft->w != NULL)
-               o = options_find(&ft->w->options, key);
-       if (o == NULL)
-               o = options_find(&global_w_options, key);
-       if (o == NULL && ft->s != NULL)
-               o = options_find(&ft->s->options, key);
-       if (o == NULL)
-               o = options_find(&global_s_options, key);
-       if (o != NULL) {
-               switch (o->type) {
-               case OPTIONS_STRING:
-                       return (o->str);
-               case OPTIONS_NUMBER:
-                       xsnprintf(s, sizeof s, "%lld", o->num);
-                       return (s);
-               case OPTIONS_STYLE:
-                       return (style_tostring(&o->style));
+       static char              s[64];
+       const char              *found;
+       char                    *copy, *saved;
+
+       found = NULL;
+
+       if (~modifiers & FORMAT_TIMESTRING) {
+               o = options_find(&global_options, key);
+               if (o == NULL && ft->w != NULL)
+                       o = options_find(&ft->w->options, key);
+               if (o == NULL)
+                       o = options_find(&global_w_options, key);
+               if (o == NULL && ft->s != NULL)
+                       o = options_find(&ft->s->options, key);
+               if (o == NULL)
+                       o = options_find(&global_s_options, key);
+               if (o != NULL) {
+                       switch (o->type) {
+                       case OPTIONS_STRING:
+                               found = o->str;
+                               goto found;
+                       case OPTIONS_NUMBER:
+                               xsnprintf(s, sizeof s, "%lld", o->num);
+                               found = s;
+                               goto found;
+                       case OPTIONS_STYLE:
+                               found = style_tostring(&o->style);
+                               goto found;
+                       }
                }
        }
 
        fe_find.key = (char *) key;
        fe = RB_FIND(format_entry_tree, &ft->tree, &fe_find);
        if (fe != NULL) {
+               if (modifiers & FORMAT_TIMESTRING) {
+                       if (fe->t == 0)
+                               return (NULL);
+                       ctime_r(&fe->t, s);
+                       s[strcspn(s, "\n")] = '\0';
+                       found = s;
+                       goto found;
+               }
+               if (fe->t != 0) {
+                       xsnprintf(s, sizeof s, "%lld", (long long)fe->t);
+                       found = s;
+                       goto found;
+               }
                if (fe->value == NULL && fe->cb != NULL)
                        fe->cb(ft, fe);
-               return (fe->value);
+               found = fe->value;
+               goto found;
        }
 
-       envent = NULL;
-       if (ft->s != NULL)
-               envent = environ_find(&ft->s->environ, key);
-       if (envent == NULL)
-               envent = environ_find(&global_environ, key);
-       if (envent != NULL)
-               return (envent->value);
+       if (~modifiers & FORMAT_TIMESTRING) {
+               envent = NULL;
+               if (ft->s != NULL)
+                       envent = environ_find(&ft->s->environ, key);
+               if (envent == NULL)
+                       envent = environ_find(&global_environ, key);
+               if (envent != NULL) {
+                       found = envent->value;
+                       goto found;
+               }
+       }
 
        return (NULL);
+
+found:
+       copy = xstrdup(found);
+       if (modifiers & FORMAT_BASENAME) {
+               saved = copy;
+               copy = xstrdup(basename(saved));
+               free(saved);
+       }
+       if (modifiers & FORMAT_DIRNAME) {
+               saved = copy;
+               copy = xstrdup(dirname(saved));
+               free(saved);
+       }
+       return (copy);
 }
 
 /*
@@ -589,10 +665,10 @@ int
 format_replace(struct format_tree *ft, const char *key, size_t keylen,
     char **buf, size_t *len, size_t *off)
 {
-       char            *copy, *copy0, *endptr, *ptr, *saved, *trimmed;
-       const char      *value;
+       char            *copy, *copy0, *endptr, *ptr, *saved, *trimmed, *value;
        size_t           valuelen;
        u_long           limit = 0;
+       int              modifiers = 0;
 
        /* Make a copy of the key. */
        copy0 = copy = xmalloc(keylen + 1);
@@ -600,24 +676,34 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
        copy[keylen] = '\0';
 
        /* Is there a length limit or whatnot? */
-       if (!isalpha((u_char) *copy) && *copy != '@' && *copy != '?') {
-               while (*copy != ':' && *copy != '\0') {
-                       switch (*copy) {
-                       case '=':
-                               errno = 0;
-                               limit = strtoul(copy + 1, &endptr, 10);
-                               if (errno == ERANGE && limit == ULONG_MAX)
-                                       goto fail;
-                               copy = endptr;
-                               break;
-                       default:
-                               copy++;
-                               break;
-                       }
-               }
-               if (*copy != ':')
-                       goto fail;
-               copy++;
+       switch (copy[0]) {
+       case '=':
+               errno = 0;
+               limit = strtoul(copy + 1, &endptr, 10);
+               if (errno == ERANGE && limit == ULONG_MAX)
+                       break;
+               if (*endptr != ':')
+                       break;
+               copy = endptr + 1;
+               break;
+       case 'b':
+               if (copy[1] != ':')
+                       break;
+               modifiers |= FORMAT_BASENAME;
+               copy += 2;
+               break;
+       case 'd':
+               if (copy[1] != ':')
+                       break;
+               modifiers |= FORMAT_DIRNAME;
+               copy += 2;
+               break;
+       case 't':
+               if (copy[1] != ':')
+                       break;
+               modifiers |= FORMAT_TIMESTRING;
+               copy += 2;
+               break;
        }
 
        /*
@@ -630,7 +716,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
                        goto fail;
                *ptr = '\0';
 
-               value = format_find(ft, copy + 1);
+               value = saved = format_find(ft, copy + 1, modifiers);
                if (value != NULL && *value != '\0' &&
                    (value[0] != '0' || value[1] != '\0')) {
                        value = ptr + 1;
@@ -644,13 +730,13 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
                                goto fail;
                        value = ptr + 1;
                }
-               saved = format_expand(ft, value);
-               value = saved;
+               value = format_expand(ft, value);
+               free(saved);
+               saved = value;
        } else {
-               value = format_find(ft, copy);
+               saved = value = format_find(ft, copy, modifiers);
                if (value == NULL)
-                       value = "";
-               saved = NULL;
+                       saved = value = xstrdup("");
        }
 
        /* Truncate the value if needed. */
@@ -820,18 +906,6 @@ format_expand(struct format_tree *ft, const char *fmt)
        return (buf);
 }
 
-/* Get time as a string. */
-char *
-format_time_string(time_t t)
-{
-       char    *tim;
-
-       tim = ctime(&t);
-       *strchr(tim, '\n') = '\0';
-
-       return (tim);
-}
-
 /* Set defaults for any of arguments that are not NULL. */
 void
 format_defaults(struct format_tree *ft, struct client *c, struct session *s,
@@ -859,7 +933,6 @@ void
 format_defaults_session(struct format_tree *ft, struct session *s)
 {
        struct session_group    *sg;
-       time_t                   t;
 
        ft->s = s;
 
@@ -874,20 +947,9 @@ format_defaults_session(struct format_tree *ft, struct session *s)
        if (sg != NULL)
                format_add(ft, "session_group", "%u", session_group_index(sg));
 
-       t = s->creation_time.tv_sec;
-       format_add(ft, "session_created", "%lld", (long long) t);
-       format_add(ft, "session_created_string", "%s", format_time_string(t));
-
-       t = s->last_attached_time.tv_sec;
-       if (t != 0) { /* zero if never attached */
-               format_add(ft, "session_last_attached", "%lld", (long long) t);
-               format_add(ft, "session_last_attached_string", "%s",
-                   format_time_string(t));
-       }
-
-       t = s->activity_time.tv_sec;
-       format_add(ft, "session_activity", "%lld", (long long) t);
-       format_add(ft, "session_activity_string", "%s", format_time_string(t));
+       format_add_tv(ft, "session_created", &s->creation_time);
+       format_add_tv(ft, "session_last_attached", &s->last_attached_time);
+       format_add_tv(ft, "session_activity", &s->activity_time);
 
        format_add(ft, "session_attached", "%u", s->attached);
        format_add(ft, "session_many_attached", "%d", s->attached > 1);
@@ -900,7 +962,6 @@ void
 format_defaults_client(struct format_tree *ft, struct client *c)
 {
        struct session  *s;
-       time_t           t;
 
        if (ft->s == NULL)
                ft->s = c->session;
@@ -915,13 +976,8 @@ format_defaults_client(struct format_tree *ft, struct client *c)
        format_add(ft, "client_control_mode", "%d",
                !!(c->flags & CLIENT_CONTROL));
 
-       t = c->creation_time.tv_sec;
-       format_add(ft, "client_created", "%lld", (long long) t);
-       format_add(ft, "client_created_string", "%s", format_time_string(t));
-
-       t = c->activity_time.tv_sec;
-       format_add(ft, "client_activity", "%lld", (long long) t);
-       format_add(ft, "client_activity_string", "%s", format_time_string(t));
+       format_add_tv(ft, "client_created", &c->creation_time);
+       format_add_tv(ft, "client_activity", &c->activity_time);
 
        if (strcmp(c->keytable->name, "root") == 0)
                format_add(ft, "client_prefix", "%d", 0);
@@ -951,14 +1007,9 @@ format_defaults_client(struct format_tree *ft, struct client *c)
 void
 format_defaults_window(struct format_tree *ft, struct window *w)
 {
-       time_t   t;
-
        ft->w = w;
 
-       t = w->activity_time.tv_sec;
-       format_add(ft, "window_activity", "%lld", (long long) t);
-       format_add(ft, "window_activity_string", "%s", format_time_string(t));
-
+       format_add_tv(ft, "window_activity", &w->activity_time);
        format_add(ft, "window_id", "@%u", w->id);
        format_add(ft, "window_name", "%s", w->name);
        format_add(ft, "window_width", "%u", w->sx);
index d2de3b2..ab31d50 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.452 2015/10/23 16:02:21 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.453 2015/10/25 22:29:17 nicm Exp $
 .\"
 .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 .\"
@@ -14,7 +14,7 @@
 .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: October 23 2015 $
+.Dd $Mdocdate: October 25 2015 $
 .Dt TMUX 1
 .Os
 .Sh NAME
@@ -3319,12 +3319,31 @@ if
 is enabled, or
 .Ql no
 if not.
+.Pp
 A limit may be placed on the length of the resultant string by prefixing it
 by an
 .Ql = ,
 a number and a colon, so
 .Ql #{=10:pane_title}
 will include at most the first 10 characters of the pane title.
+Prefixing a time variable with
+.Ql t:
+will convert it to a string, so if
+.Ql #{window_activity}
+gives
+.Ql 1445765102,
+.Ql #{t:window_activity}
+gives
+.Ql Sun Oct 25 09:25:02 2015 .
+The
+.Ql b:
+and
+.Ql d:
+prefixes are
+.Xr basename 3
+and
+.Xr dirname 3
+of the variable respectively.
 .Pp
 In addition, the first line of a shell command's output may be inserted using
 .Ql #() .
@@ -3352,9 +3371,7 @@ The following variables are available, where appropriate:
 .It Li "buffer_sample" Ta "" Ta "Sample of start of buffer"
 .It Li "buffer_size" Ta "" Ta "Size of the specified buffer in bytes"
 .It Li "client_activity" Ta "" Ta "Integer time client last had activity"
-.It Li "client_activity_string" Ta "" Ta "String time client last had activity"
 .It Li "client_created" Ta "" Ta "Integer time client created"
-.It Li "client_created_string" Ta "" Ta "String time client created"
 .It Li "client_control_mode" Ta "" Ta "1 if client is in control mode"
 .It Li "client_height" Ta "" Ta "Height of client"
 .It Li "client_key_table" Ta "" Ta "Current key table"
@@ -3410,11 +3427,8 @@ The following variables are available, where appropriate:
 .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_activity" Ta "" Ta "Integer time of session last activity"
-.It Li "session_activity_string" Ta "" Ta "String time of session last activity"
 .It Li "session_created" Ta "" Ta "Integer time session created"
-.It Li "session_created_string" Ta "" Ta "String time session created"
 .It Li "session_last_attached" Ta "" Ta "Integer time session last attached"
-.It Li "session_last_attached_string" Ta "" Ta "String time session last attached"
 .It Li "session_group" Ta "" Ta "Number of session group"
 .It Li "session_grouped" Ta "" Ta "1 if session in a group"
 .It Li "session_height" Ta "" Ta "Height of session"
@@ -3424,9 +3438,7 @@ The following variables are available, where appropriate:
 .It Li "session_width" Ta "" Ta "Width of session"
 .It Li "session_windows" Ta "" Ta "Number of windows in session"
 .It Li "window_activity" Ta "" Ta "Integer time of window last activity"
-.It Li "window_activity_string" Ta "" Ta "String time of window last activity"
 .It Li "window_active" Ta "" Ta "1 if window active"
-.It Li "window_activity_flag" Ta "" Ta "1 if window has activity alert"
 .It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
 .It Li "window_find_matches" Ta "" Ta "Matched data from the find-window"
 .It Li "window_flags" Ta "#F" Ta "Window flags"
index 10addf6..fd50033 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.564 2015/10/23 16:02:21 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.565 2015/10/25 22:29:17 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -1453,7 +1453,6 @@ struct format_tree *format_create_flags(int);
 void            format_free(struct format_tree *);
 void printflike(3, 4) format_add(struct format_tree *, const char *,
                     const char *, ...);
-const char     *format_find(struct format_tree *, const char *);
 char           *format_expand_time(struct format_tree *, const char *, time_t);
 char           *format_expand(struct format_tree *, const char *);
 void            format_defaults(struct format_tree *, struct client *,