Add an option (history-file) for a file to save/restore command prompt

history, from Olof-Joachim Frahm.
This commit is contained in:
nicm 2015-07-20 15:50:04 +00:00
parent d4ce210713
commit 92af3766ec
6 changed files with 124 additions and 9 deletions

View File

@ -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,

View File

@ -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);
} }

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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);