mirror of
https://github.com/tmux/tmux.git
synced 2025-01-07 16:28:48 +00:00
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.
This commit is contained in:
parent
55b8d74561
commit
983ebb2689
175
format.c
175
format.c
@ -35,14 +35,23 @@
|
|||||||
* string.
|
* string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct format_entry;
|
||||||
|
typedef void (*format_cb)(struct format_tree *, struct format_entry *);
|
||||||
|
|
||||||
void format_job_callback(struct job *);
|
void format_job_callback(struct job *);
|
||||||
const char *format_job_get(struct format_tree *, const char *);
|
const char *format_job_get(struct format_tree *, const char *);
|
||||||
void format_job_timer(int, short, void *);
|
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 **,
|
int format_replace(struct format_tree *, const char *, size_t, char **,
|
||||||
size_t *, size_t *);
|
size_t *, size_t *);
|
||||||
char *format_time_string(time_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_pane_tabs(struct format_tree *, struct window_pane *);
|
||||||
void format_defaults_session(struct format_tree *, struct session *);
|
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. */
|
/* Entry in format tree. */
|
||||||
struct format_entry {
|
struct format_entry {
|
||||||
char *key;
|
char *key;
|
||||||
char *value;
|
char *value;
|
||||||
|
format_cb cb;
|
||||||
RB_ENTRY(format_entry) entry;
|
RB_ENTRY(format_entry) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Format entry tree. */
|
/* Format entry tree. */
|
||||||
struct format_tree {
|
struct format_tree {
|
||||||
struct window *w;
|
struct window *w;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
|
struct window_pane *wp;
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
RB_HEAD(format_entry_tree, format_entry) tree;
|
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);
|
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. */
|
/* Create a new tree. */
|
||||||
struct format_tree *
|
struct format_tree *
|
||||||
format_create(void)
|
format_create(void)
|
||||||
@ -269,7 +348,6 @@ struct format_tree *
|
|||||||
format_create_status(int status)
|
format_create_status(int status)
|
||||||
{
|
{
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
char host[HOST_NAME_MAX + 1], *ptr;
|
|
||||||
|
|
||||||
if (!event_initialized(&format_job_event)) {
|
if (!event_initialized(&format_job_event)) {
|
||||||
evtimer_set(&format_job_event, format_job_timer, NULL);
|
evtimer_set(&format_job_event, format_job_timer, NULL);
|
||||||
@ -280,13 +358,9 @@ format_create_status(int status)
|
|||||||
RB_INIT(&ft->tree);
|
RB_INIT(&ft->tree);
|
||||||
ft->status = status;
|
ft->status = status;
|
||||||
|
|
||||||
if (gethostname(host, sizeof host) == 0) {
|
format_add_cb(ft, "host", format_cb_host);
|
||||||
format_add(ft, "host", "%s", host);
|
format_add_cb(ft, "host_short", format_cb_host_short);
|
||||||
if ((ptr = strchr(host, '.')) != NULL)
|
format_add_cb(ft, "pid", format_cb_pid);
|
||||||
*ptr = '\0';
|
|
||||||
format_add(ft, "host_short", "%s", host);
|
|
||||||
}
|
|
||||||
format_add(ft, "pid", "%ld", (long) getpid());
|
|
||||||
|
|
||||||
return (ft);
|
return (ft);
|
||||||
}
|
}
|
||||||
@ -318,17 +392,42 @@ format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
|
|||||||
fe = xmalloc(sizeof *fe);
|
fe = xmalloc(sizeof *fe);
|
||||||
fe->key = xstrdup(key);
|
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);
|
va_start(ap, fmt);
|
||||||
xvasprintf(&fe->value, fmt, ap);
|
xvasprintf(&fe->value, fmt, ap);
|
||||||
va_end(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);
|
fe_now = RB_INSERT(format_entry_tree, &ft->tree, fe);
|
||||||
if (fe_now != NULL) {
|
if (fe_now != NULL) {
|
||||||
free(fe_now->value);
|
|
||||||
fe_now->value = fe->value;
|
|
||||||
free(fe->key);
|
free(fe->key);
|
||||||
free(fe);
|
free(fe);
|
||||||
|
free(fe_now->value);
|
||||||
|
fe = fe_now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fe->cb = cb;
|
||||||
|
|
||||||
|
fe->value = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a format entry. */
|
/* Find a format entry. */
|
||||||
@ -363,8 +462,11 @@ format_find(struct format_tree *ft, const char *key)
|
|||||||
|
|
||||||
fe_find.key = (char *) key;
|
fe_find.key = (char *) key;
|
||||||
fe = RB_FIND(format_entry_tree, &ft->tree, &fe_find);
|
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);
|
return (fe->value);
|
||||||
|
}
|
||||||
|
|
||||||
envent = NULL;
|
envent = NULL;
|
||||||
if (ft->s != NULL)
|
if (ft->s != NULL)
|
||||||
@ -506,7 +608,7 @@ char *
|
|||||||
format_expand(struct format_tree *ft, const char *fmt)
|
format_expand(struct format_tree *ft, const char *fmt)
|
||||||
{
|
{
|
||||||
char *buf, *tmp, *cmd;
|
char *buf, *tmp, *cmd;
|
||||||
const char *ptr, *s;
|
const char *ptr, *s, *saved = fmt;
|
||||||
size_t off, len, n, slen;
|
size_t off, len, n, slen;
|
||||||
int ch, brackets;
|
int ch, brackets;
|
||||||
|
|
||||||
@ -610,29 +712,10 @@ format_expand(struct format_tree *ft, const char *fmt)
|
|||||||
}
|
}
|
||||||
buf[off] = '\0';
|
buf[off] = '\0';
|
||||||
|
|
||||||
|
log_debug("format '%s' -> '%s'", saved, buf);
|
||||||
return (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. */
|
/* Get time as a string. */
|
||||||
char *
|
char *
|
||||||
format_time_string(time_t t)
|
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;
|
struct grid_line *gl;
|
||||||
unsigned long long size;
|
unsigned long long size;
|
||||||
u_int i, idx;
|
u_int i, idx;
|
||||||
char *cmd;
|
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (ft->w == NULL)
|
if (ft->w == NULL)
|
||||||
ft->w = wp->window;
|
ft->w = wp->window;
|
||||||
|
ft->wp = wp;
|
||||||
|
|
||||||
size = 0;
|
size = 0;
|
||||||
for (i = 0; i < gd->hsize; i++) {
|
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_tty", "%s", wp->tty);
|
||||||
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
|
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
|
||||||
if ((cmd = cmd_stringify_argv(wp->argc, wp->argv)) != NULL) {
|
format_add_cb(ft, "pane_start_command", format_cb_start_command);
|
||||||
format_add(ft, "pane_start_command", "%s", cmd);
|
format_add_cb(ft, "pane_current_command", format_cb_current_command);
|
||||||
free(cmd);
|
|
||||||
}
|
|
||||||
if ((cmd = format_get_command(wp)) != NULL) {
|
|
||||||
format_add(ft, "pane_current_command", "%s", cmd);
|
|
||||||
free(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
format_add(ft, "cursor_x", "%u", wp->base.cx);
|
format_add(ft, "cursor_x", "%u", wp->base.cx);
|
||||||
format_add(ft, "cursor_y", "%u", wp->base.cy);
|
format_add(ft, "cursor_y", "%u", wp->base.cy);
|
||||||
|
Loading…
Reference in New Issue
Block a user