mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 01:34:18 +00:00 
			
		
		
		
	Add an option (history-file) for a file to save/restore command prompt
history, from Olof-Joachim Frahm.
This commit is contained in:
		@@ -83,6 +83,11 @@ const struct options_table_entry server_options_table[] = {
 | 
				
			|||||||
	  .default_num = 0
 | 
						  .default_num = 0
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{ .name = "history-file",
 | 
				
			||||||
 | 
						  .type = OPTIONS_TABLE_STRING,
 | 
				
			||||||
 | 
						  .default_str = NULL
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	{ .name = "message-limit",
 | 
						{ .name = "message-limit",
 | 
				
			||||||
	  .type = OPTIONS_TABLE_NUMBER,
 | 
						  .type = OPTIONS_TABLE_NUMBER,
 | 
				
			||||||
	  .minimum = 0,
 | 
						  .minimum = 0,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								server.c
									
									
									
									
									
								
							@@ -240,6 +240,7 @@ server_start(int lockfd, char *lockfile)
 | 
				
			|||||||
			cfg_add_cause("%s: %s", cfg_file, cause);
 | 
								cfg_add_cause("%s: %s", cfg_file, cause);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cmdq_continue(cfg_cmd_q);
 | 
						cmdq_continue(cfg_cmd_q);
 | 
				
			||||||
 | 
						status_prompt_load_history();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	server_add_accept(0);
 | 
						server_add_accept(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -250,6 +251,7 @@ server_start(int lockfd, char *lockfile)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	set_signals(server_signal_callback);
 | 
						set_signals(server_signal_callback);
 | 
				
			||||||
	server_loop();
 | 
						server_loop();
 | 
				
			||||||
 | 
						status_prompt_save_history();
 | 
				
			||||||
	exit(0);
 | 
						exit(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										91
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								status.c
									
									
									
									
									
								
							@@ -47,11 +47,102 @@ const char **status_prompt_complete_list(u_int *, const char *);
 | 
				
			|||||||
char   *status_prompt_complete_prefix(const char **, u_int);
 | 
					char   *status_prompt_complete_prefix(const char **, u_int);
 | 
				
			||||||
char   *status_prompt_complete(struct session *, const char *);
 | 
					char   *status_prompt_complete(struct session *, const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char   *status_prompt_find_history_file(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Status prompt history. */
 | 
					/* Status prompt history. */
 | 
				
			||||||
#define PROMPT_HISTORY 100
 | 
					#define PROMPT_HISTORY 100
 | 
				
			||||||
char	**status_prompt_hlist;
 | 
					char	**status_prompt_hlist;
 | 
				
			||||||
u_int	  status_prompt_hsize;
 | 
					u_int	  status_prompt_hsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Find the history file to load/save from/to. */
 | 
				
			||||||
 | 
					char *
 | 
				
			||||||
 | 
					status_prompt_find_history_file(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char	*home, *history_file;
 | 
				
			||||||
 | 
						char		*path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						history_file = options_get_string(&global_options, "history-file");
 | 
				
			||||||
 | 
						if (*history_file == '\0')
 | 
				
			||||||
 | 
							return (NULL);
 | 
				
			||||||
 | 
						if (*history_file == '/')
 | 
				
			||||||
 | 
							return (xstrdup(history_file));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (history_file[0] != '~' || history_file[1] != '/')
 | 
				
			||||||
 | 
							return (NULL);
 | 
				
			||||||
 | 
						if ((home = find_home()) == NULL)
 | 
				
			||||||
 | 
							return (NULL);
 | 
				
			||||||
 | 
						xasprintf(&path, "%s%s", home, history_file + 1);
 | 
				
			||||||
 | 
						return (path);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Load status prompt history from file. */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					status_prompt_load_history(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						FILE	*f;
 | 
				
			||||||
 | 
						char	*history_file, *line, *tmp;
 | 
				
			||||||
 | 
						size_t	 length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((history_file = status_prompt_find_history_file()) == NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						log_debug("loading history from %s", history_file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f = fopen(history_file, "r");
 | 
				
			||||||
 | 
						if (f == NULL) {
 | 
				
			||||||
 | 
							log_debug("%s: %s", history_file, strerror(errno));
 | 
				
			||||||
 | 
							free(history_file);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(history_file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (;;) {
 | 
				
			||||||
 | 
							if ((line = fgetln(f, &length)) == NULL)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (length > 0) {
 | 
				
			||||||
 | 
								if (line[length - 1] == '\n') {
 | 
				
			||||||
 | 
									line[length - 1] = '\0';
 | 
				
			||||||
 | 
									status_prompt_add_history(line);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									tmp = xmalloc(length + 1);
 | 
				
			||||||
 | 
									memcpy(tmp, line, length);
 | 
				
			||||||
 | 
									tmp[length] = '\0';
 | 
				
			||||||
 | 
									status_prompt_add_history(tmp);
 | 
				
			||||||
 | 
									free(tmp);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fclose(f);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Save status prompt history to file. */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					status_prompt_save_history(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						FILE	*f;
 | 
				
			||||||
 | 
						u_int	 i;
 | 
				
			||||||
 | 
						char	*history_file;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((history_file = status_prompt_find_history_file()) == NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						log_debug("saving history to %s", history_file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f = fopen(history_file, "w");
 | 
				
			||||||
 | 
						if (f == NULL) {
 | 
				
			||||||
 | 
							log_debug("%s: %s", history_file, strerror(errno));
 | 
				
			||||||
 | 
							free(history_file);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(history_file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < status_prompt_hsize; i++) {
 | 
				
			||||||
 | 
							fputs(status_prompt_hlist[i], f);
 | 
				
			||||||
 | 
							fputc('\n', f);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fclose(f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Status output tree. */
 | 
					/* Status output tree. */
 | 
				
			||||||
RB_GENERATE(status_out_tree, status_out, entry, status_out_cmp);
 | 
					RB_GENERATE(status_out_tree, status_out, entry, status_out_cmp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								tmux.1
									
									
									
									
									
								
							@@ -2396,6 +2396,10 @@ passed through to applications running in
 | 
				
			|||||||
.Nm .
 | 
					.Nm .
 | 
				
			||||||
Attached clients should be detached and attached again after changing this
 | 
					Attached clients should be detached and attached again after changing this
 | 
				
			||||||
option.
 | 
					option.
 | 
				
			||||||
 | 
					.It Ic history-file Ar path
 | 
				
			||||||
 | 
					If not empty, a file to which
 | 
				
			||||||
 | 
					.Nm
 | 
				
			||||||
 | 
					will write command prompt history on exit and load it from on start.
 | 
				
			||||||
.It Ic message-limit Ar number
 | 
					.It Ic message-limit Ar number
 | 
				
			||||||
Set the number of error or information messages to save in the message log for
 | 
					Set the number of error or information messages to save in the message log for
 | 
				
			||||||
each client.
 | 
					each client.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								tmux.c
									
									
									
									
									
								
							@@ -198,10 +198,27 @@ shell_exec(const char *shell, const char *shellcmd)
 | 
				
			|||||||
	fatal("execl failed");
 | 
						fatal("execl failed");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char*
 | 
				
			||||||
 | 
					find_home(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct passwd	*pw;
 | 
				
			||||||
 | 
						const char	*home;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						home = getenv("HOME");
 | 
				
			||||||
 | 
						if (home == NULL || *home == '\0') {
 | 
				
			||||||
 | 
							pw = getpwuid(getuid());
 | 
				
			||||||
 | 
							if (pw != NULL)
 | 
				
			||||||
 | 
								home = pw->pw_dir;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								home = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return home;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
main(int argc, char **argv)
 | 
					main(int argc, char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct passwd	*pw;
 | 
					 | 
				
			||||||
	char		*s, *path, *label, **var, tmp[PATH_MAX];
 | 
						char		*s, *path, *label, **var, tmp[PATH_MAX];
 | 
				
			||||||
	char		 in[256];
 | 
						char		 in[256];
 | 
				
			||||||
	const char	*home;
 | 
						const char	*home;
 | 
				
			||||||
@@ -320,14 +337,7 @@ main(int argc, char **argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* Locate the configuration file. */
 | 
						/* Locate the configuration file. */
 | 
				
			||||||
	if (cfg_file == NULL) {
 | 
						if (cfg_file == NULL) {
 | 
				
			||||||
		home = getenv("HOME");
 | 
							home = find_home();
 | 
				
			||||||
		if (home == NULL || *home == '\0') {
 | 
					 | 
				
			||||||
			pw = getpwuid(getuid());
 | 
					 | 
				
			||||||
			if (pw != NULL)
 | 
					 | 
				
			||||||
				home = pw->pw_dir;
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				home = NULL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (home != NULL) {
 | 
							if (home != NULL) {
 | 
				
			||||||
			xasprintf(&cfg_file, "%s/.tmux.conf", home);
 | 
								xasprintf(&cfg_file, "%s/.tmux.conf", home);
 | 
				
			||||||
			if (access(cfg_file, R_OK) != 0 && errno == ENOENT) {
 | 
								if (access(cfg_file, R_OK) != 0 && errno == ENOENT) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1469,6 +1469,7 @@ int		 checkshell(const char *);
 | 
				
			|||||||
int		 areshell(const char *);
 | 
					int		 areshell(const char *);
 | 
				
			||||||
void		 setblocking(int, int);
 | 
					void		 setblocking(int, int);
 | 
				
			||||||
__dead void	 shell_exec(const char *, const char *);
 | 
					__dead void	 shell_exec(const char *, const char *);
 | 
				
			||||||
 | 
					const char	*find_home(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* cfg.c */
 | 
					/* cfg.c */
 | 
				
			||||||
extern struct cmd_q *cfg_cmd_q;
 | 
					extern struct cmd_q *cfg_cmd_q;
 | 
				
			||||||
@@ -1943,6 +1944,8 @@ void	 status_prompt_clear(struct client *);
 | 
				
			|||||||
int	 status_prompt_redraw(struct client *);
 | 
					int	 status_prompt_redraw(struct client *);
 | 
				
			||||||
void	 status_prompt_key(struct client *, int);
 | 
					void	 status_prompt_key(struct client *, int);
 | 
				
			||||||
void	 status_prompt_update(struct client *, const char *, const char *);
 | 
					void	 status_prompt_update(struct client *, const char *, const char *);
 | 
				
			||||||
 | 
					void	 status_prompt_load_history(void);
 | 
				
			||||||
 | 
					void	 status_prompt_save_history(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* resize.c */
 | 
					/* resize.c */
 | 
				
			||||||
void	 recalculate_sizes(void);
 | 
					void	 recalculate_sizes(void);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user