mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Add a per-client log of status line messages displayed while that client
exists. A new message-limit session option sets the maximum number of entries and a command, show-messages, shows the log (bound to ~ by default). This (and prompt history) might be better as a single global log but until there are global options it is easier for them to be per client.
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -22,7 +22,7 @@ SRCS=	attributes.c cfg.c client.c clock.c \
 | 
			
		||||
	cmd-select-layout.c cmd-select-pane.c \
 | 
			
		||||
	cmd-select-prompt.c cmd-select-window.c cmd-send-keys.c \
 | 
			
		||||
	cmd-send-prefix.c cmd-server-info.c cmd-set-buffer.c cmd-set-option.c \
 | 
			
		||||
	cmd-set-window-option.c cmd-show-buffer.c \
 | 
			
		||||
	cmd-set-window-option.c cmd-show-buffer.c cmd-show-messages.c \
 | 
			
		||||
	cmd-show-options.c cmd-show-window-options.c cmd-source-file.c \
 | 
			
		||||
	cmd-split-window.c cmd-start-server.c cmd-string.c cmd-if-shell.c \
 | 
			
		||||
	cmd-run-shell.c cmd-suspend-client.c cmd-swap-pane.c cmd-swap-window.c \
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,7 @@ const struct set_option_entry set_option_table[] = {
 | 
			
		||||
	{ "message-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
 | 
			
		||||
	{ "message-bg", SET_OPTION_COLOUR, 0, 0, NULL },
 | 
			
		||||
	{ "message-fg", SET_OPTION_COLOUR, 0, 0, NULL },
 | 
			
		||||
	{ "message-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
 | 
			
		||||
	{ "mouse-select-pane", SET_OPTION_FLAG, 0, 0, NULL },
 | 
			
		||||
	{ "prefix", SET_OPTION_KEYS, 0, 0, NULL },
 | 
			
		||||
	{ "repeat-time", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										65
									
								
								cmd-show-messages.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								cmd-show-messages.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
/* $OpenBSD$ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
 *
 | 
			
		||||
 * Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
 * purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 * copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Show client message log.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
int	cmd_show_messages_exec(struct cmd *, struct cmd_ctx *);
 | 
			
		||||
 | 
			
		||||
const struct cmd_entry cmd_show_messages_entry = {
 | 
			
		||||
	"show-messages", "showmsgs",
 | 
			
		||||
	CMD_TARGET_CLIENT_USAGE,
 | 
			
		||||
	0, "",
 | 
			
		||||
	cmd_target_init,
 | 
			
		||||
	cmd_target_parse,
 | 
			
		||||
	cmd_show_messages_exec,
 | 
			
		||||
	cmd_target_free,
 | 
			
		||||
	cmd_target_print
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
cmd_show_messages_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd_target_data		*data = self->data;
 | 
			
		||||
	struct client			*c;
 | 
			
		||||
	struct message_entry		*msg;
 | 
			
		||||
	char				*tim;
 | 
			
		||||
	u_int				 i;
 | 
			
		||||
 | 
			
		||||
	if ((c = cmd_find_client(ctx, data->target)) == NULL)
 | 
			
		||||
		return (-1);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&c->message_log); i++) {
 | 
			
		||||
		msg = &ARRAY_ITEM(&c->message_log, i);
 | 
			
		||||
 | 
			
		||||
		tim = ctime(&msg->msg_time);
 | 
			
		||||
		*strchr(tim, '\n') = '\0';
 | 
			
		||||
		
 | 
			
		||||
		ctx->print(ctx, "%s %s", tim, msg->msg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								cmd.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								cmd.c
									
									
									
									
									
								
							@@ -95,6 +95,7 @@ const struct cmd_entry *cmd_table[] = {
 | 
			
		||||
	&cmd_set_window_option_entry,
 | 
			
		||||
	&cmd_show_buffer_entry,
 | 
			
		||||
	&cmd_show_environment_entry,
 | 
			
		||||
	&cmd_show_messages_entry,
 | 
			
		||||
	&cmd_show_options_entry,
 | 
			
		||||
	&cmd_show_window_options_entry,
 | 
			
		||||
	&cmd_source_file_entry,
 | 
			
		||||
 
 | 
			
		||||
@@ -105,8 +105,8 @@ key_bindings_init(void)
 | 
			
		||||
		{ ' ',			  0, &cmd_next_layout_entry },
 | 
			
		||||
		{ '!', 			  0, &cmd_break_pane_entry },
 | 
			
		||||
		{ '"', 			  0, &cmd_split_window_entry },	
 | 
			
		||||
		{ '%', 			  0, &cmd_split_window_entry },	
 | 
			
		||||
		{ '#', 			  0, &cmd_list_buffers_entry },
 | 
			
		||||
		{ '%', 			  0, &cmd_split_window_entry },	
 | 
			
		||||
		{ '&', 			  0, &cmd_confirm_before_entry },
 | 
			
		||||
		{ ',', 			  0, &cmd_command_prompt_entry },
 | 
			
		||||
		{ '-', 			  0, &cmd_delete_buffer_entry },
 | 
			
		||||
@@ -123,13 +123,15 @@ key_bindings_init(void)
 | 
			
		||||
		{ '9', 			  0, &cmd_select_window_entry },
 | 
			
		||||
		{ ':', 			  0, &cmd_command_prompt_entry },
 | 
			
		||||
		{ '?', 			  0, &cmd_list_keys_entry },
 | 
			
		||||
		{ 'D',			  0, &cmd_choose_client_entry },
 | 
			
		||||
		{ '[', 			  0, &cmd_copy_mode_entry },
 | 
			
		||||
		{ '\'',			  0, &cmd_select_prompt_entry },
 | 
			
		||||
		{ '\002', /* C-b */	  0, &cmd_send_prefix_entry },
 | 
			
		||||
		{ '\017', /* C-o */	  0, &cmd_rotate_window_entry },
 | 
			
		||||
		{ '\032', /* C-z */	  0, &cmd_suspend_client_entry },
 | 
			
		||||
		{ ']', 			  0, &cmd_paste_buffer_entry },
 | 
			
		||||
		{ 'c', 			  0, &cmd_new_window_entry },
 | 
			
		||||
		{ 'd', 			  0, &cmd_detach_client_entry },
 | 
			
		||||
		{ 'D',			  0, &cmd_choose_client_entry },
 | 
			
		||||
		{ 'f', 			  0, &cmd_command_prompt_entry },
 | 
			
		||||
		{ 'i',			  0, &cmd_display_message_entry },
 | 
			
		||||
		{ 'l', 			  0, &cmd_last_window_entry },
 | 
			
		||||
@@ -144,13 +146,14 @@ key_bindings_init(void)
 | 
			
		||||
		{ 'x', 			  0, &cmd_confirm_before_entry },
 | 
			
		||||
		{ '{',			  0, &cmd_swap_pane_entry },
 | 
			
		||||
		{ '}',			  0, &cmd_swap_pane_entry },
 | 
			
		||||
		{ '\002', /* C-b */	  0, &cmd_send_prefix_entry },
 | 
			
		||||
		{ '~',			  0, &cmd_show_messages_entry },
 | 
			
		||||
		{ '1' | KEYC_ESCAPE,	  0, &cmd_select_layout_entry },
 | 
			
		||||
		{ '2' | KEYC_ESCAPE,	  0, &cmd_select_layout_entry },
 | 
			
		||||
		{ '3' | KEYC_ESCAPE,	  0, &cmd_select_layout_entry },
 | 
			
		||||
		{ '4' | KEYC_ESCAPE,	  0, &cmd_select_layout_entry },
 | 
			
		||||
		{ KEYC_PPAGE, 		  0, &cmd_copy_mode_entry },
 | 
			
		||||
		{ 'n' | KEYC_ESCAPE, 	  0, &cmd_next_window_entry },
 | 
			
		||||
		{ 'o' | KEYC_ESCAPE,	  0, &cmd_rotate_window_entry },
 | 
			
		||||
		{ 'p' | KEYC_ESCAPE, 	  0, &cmd_previous_window_entry },
 | 
			
		||||
		{ KEYC_UP, 		  0, &cmd_up_pane_entry },
 | 
			
		||||
		{ KEYC_DOWN, 		  0, &cmd_down_pane_entry },
 | 
			
		||||
@@ -162,8 +165,6 @@ key_bindings_init(void)
 | 
			
		||||
		{ KEYC_DOWN | KEYC_CTRL,  1, &cmd_resize_pane_entry },	
 | 
			
		||||
		{ KEYC_LEFT | KEYC_CTRL,  1, &cmd_resize_pane_entry },
 | 
			
		||||
		{ KEYC_RIGHT | KEYC_CTRL, 1, &cmd_resize_pane_entry },
 | 
			
		||||
		{ 'o' | KEYC_ESCAPE,	  0, &cmd_rotate_window_entry },
 | 
			
		||||
		{ '\017', /* C-o */	  0, &cmd_rotate_window_entry },
 | 
			
		||||
	};
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
	struct cmd	*cmd;
 | 
			
		||||
 
 | 
			
		||||
@@ -80,6 +80,7 @@ server_client_create(int fd)
 | 
			
		||||
	job_tree_init(&c->status_jobs);
 | 
			
		||||
 | 
			
		||||
	c->message_string = NULL;
 | 
			
		||||
	ARRAY_INIT(&c->message_log);
 | 
			
		||||
 | 
			
		||||
	c->prompt_string = NULL;
 | 
			
		||||
	c->prompt_buffer = NULL;
 | 
			
		||||
@@ -101,7 +102,8 @@ server_client_create(int fd)
 | 
			
		||||
void
 | 
			
		||||
server_client_lost(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	u_int	i;
 | 
			
		||||
	struct message_entry	*msg;
 | 
			
		||||
	u_int			 i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
 | 
			
		||||
		if (ARRAY_ITEM(&clients, i) == c)
 | 
			
		||||
@@ -129,6 +131,11 @@ server_client_lost(struct client *c)
 | 
			
		||||
	if (c->message_string != NULL)
 | 
			
		||||
		xfree(c->message_string);
 | 
			
		||||
	evtimer_del(&c->message_timer);
 | 
			
		||||
	for (i = 0; i < ARRAY_LENGTH(&c->message_log); i++) {
 | 
			
		||||
		msg = &ARRAY_ITEM(&c->message_log, i);
 | 
			
		||||
		xfree(msg->msg);
 | 
			
		||||
	}
 | 
			
		||||
	ARRAY_FREE(&c->message_log);
 | 
			
		||||
 | 
			
		||||
	if (c->prompt_string != NULL)
 | 
			
		||||
		xfree(c->prompt_string);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								status.c
									
									
									
									
									
								
							@@ -566,9 +566,12 @@ status_print(struct session *s, struct winlink *wl, struct grid_cell *gc)
 | 
			
		||||
void printflike2
 | 
			
		||||
status_message_set(struct client *c, const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	struct timeval	tv;
 | 
			
		||||
	va_list		ap;
 | 
			
		||||
	int		delay;
 | 
			
		||||
	struct timeval		 tv;
 | 
			
		||||
	struct session		*s = c->session;
 | 
			
		||||
	struct message_entry	*msg;
 | 
			
		||||
	va_list			 ap;
 | 
			
		||||
	int			 delay;
 | 
			
		||||
	u_int			 i, limit;
 | 
			
		||||
 | 
			
		||||
	status_prompt_clear(c);
 | 
			
		||||
	status_message_clear(c);
 | 
			
		||||
@@ -577,10 +580,25 @@ status_message_set(struct client *c, const char *fmt, ...)
 | 
			
		||||
	xvasprintf(&c->message_string, fmt, ap);
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
 | 
			
		||||
	ARRAY_EXPAND(&c->message_log, 1);
 | 
			
		||||
	msg = &ARRAY_LAST(&c->message_log);
 | 
			
		||||
	msg->msg_time = time(NULL);
 | 
			
		||||
	msg->msg = xstrdup(c->message_string);
 | 
			
		||||
 | 
			
		||||
	if (s == NULL)
 | 
			
		||||
		limit = 0;
 | 
			
		||||
	else
 | 
			
		||||
		limit = options_get_number(&s->options, "message-limit");
 | 
			
		||||
	for (i = ARRAY_LENGTH(&c->message_log); i > limit; i--) {
 | 
			
		||||
		msg = &ARRAY_ITEM(&c->message_log, i - 1);
 | 
			
		||||
		xfree(msg->msg);
 | 
			
		||||
		ARRAY_REMOVE(&c->message_log, i - 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	delay = options_get_number(&c->session->options, "display-time");
 | 
			
		||||
	tv.tv_sec = delay / 1000;
 | 
			
		||||
	tv.tv_usec = (delay % 1000) * 1000L;
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	evtimer_del(&c->message_timer);
 | 
			
		||||
	evtimer_set(&c->message_timer, status_message_callback, c);
 | 
			
		||||
	evtimer_add(&c->message_timer, &tv);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								tmux.1
									
									
									
									
									
								
							@@ -454,6 +454,16 @@ with
 | 
			
		||||
.D1 (alias: Ic rename )
 | 
			
		||||
Rename the session to
 | 
			
		||||
.Ar new-name .
 | 
			
		||||
.It Xo Ic show-messages 
 | 
			
		||||
.Op Fl t Ar target-client
 | 
			
		||||
.Xc
 | 
			
		||||
.D1 (alias: Ic showmsgs )
 | 
			
		||||
Any messages displayed on the status line are saved in a per-client message
 | 
			
		||||
log, up to a maximum of the limit set by the
 | 
			
		||||
.Ar message-limit
 | 
			
		||||
session option for the session attached to that client.
 | 
			
		||||
This command displays the log for
 | 
			
		||||
.Ar target-client .
 | 
			
		||||
.It Ic source-file Ar path
 | 
			
		||||
.D1 (alias: Ic source )
 | 
			
		||||
Execute commands from
 | 
			
		||||
@@ -1373,6 +1383,10 @@ from the 256-colour palette, or
 | 
			
		||||
.Ic default .
 | 
			
		||||
.It Ic message-fg Ar colour
 | 
			
		||||
Set status line message foreground colour.
 | 
			
		||||
.It Ic message-limit Ar number
 | 
			
		||||
Set the number of error or information messages to save in the message log for
 | 
			
		||||
each client.
 | 
			
		||||
The default is 20.
 | 
			
		||||
.It Xo Ic mouse-select-pane
 | 
			
		||||
.Op Ic on | off
 | 
			
		||||
.Xc
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								tmux.c
									
									
									
									
									
								
							@@ -332,6 +332,7 @@ main(int argc, char **argv)
 | 
			
		||||
	options_set_number(so, "message-attr", 0);
 | 
			
		||||
	options_set_number(so, "message-bg", 3);
 | 
			
		||||
	options_set_number(so, "message-fg", 0);
 | 
			
		||||
	options_set_number(so, "message-limit", 20);
 | 
			
		||||
	options_set_number(so, "mouse-select-pane", 0);
 | 
			
		||||
	options_set_number(so, "repeat-time", 500);
 | 
			
		||||
	options_set_number(so, "set-remain-on-exit", 0);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1041,6 +1041,12 @@ struct mouse_event {
 | 
			
		||||
	u_char	y;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Saved message entry. */
 | 
			
		||||
struct message_entry {
 | 
			
		||||
	char   *msg;
 | 
			
		||||
	time_t	msg_time;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Client connection. */
 | 
			
		||||
struct client {
 | 
			
		||||
	struct imsgbuf	 ibuf;
 | 
			
		||||
@@ -1077,6 +1083,7 @@ struct client {
 | 
			
		||||
 | 
			
		||||
	char		*message_string;
 | 
			
		||||
	struct event	 message_timer;
 | 
			
		||||
	ARRAY_DECL(, struct message_entry) message_log;
 | 
			
		||||
 | 
			
		||||
	char		*prompt_string;
 | 
			
		||||
	char		*prompt_buffer;
 | 
			
		||||
@@ -1481,6 +1488,7 @@ extern const struct cmd_entry cmd_set_option_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_set_window_option_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_show_buffer_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_show_environment_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_show_messages_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_show_options_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_show_window_options_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_source_file_entry;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user