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. ...@@ -4,6 +4,7 @@ mutt. Please read this file carefully when upgrading your installation.
The keys used are: The keys used are:
!: modified feature, -: deleted feature, +: new feature !: modified feature, -: deleted feature, +: new feature
+ $save_history, $history_file (save history across sessions)
+ $assumed_charset, $file_charset, $strict_mime + $assumed_charset, $file_charset, $strict_mime
+ $smtp_url (ESMTP relay support) + $smtp_url (ESMTP relay support)
+ $crypt_use_pka (use GPGME PKA signature verification) + $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, ...@@ -562,7 +562,7 @@ int _mutt_enter_string (char *buf, size_t buflen, int y, int x,
{ {
mutt_pretty_mailbox (buf); mutt_pretty_mailbox (buf);
if (!pass) if (!pass)
mutt_history_add (hclass, buf); mutt_history_add (hclass, buf, 1);
rv = 0; rv = 0;
goto bye; goto bye;
} }
...@@ -667,7 +667,7 @@ self_insert: ...@@ -667,7 +667,7 @@ self_insert:
/* Convert from wide characters */ /* Convert from wide characters */
my_wcstombs (buf, buflen, state->wbuf, state->lastchar); my_wcstombs (buf, buflen, state->wbuf, state->lastchar);
if (!pass) if (!pass)
mutt_history_add (hclass, buf); mutt_history_add (hclass, buf, 1);
if (multiple) if (multiple)
{ {
......
...@@ -53,6 +53,7 @@ WHERE char *FolderFormat; ...@@ -53,6 +53,7 @@ WHERE char *FolderFormat;
WHERE char *ForwFmt; WHERE char *ForwFmt;
WHERE char *Fqdn; WHERE char *Fqdn;
WHERE char *HdrFmt; WHERE char *HdrFmt;
WHERE char *HistFile;
WHERE char *Homedir; WHERE char *Homedir;
WHERE char *Hostname; WHERE char *Hostname;
#ifdef USE_IMAP #ifdef USE_IMAP
...@@ -195,6 +196,7 @@ WHERE short MenuContext; ...@@ -195,6 +196,7 @@ WHERE short MenuContext;
WHERE short PagerContext; WHERE short PagerContext;
WHERE short PagerIndexLines; WHERE short PagerIndexLines;
WHERE short ReadInc; WHERE short ReadInc;
WHERE short SaveHist;
WHERE short SendmailWait; WHERE short SendmailWait;
WHERE short SleepTime INITVAL (1); WHERE short SleepTime INITVAL (1);
WHERE short Timeout; WHERE short Timeout;
......
...@@ -56,6 +56,145 @@ static void init_history (struct history *h) ...@@ -56,6 +56,145 @@ static void init_history (struct history *h)
h->last = 0; 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) void mutt_init_history(void)
{ {
history_class_t hclass; history_class_t hclass;
...@@ -69,7 +208,7 @@ void mutt_init_history(void) ...@@ -69,7 +208,7 @@ void mutt_init_history(void)
OldSize = HistSize; 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; int prev;
struct history *h = &History[hclass]; struct history *h = &History[hclass];
...@@ -88,6 +227,8 @@ void mutt_history_add (history_class_t hclass, const char *s) ...@@ -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 (*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); mutt_str_replace (&h->hist[h->last++], s);
if (h->last > HistSize - 1) if (h->last > HistSize - 1)
h->last = 0; h->last = 0;
......
...@@ -35,7 +35,8 @@ enum history_class ...@@ -35,7 +35,8 @@ enum history_class
typedef enum history_class history_class_t; typedef enum history_class history_class_t;
void mutt_init_history(void); 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_next(history_class_t);
char *mutt_history_prev(history_class_t); char *mutt_history_prev(history_class_t);
......
...@@ -3012,6 +3012,8 @@ void mutt_init (int skip_sys_rc, LIST *commands) ...@@ -3012,6 +3012,8 @@ void mutt_init (int skip_sys_rc, LIST *commands)
mutt_exit(1); mutt_exit(1);
} }
mutt_read_histfile ();
#if 0 #if 0
set_option (OPTWEED); /* turn weeding on by default */ set_option (OPTWEED); /* turn weeding on by default */
#endif #endif
......
...@@ -828,6 +828,11 @@ struct option_t MuttVars[] = { ...@@ -828,6 +828,11 @@ struct option_t MuttVars[] = {
** the string history buffer. The buffer is cleared each time the ** the string history buffer. The buffer is cleared each time the
** variable is set. ** 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 }, { "honor_followup_to", DT_QUAD, R_NONE, OPT_MFUPTO, M_YES },
/* /*
** .pp ** .pp
...@@ -2438,6 +2443,12 @@ struct option_t MuttVars[] = { ...@@ -2438,6 +2443,12 @@ struct option_t MuttVars[] = {
** \fBNote:\fP This only applies to mbox and MMDF folders, Mutt does not ** \fBNote:\fP This only applies to mbox and MMDF folders, Mutt does not
** delete MH and Maildir directories. ** 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 }, { "save_name", DT_BOOL, R_NONE, OPTSAVENAME, 0 },
/* /*
** .pp ** .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