mutt

changeset 4926:ae569572be53

Add $history_file and $save_history, for saving command history across
sessions.
author Vincent Lefevre <vincent@vinc17.org>
date Mon Feb 26 17:17:13 2007 +0000 (17 months ago)
parents f0843d6d08e3
children fc54342e8645
files UPDATING enter.c globals.h history.c history.h init.c init.h
line diff
1--- a/UPDATING Mon Feb 26 16:54:26 2007 +0000
2+++ b/UPDATING Mon Feb 26 17:17:13 2007 +0000
3@@ -4,6 +4,7 @@
4 The keys used are:
5 !: modified feature, -: deleted feature, +: new feature
6
7+ + $save_history, $history_file (save history across sessions)
8 + $assumed_charset, $file_charset, $strict_mime
9 + $smtp_url (ESMTP relay support)
10 + $crypt_use_pka (use GPGME PKA signature verification)
1.1--- a/enter.c Mon Feb 26 16:54:26 2007 +0000
1.2+++ b/enter.c Mon Feb 26 17:17:13 2007 +0000
1.3@@ -562,7 +562,7 @@
1.4 {
1.5 mutt_pretty_mailbox (buf);
1.6 if (!pass)
1.7- mutt_history_add (hclass, buf);
1.8+ mutt_history_add (hclass, buf, 1);
1.9 rv = 0;
1.10 goto bye;
1.11 }
1.12@@ -667,7 +667,7 @@
1.13 /* Convert from wide characters */
1.14 my_wcstombs (buf, buflen, state->wbuf, state->lastchar);
1.15 if (!pass)
1.16- mutt_history_add (hclass, buf);
1.17+ mutt_history_add (hclass, buf, 1);
1.18
1.19 if (multiple)
1.20 {
2.1--- a/globals.h Mon Feb 26 16:54:26 2007 +0000
2.2+++ b/globals.h Mon Feb 26 17:17:13 2007 +0000
2.3@@ -53,6 +53,7 @@
2.4 WHERE char *ForwFmt;
2.5 WHERE char *Fqdn;
2.6 WHERE char *HdrFmt;
2.7+WHERE char *HistFile;
2.8 WHERE char *Homedir;
2.9 WHERE char *Hostname;
2.10 #ifdef USE_IMAP
2.11@@ -195,6 +196,7 @@
2.12 WHERE short PagerContext;
2.13 WHERE short PagerIndexLines;
2.14 WHERE short ReadInc;
2.15+WHERE short SaveHist;
2.16 WHERE short SendmailWait;
2.17 WHERE short SleepTime INITVAL (1);
2.18 WHERE short Timeout;
3.1--- a/history.c Mon Feb 26 16:54:26 2007 +0000
3.2+++ b/history.c Mon Feb 26 17:17:13 2007 +0000
3.3@@ -56,6 +56,145 @@
3.4 h->last = 0;
3.5 }
3.6
3.7+void mutt_read_histfile (void)
3.8+{
3.9+ FILE *f;
3.10+ int line = 0, hclass, read;
3.11+ char *linebuf = NULL, *p;
3.12+ size_t buflen;
3.13+
3.14+ if ((f = fopen (HistFile, "r")) == NULL)
3.15+ return;
3.16+
3.17+ while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL)
3.18+ {
3.19+ read = 0;
3.20+ if (sscanf (linebuf, "%d:%n", &hclass, &read) < 1 || read == 0 ||
3.21+ *(p = linebuf + strlen (linebuf) - 1) != '|')
3.22+ {
3.23+ mutt_error (_("Bad history file format (line %d)"), line);
3.24+ break;
3.25+ }
3.26+ *p = '\0';
3.27+ p = safe_strdup (linebuf + read);
3.28+ if (p)
3.29+ {
3.30+ mutt_convert_string (&p, "utf-8", Charset, 0);
3.31+ mutt_history_add (hclass, p, 0);
3.32+ FREE (&p);
3.33+ }
3.34+ }
3.35+
3.36+ fclose (f);
3.37+ FREE (&linebuf);
3.38+}
3.39+
3.40+static void shrink_histfile (void)
3.41+{
3.42+ char tmpfname[_POSIX_PATH_MAX];
3.43+ FILE *f, *tmp = NULL;
3.44+ int n[HC_LAST] = { 0 };
3.45+ int line, hclass;
3.46+ char *linebuf = NULL;
3.47+ size_t buflen;
3.48+
3.49+ if ((f = fopen (HistFile, "r")) == NULL)
3.50+ return;
3.51+
3.52+ line = 0;
3.53+ while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL)
3.54+ {
3.55+ if (sscanf (linebuf, "%d", &hclass) < 1)
3.56+ {
3.57+ mutt_error (_("Bad history file format (line %d)"), line);
3.58+ goto cleanup;
3.59+ }
3.60+ n[hclass]++;
3.61+ }
3.62+
3.63+ for(hclass = HC_FIRST; hclass < HC_LAST; hclass++)
3.64+ if (n[hclass] > SaveHist)
3.65+ {
3.66+ mutt_mktemp (tmpfname);
3.67+ if ((tmp = safe_fopen (tmpfname, "w+")) == NULL)
3.68+ mutt_perror (tmpfname);
3.69+ break;
3.70+ }
3.71+
3.72+ if (tmp != NULL)
3.73+ {
3.74+ rewind (f);
3.75+ line = 0;
3.76+ while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL)
3.77+ {
3.78+ if (sscanf (linebuf, "%d", &hclass) < 1)
3.79+ {
3.80+ mutt_error (_("Bad history file format (line %d)"), line);
3.81+ goto cleanup;
3.82+ }
3.83+ if (n[hclass]-- <= SaveHist)
3.84+ fprintf (tmp, "%s\n", linebuf);
3.85+ }
3.86+ }
3.87+
3.88+cleanup:
3.89+ fclose (f);
3.90+ FREE (&linebuf);
3.91+ if (tmp != NULL)
3.92+ {
3.93+ if (fflush (tmp) == 0 &&
3.94+ (f = fopen (HistFile, "w")) != NULL) /* __FOPEN_CHECKED__ */
3.95+ {
3.96+ rewind (tmp);
3.97+ mutt_copy_stream (tmp, f);
3.98+ fclose (f);
3.99+ }
3.100+ fclose (tmp);
3.101+ unlink (tmpfname);
3.102+ }
3.103+}
3.104+
3.105+static void save_history (history_class_t hclass, const char *s)
3.106+{
3.107+ static int n = 0;
3.108+ FILE *f;
3.109+ char *tmp, *p;
3.110+
3.111+ if (!s || !*s) /* This shouldn't happen, but it's safer. */
3.112+ return;
3.113+
3.114+ if ((f = fopen (HistFile, "a")) == NULL)
3.115+ {
3.116+ mutt_perror ("fopen");
3.117+ return;
3.118+ }
3.119+
3.120+ tmp = safe_strdup (s);
3.121+ mutt_convert_string (&tmp, Charset, "utf-8", 0);
3.122+
3.123+ /* Format of a history item (1 line): "<histclass>:<string>|".
3.124+ We add a '|' in order to avoid lines ending with '\'. */
3.125+ fprintf (f, "%d:", (int) hclass);
3.126+ for (p = tmp; *p; p++)
3.127+ {
3.128+ /* Don't copy \n as a history item must fit on one line. The string
3.129+ shouldn't contain such a character anyway, but as this can happen
3.130+ in practice, we must deal with that. */
3.131+ if (*p != '\n')
3.132+ putc ((unsigned char) *p, f);
3.133+ }
3.134+ fputs ("|\n", f);
3.135+
3.136+ fclose (f);
3.137+ FREE (&tmp);
3.138+
3.139+ if (--n < 0)
3.140+ {
3.141+ n = SaveHist;
3.142+ shrink_histfile();
3.143+ }
3.144+}
3.145+
3.146 void mutt_init_history(void)
3.147 {
3.148 history_class_t hclass;
3.149@@ -69,7 +208,7 @@
3.150 OldSize = HistSize;
3.151 }
3.152
3.153-void mutt_history_add (history_class_t hclass, const char *s)
3.154+void mutt_history_add (history_class_t hclass, const char *s, int save)
3.155 {
3.156 int prev;
3.157 struct history *h = &History[hclass];
3.158@@ -88,6 +227,8 @@
3.159 */
3.160 if (*s != ' ' && (!h->hist[prev] || mutt_strcmp (h->hist[prev], s) != 0))
3.161 {
3.162+ if (save && SaveHist)
3.163+ save_history (hclass, s);
3.164 mutt_str_replace (&h->hist[h->last++], s);
3.165 if (h->last > HistSize - 1)
3.166 h->last = 0;
4.1--- a/history.h Mon Feb 26 16:54:26 2007 +0000
4.2+++ b/history.h Mon Feb 26 17:17:13 2007 +0000
4.3@@ -35,7 +35,8 @@
4.4 typedef enum history_class history_class_t;
4.5
4.6 void mutt_init_history(void);
4.7-void mutt_history_add(history_class_t, const char *);
4.8+void mutt_read_histfile(void);
4.9+void mutt_history_add(history_class_t, const char *, int);
4.10 char *mutt_history_next(history_class_t);
4.11 char *mutt_history_prev(history_class_t);
4.12
5.1--- a/init.c Mon Feb 26 16:54:26 2007 +0000
5.2+++ b/init.c Mon Feb 26 17:17:13 2007 +0000
5.3@@ -3012,6 +3012,8 @@
5.4 mutt_exit(1);
5.5 }
5.6
5.7+ mutt_read_histfile ();
5.8+
5.9 #if 0
5.10 set_option (OPTWEED); /* turn weeding on by default */
5.11 #endif
6.1--- a/init.h Mon Feb 26 16:54:26 2007 +0000
6.2+++ b/init.h Mon Feb 26 17:17:13 2007 +0000
6.3@@ -828,6 +828,11 @@
6.4 ** the string history buffer. The buffer is cleared each time the
6.5 ** variable is set.
6.6 */
6.7+ { "history_file", DT_PATH, R_NONE, UL &HistFile, UL "~/.mutthistory" },
6.8+ /*
6.9+ ** .pp
6.10+ ** The file in which Mutt will save its history.
6.11+ */
6.12 { "honor_followup_to", DT_QUAD, R_NONE, OPT_MFUPTO, M_YES },
6.13 /*
6.14 ** .pp
6.15@@ -2438,6 +2443,12 @@
6.16 ** \fBNote:\fP This only applies to mbox and MMDF folders, Mutt does not
6.17 ** delete MH and Maildir directories.
6.18 */
6.19+ { "save_history", DT_NUM, R_NONE, UL &SaveHist, 0 },
6.20+ /*
6.21+ ** .pp
6.22+ ** This variable controls the size of the history saved in the
6.23+ ** ``$$history_file'' file.
6.24+ */
6.25 { "save_name", DT_BOOL, R_NONE, OPTSAVENAME, 0 },
6.26 /*
6.27 ** .pp