summaryrefslogtreecommitdiffstats
path: root/format.c
diff options
context:
space:
mode:
authornicm <nicm>2015-08-28 16:46:40 +0000
committernicm <nicm>2015-08-28 16:46:40 +0000
commit983ebb26898beaf66383c5f5aff56cb4c0f80ca4 (patch)
treea8326982e26a8818b2197aecd2bc701fec738eea /format.c
parent55b8d7456155de4e5d44136a140a599e2a2a755b (diff)
Allow formats to be specified as functions (in the code) so they are
only evaluated on demand rather than each time a format tree is constructed. Use this for expensive formats like pane_current_command.
Diffstat (limited to 'format.c')
-rw-r--r--format.c175
1 files changed, 126 insertions, 49 deletions
diff --git a/format.c b/format.c
index 39843674..a885bb85 100644
--- a/format.c
+++ b/format.c
@@ -35,14 +35,23 @@
* string.
*/
+struct format_entry;
+typedef void (*format_cb)(struct format_tree *, struct format_entry *);
+
void format_job_callback(struct job *);
const char *format_job_get(struct format_tree *, const char *);
void format_job_timer(int, short, void *);
+void format_cb_host(struct format_tree *, struct format_entry *);
+void format_cb_host_short(struct format_tree *, struct format_entry *);
+void format_cb_pid(struct format_tree *, struct format_entry *);
+void format_cb_start_command(struct format_tree *, struct format_entry *);
+void format_cb_current_command(struct format_tree *, struct format_entry *);
+
+void format_add_cb(struct format_tree *, const char *, format_cb);
int format_replace(struct format_tree *, const char *, size_t, char **,
size_t *, size_t *);
char *format_time_string(time_t);
-char *format_get_command(struct window_pane *);
void format_defaults_pane_tabs(struct format_tree *, struct window_pane *);
void format_defaults_session(struct format_tree *, struct session *);
@@ -79,18 +88,19 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
/* Entry in format tree. */
struct format_entry {
- char *key;
- char *value;
-
- RB_ENTRY(format_entry) entry;
+ char *key;
+ char *value;
+ format_cb cb;
+ RB_ENTRY(format_entry) entry;
};
/* Format entry tree. */
struct format_tree {
- struct window *w;
- struct session *s;
+ struct window *w;
+ struct session *s;
+ struct window_pane *wp;
- int status;
+ int status;
RB_HEAD(format_entry_tree, format_entry) tree;
};
@@ -257,6 +267,75 @@ format_job_timer(unused int fd, unused short events, unused void *arg)
evtimer_add(&format_job_event, &tv);
}
+/* Callback for host. */
+void
+format_cb_host(unused struct format_tree *ft, struct format_entry *fe)
+{
+ char host[HOST_NAME_MAX + 1];
+
+ if (gethostname(host, sizeof host) != 0)
+ fe->value = xstrdup("");
+ else
+ fe->value = xstrdup(host);
+}
+
+/* Callback for host_short. */
+void
+format_cb_host_short(unused struct format_tree *ft, struct format_entry *fe)
+{
+ char host[HOST_NAME_MAX + 1], *cp;
+
+ if (gethostname(host, sizeof host) != 0)
+ fe->value = xstrdup("");
+ else {
+ if ((cp = strchr(host, '.')) != NULL)
+ *cp = '\0';
+ fe->value = xstrdup(host);
+ }
+}
+
+/* Callback for pid. */
+void
+format_cb_pid(unused struct format_tree *ft, struct format_entry *fe)
+{
+ xasprintf(&fe->value, "%ld", (long)getpid());
+}
+
+/* Callback for pane_start_command. */
+void
+format_cb_start_command(struct format_tree *ft, struct format_entry *fe)
+{
+ struct window_pane *wp = ft->wp;
+
+ if (wp == NULL)
+ return;
+
+ fe->value = cmd_stringify_argv(wp->argc, wp->argv);
+}
+
+/* Callback for pane_current_command. */
+void
+format_cb_current_command(struct format_tree *ft, struct format_entry *fe)
+{
+ struct window_pane *wp = ft->wp;
+ char *cmd;
+
+ if (wp == NULL)
+ return;
+
+ cmd = get_proc_name(wp->fd, wp->tty);
+ if (cmd == NULL || *cmd == '\0') {
+ free(cmd);
+ cmd = cmd_stringify_argv(wp->argc, wp->argv);
+ if (cmd == NULL || *cmd == '\0') {
+ free(cmd);
+ cmd = xstrdup(wp->shell);
+ }
+ }
+ fe->value = parse_window_name(cmd);
+ free(cmd);
+}
+
/* Create a new tree. */
struct format_tree *
format_create(void)
@@ -269,7 +348,6 @@ struct format_tree *
format_create_status(int status)
{
struct format_tree *ft;
- char host[HOST_NAME_MAX + 1], *ptr;
if (!event_initialized(&format_job_event)) {
evtimer_set(&format_job_event, format_job_timer, NULL);
@@ -280,13 +358,9 @@ format_create_status(int status)
RB_INIT(&ft->tree);
ft->status = status;
- if (gethostname(host, sizeof host) == 0) {
- format_add(ft, "host", "%s", host);
- if ((ptr = strchr(host, '.')) != NULL)
- *ptr = '\0';
- format_add(ft, "host_short", "%s", host);
- }
- format_add(ft, "pid", "%ld", (long) getpid());
+ format_add_cb(ft, "host", format_cb_host);
+ format_add_cb(ft, "host_short", format_cb_host_short);
+ format_add_cb(ft, "pid", format_cb_pid);
return (ft);
}
@@ -318,17 +392,42 @@ format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
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;
+
va_start(ap, fmt);
xvasprintf(&fe->value, fmt, ap);
va_end(ap);
+}
+
+/* Add a key and function. */
+void
+format_add_cb(struct format_tree *ft, const char *key, format_cb cb)
+{
+ 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_now->value);
- fe_now->value = fe->value;
free(fe->key);
free(fe);
+ free(fe_now->value);
+ fe = fe_now;
}
+
+ fe->cb = cb;
+
+ fe->value = NULL;
}
/* Find a format entry. */
@@ -363,8 +462,11 @@ format_find(struct format_tree *ft, const char *key)
fe_find.key = (char *) key;
fe = RB_FIND(format_entry_tree, &ft->tree, &fe_find);
- if (fe != NULL)
+ if (fe != NULL) {
+ if (fe->value == NULL && fe->cb != NULL)
+ fe->cb(ft, fe);
return (fe->value);
+ }
envent = NULL;
if (ft->s != NULL)
@@ -506,7 +608,7 @@ char *
format_expand(struct format_tree *ft, const char *fmt)
{
char *buf, *tmp, *cmd;
- const char *ptr, *s;
+ const char *ptr, *s, *saved = fmt;
size_t off, len, n, slen;
int ch, brackets;
@@ -610,29 +712,10 @@ format_expand(struct format_tree *ft, const char *fmt)
}
buf[off] = '\0';
+ log_debug("format '%s' -> '%s'", saved, buf);
return (buf);
}
-/* Get command name for format. */
-char *
-format_get_command(struct window_pane *wp)
-{
- char *cmd, *out;
-
- cmd = get_proc_name(wp->fd, wp->tty);
- if (cmd == NULL || *cmd == '\0') {
- free(cmd);
- cmd = cmd_stringify_argv(wp->argc, wp->argv);
- if (cmd == NULL || *cmd == '\0') {
- free(cmd);
- cmd = xstrdup(wp->shell);
- }
- }
- out = parse_window_name(cmd);
- free(cmd);
- return (out);
-}
-
/* Get time as a string. */
char *
format_time_string(time_t t)
@@ -863,11 +946,11 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
struct grid_line *gl;
unsigned long long size;
u_int i, idx;
- char *cmd;
int status;
if (ft->w == NULL)
ft->w = wp->window;
+ ft->wp = wp;
size = 0;
for (i = 0; i < gd->hsize; i++) {
@@ -908,14 +991,8 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
format_add(ft, "pane_tty", "%s", wp->tty);
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
- if ((cmd = cmd_stringify_argv(wp->argc, wp->argv)) != NULL) {
- format_add(ft, "pane_start_command", "%s", cmd);
- free(cmd);
- }
- if ((cmd = format_get_command(wp)) != NULL) {
- format_add(ft, "pane_current_command", "%s", cmd);
- free(cmd);
- }
+ format_add_cb(ft, "pane_start_command", format_cb_start_command);
+ format_add_cb(ft, "pane_current_command", format_cb_current_command);
format_add(ft, "cursor_x", "%u", wp->base.cx);
format_add(ft, "cursor_y", "%u", wp->base.cy);