mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +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:
		
							
								
								
									
										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);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user