From 476f93eb6b340bc7de5a00be978d70acbba88ef2 Mon Sep 17 00:00:00 2001 From: nicm Date: Sun, 25 Oct 2015 22:29:17 +0000 Subject: [PATCH] Extend the modifiers allowed before formats: as well as the existing #{=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 | 4 +- usr.bin/tmux/cmd-list-sessions.c | 4 +- usr.bin/tmux/format.c | 247 +++++++++++++++++++------------ usr.bin/tmux/tmux.1 | 30 ++-- usr.bin/tmux/tmux.h | 3 +- 5 files changed, 175 insertions(+), 113 deletions(-) diff --git a/usr.bin/tmux/cmd-choose-client.c b/usr.bin/tmux/cmd-choose-client.c index e118117ae0f..b184b50f177 100644 --- a/usr.bin/tmux/cmd-choose-client.c +++ b/usr.bin/tmux/cmd-choose-client.c @@ -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 @@ -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 *); diff --git a/usr.bin/tmux/cmd-list-sessions.c b/usr.bin/tmux/cmd-list-sessions.c index 64d3361bcb2..32ef9862bac 100644 --- a/usr.bin/tmux/cmd-list-sessions.c +++ b/usr.bin/tmux/cmd-list-sessions.c @@ -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 @@ -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,),}" \ diff --git a/usr.bin/tmux/format.c b/usr.bin/tmux/format.c index cea81da8a9c..2a65422fea6 100644 --- a/usr.bin/tmux/format.c +++ b/usr.bin/tmux/format.c @@ -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 @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -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); diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index d2de3b266d2..ab31d50b7bb 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -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 .\" @@ -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" diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 10addf6601b..fd50033f969 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -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 @@ -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 *, -- 2.20.1