Commit 36677253 authored by Vincent Lefevre's avatar Vincent Lefevre

Add $history_file and $save_history, for saving command history across

sessions.
parent 7f853948
......@@ -4,6 +4,7 @@ mutt. Please read this file carefully when upgrading your installation.
The keys used are:
!: modified feature, -: deleted feature, +: new feature
+ $save_history, $history_file (save history across sessions)
+ $assumed_charset, $file_charset, $strict_mime
+ $smtp_url (ESMTP relay support)
+ $crypt_use_pka (use GPGME PKA signature verification)
......
......@@ -562,7 +562,7 @@ int _mutt_enter_string (char *buf, size_t buflen, int y, int x,
{
mutt_pretty_mailbox (buf);
if (!pass)
mutt_history_add (hclass, buf);
mutt_history_add (hclass, buf, 1);
rv = 0;
goto bye;
}
......@@ -667,7 +667,7 @@ self_insert:
/* Convert from wide characters */
my_wcstombs (buf, buflen, state->wbuf, state->lastchar);
if (!pass)
mutt_history_add (hclass, buf);
mutt_history_add (hclass, buf, 1);
if (multiple)
{
......
......@@ -53,6 +53,7 @@ WHERE char *FolderFormat;
WHERE char *ForwFmt;
WHERE char *Fqdn;
WHERE char *HdrFmt;
WHERE char *HistFile;
WHERE char *Homedir;
WHERE char *Hostname;
#ifdef USE_IMAP
......@@ -195,6 +196,7 @@ WHERE short MenuContext;
WHERE short PagerContext;
WHERE short PagerIndexLines;
WHERE short ReadInc;
WHERE short SaveHist;
WHERE short SendmailWait;
WHERE short SleepTime INITVAL (1);
WHERE short Timeout;
......
......@@ -56,6 +56,145 @@ static void init_history (struct history *h)
h->last = 0;
}
void mutt_read_histfile (void)
{
FILE *f;
int line = 0, hclass, read;
char *linebuf = NULL, *p;
size_t buflen;
if ((f = fopen (HistFile, "r")) == NULL)
return;
while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL)
{
read = 0;
if (sscanf (linebuf, "%d:%n", &hclass, &read) < 1 || read == 0 ||
*(p = linebuf + strlen (linebuf) - 1) != '|')
{
mutt_error (_("Bad history file format (line %d)"), line);
break;
}
*p = '\0';
p = safe_strdup (linebuf + read);
if (p)
{
mutt_convert_string (&p, "utf-8", Charset, 0);
mutt_history_add (hclass, p, 0);
FREE (&p);
}
}
fclose (f);
FREE (&linebuf);
}
static void shrink_histfile (void)
{
char tmpfname[_POSIX_PATH_MAX];
FILE *f, *tmp = NULL;
int n[HC_LAST] = { 0 };
int line, hclass;
char *linebuf = NULL;
size_t buflen;
if ((f = fopen (HistFile, "r")) == NULL)
return;
line = 0;
while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL)
{
if (sscanf (linebuf, "%d", &hclass) < 1)
{
mutt_error (_("Bad history file format (line %d)"), line);
goto cleanup;
}
n[hclass]++;
}
for(hclass = HC_FIRST; hclass < HC_LAST; hclass++)
if (n[hclass] > SaveHist)
{
mutt_mktemp (tmpfname);
if ((tmp = safe_fopen (tmpfname, "w+")) == NULL)
mutt_perror (tmpfname);
break;
}
if (tmp != NULL)
{
rewind (f);
line = 0;
while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL)
{
if (sscanf (linebuf, "%d", &hclass) < 1)
{
mutt_error (_("Bad history file format (line %d)"), line);
goto cleanup;
}
if (n[hclass]-- <= SaveHist)
fprintf (tmp, "%s\n", linebuf);
}
}
cleanup:
fclose (f);
FREE (&linebuf);
if (tmp != NULL)
{
if (fflush (tmp) == 0 &&
(f = fopen (HistFile, "w")) != NULL) /* __FOPEN_CHECKED__ */
{
rewind (tmp);
mutt_copy_stream (tmp, f);
fclose (f);
}
fclose (tmp);
unlink (tmpfname);
}
}
static void save_history (history_class_t hclass, const char *s)
{
static int n = 0;
FILE *f;
char *tmp, *p;
if (!s || !*s) /* This shouldn't happen, but it's safer. */
return;
if ((f = fopen (HistFile, "a")) == NULL)
{
mutt_perror ("fopen");
return;
}
tmp = safe_strdup (s);
mutt_convert_string (&tmp, Charset, "utf-8", 0);
/* Format of a history item (1 line): "<histclass>:<string>|".
We add a '|' in order to avoid lines ending with '\'. */
fprintf (f, "%d:", (int) hclass);
for (p = tmp; *p; p++)
{
/* Don't copy \n as a history item must fit on one line. The string
shouldn't contain such a character anyway, but as this can happen
in practice, we must deal with that. */
if (*p != '\n')
putc ((unsigned char) *p, f);
}
fputs ("|\n", f);
fclose (f);
FREE (&tmp);
if (--n < 0)
{
n = SaveHist;
shrink_histfile();
}
}
void mutt_init_history(void)
{
history_class_t hclass;
......@@ -69,7 +208,7 @@ void mutt_init_history(void)
OldSize = HistSize;
}
void mutt_history_add (history_class_t hclass, const char *s)
void mutt_history_add (history_class_t hclass, const char *s, int save)
{
int prev;
struct history *h = &History[hclass];
......@@ -88,6 +227,8 @@ void mutt_history_add (history_class_t hclass, const char *s)
*/
if (*s != ' ' && (!h->hist[prev] || mutt_strcmp (h->hist[prev], s) != 0))
{
if (save && SaveHist)
save_history (hclass, s);
mutt_str_replace (&h->hist[h->last++], s);
if (h->last > HistSize - 1)
h->last = 0;
......
......@@ -35,7 +35,8 @@ enum history_class
typedef enum history_class history_class_t;
void mutt_init_history(void);
void mutt_history_add(history_class_t, const char *);
void mutt_read_histfile(void);
void mutt_history_add(history_class_t, const char *, int);
char *mutt_history_next(history_class_t);
char *mutt_history_prev(history_class_t);
......
......@@ -3012,6 +3012,8 @@ void mutt_init (int skip_sys_rc, LIST *commands)
mutt_exit(1);
}
mutt_read_histfile ();
#if 0
set_option (OPTWEED); /* turn weeding on by default */
#endif
......
......@@ -828,6 +828,11 @@ struct option_t MuttVars[] = {
** the string history buffer. The buffer is cleared each time the
** variable is set.
*/
{ "history_file", DT_PATH, R_NONE, UL &HistFile, UL "~/.mutthistory" },
/*
** .pp
** The file in which Mutt will save its history.
*/
{ "honor_followup_to", DT_QUAD, R_NONE, OPT_MFUPTO, M_YES },
/*
** .pp
......@@ -2438,6 +2443,12 @@ struct option_t MuttVars[] = {
** \fBNote:\fP This only applies to mbox and MMDF folders, Mutt does not
** delete MH and Maildir directories.
*/
{ "save_history", DT_NUM, R_NONE, UL &SaveHist, 0 },
/*
** .pp
** This variable controls the size of the history saved in the
** ``$$history_file'' file.
*/
{ "save_name", DT_BOOL, R_NONE, OPTSAVENAME, 0 },
/*
** .pp
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment