Commit 26b82202 authored by Kevin J. McCarthy's avatar Kevin J. McCarthy

Add Error History function and config var.

<error-history>, by default unbound, shows a list of the recent error
messages displayed by Mutt via mutt_message() or mutt_error().

$error_history sets the size of the history ring.

For now, I've decided to include mutt_message() messages too.  If this
is too chatty, we can restrict it to mutt_error() easily in the
future.
parent f2e8392f
Pipeline #20903945 passed with stages
in 27 minutes and 47 seconds
......@@ -84,6 +84,7 @@ OP_EDITOR_DOWNCASE_WORD "convert the word to lower case"
OP_EDITOR_UPCASE_WORD "convert the word to upper case"
OP_ENTER_COMMAND "enter a muttrc command"
OP_ENTER_MASK "enter a file mask"
OP_ERROR_HISTORY "display recent history of error messages"
OP_EXIT "exit this menu"
OP_FILTER "filter attachment through a shell command"
OP_FIRST_ENTRY "move to the first entry"
......
......@@ -44,6 +44,16 @@
#include <langinfo.h>
#endif
/* Error message ring */
struct error_history
{
char **msg;
short last;
} ErrorHistory = {0, 0};
static short OldErrorHistSize = 0;
/* not possible to unget more than one char under some curses libs, and it
* is impossible to unget function keys in SLang, so roll our own input
* buffering routines.
......@@ -63,6 +73,7 @@ static size_t UngetCount = 0;
static size_t UngetLen = 0;
static event_t *UngetKeyEvents;
mutt_window_t *MuttHelpWindow = NULL;
mutt_window_t *MuttIndexWindow = NULL;
mutt_window_t *MuttStatusWindow = NULL;
......@@ -392,11 +403,94 @@ void mutt_query_exit (void)
SigInt = 0;
}
void mutt_error_history_init (void)
{
short i;
if (OldErrorHistSize && ErrorHistory.msg)
{
for (i = 0; i < OldErrorHistSize; i++)
FREE (&ErrorHistory.msg[i]);
FREE (&ErrorHistory.msg);
}
if (ErrorHistSize)
ErrorHistory.msg = safe_calloc (ErrorHistSize, sizeof (char *));
ErrorHistory.last = 0;
OldErrorHistSize = ErrorHistSize;
}
static void error_history_add (const char *s)
{
static int in_process = 0;
if (!ErrorHistSize || in_process || !s || !*s)
return;
in_process = 1;
mutt_str_replace (&ErrorHistory.msg[ErrorHistory.last], s);
if (++ErrorHistory.last >= ErrorHistSize)
ErrorHistory.last = 0;
in_process = 0;
}
static void error_history_dump (FILE *f)
{
short cur;
cur = ErrorHistory.last;
do
{
if (ErrorHistory.msg[cur])
{
fputs (ErrorHistory.msg[cur], f);
fputc ('\n', f);
}
if (++cur >= ErrorHistSize)
cur = 0;
} while (cur != ErrorHistory.last);
}
void mutt_error_history_display ()
{
static int in_process = 0;
char t[_POSIX_PATH_MAX];
FILE *f;
if (!ErrorHistSize)
{
mutt_error _("Error History is disabled.");
return;
}
if (in_process)
{
mutt_error _("Error History is currently being shown.");
return;
}
mutt_mktemp (t, sizeof (t));
if ((f = safe_fopen (t, "w")) == NULL)
{
mutt_perror (t);
return;
}
error_history_dump (f);
safe_fclose (&f);
in_process = 1;
mutt_do_pager (_("Error History"), t, 0, NULL);
in_process = 0;
}
static void curses_message (int error, const char *fmt, va_list ap)
{
char scratch[LONG_STRING];
vsnprintf (scratch, sizeof (scratch), fmt, ap);
error_history_add (scratch);
dprint (1, (debugfile, "%s\n", scratch));
mutt_format_string (Errorbuf, sizeof (Errorbuf),
......
......@@ -926,6 +926,12 @@ int mutt_index_menu (void)
menu->redraw = REDRAW_FULL;
break;
case OP_ERROR_HISTORY:
mutt_error_history_display ();
menu->redraw = REDRAW_FULL;
break;
case OP_MAIN_SHOW_LIMIT:
CHECK_IN_MAILBOX;
if (!Context->pattern)
......
......@@ -78,6 +78,7 @@ const struct binding_t OpGeneric[] = { /* map: generic */
{ "current-top", OP_CURRENT_TOP, NULL },
{ "current-middle", OP_CURRENT_MIDDLE, NULL },
{ "current-bottom", OP_CURRENT_BOTTOM, NULL },
{ "error-history", OP_ERROR_HISTORY, NULL },
{ "what-key", OP_WHAT_KEY, NULL },
{ NULL, 0, NULL }
};
......@@ -264,6 +265,7 @@ const struct binding_t OpPager[] = { /* map: pager */
{ "search-reverse", OP_SEARCH_REVERSE, "\033/" },
{ "search-opposite", OP_SEARCH_OPPOSITE, NULL },
{ "next-line", OP_NEXT_LINE, MUTT_ENTER_S },
{ "error-history", OP_ERROR_HISTORY, NULL },
{ "jump", OP_JUMP, NULL },
{ "next-unread", OP_MAIN_NEXT_UNREAD, NULL },
{ "previous-new", OP_MAIN_PREV_NEW, NULL },
......
......@@ -208,6 +208,7 @@ extern unsigned char QuadOptions[];
WHERE unsigned short Counter INITVAL (0);
WHERE short ConnectTimeout;
WHERE short ErrorHistSize;
WHERE short HistSize;
WHERE short MenuContext;
WHERE short PagerContext;
......
......@@ -2451,6 +2451,12 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err)
*ptr = 0;
mutt_init_history ();
}
else if (mutt_strcmp (MuttVars[idx].option, "error_history") == 0)
{
if (*ptr < 0)
*ptr = 0;
mutt_error_history_init ();
}
else if (mutt_strcmp (MuttVars[idx].option, "pager_index_lines") == 0)
{
if (*ptr < 0)
......@@ -3505,6 +3511,7 @@ void mutt_init (int skip_sys_rc, LIST *commands)
#endif
mutt_init_history ();
mutt_error_history_init ();
/* RFC2368, "4. Unsafe headers"
* The creator of a mailto URL cannot expect the resolver of a URL to
......
......@@ -818,6 +818,14 @@ struct option_t MuttVars[] = {
** Manually sets the \fIenvelope\fP sender for outgoing messages.
** This value is ignored if $$use_envelope_from is \fIunset\fP.
*/
{ "error_history", DT_NUM, R_NONE, UL &ErrorHistSize, 30 },
/*
** .pp
** This variable controls the size (in number of strings remembered)
** of the error messages displayed by mutt. These can be shown with
** the \fC<error-history>\fP function. The history is cleared each
** time this variable is set.
*/
{ "escape", DT_STR, R_NONE, UL &EscChar, UL "~" },
/*
** .pp
......
......@@ -1202,6 +1202,11 @@ int mutt_menuLoop (MUTTMENU *menu)
menu->redraw = REDRAW_FULL;
break;
case OP_ERROR_HISTORY:
mutt_error_history_display ();
menu->redraw = REDRAW_FULL;
break;
case OP_NULL:
km_error_key (menu->menu);
break;
......
......@@ -2381,6 +2381,11 @@ search_next:
mutt_error _("Help is currently being shown.");
break;
case OP_ERROR_HISTORY:
mutt_error_history_display ();
pager_menu->redraw = REDRAW_FULL;
break;
case OP_PAGER_HIDE_QUOTED:
if (rd.has_types)
{
......
......@@ -198,6 +198,8 @@ void mutt_curses_message (const char *, ...);
void mutt_encode_descriptions (BODY *, short);
void mutt_encode_path (char *, size_t, const char *);
void mutt_enter_command (void);
void mutt_error_history_display (void);
void mutt_error_history_init (void);
void mutt_expand_aliases_env (ENVELOPE *);
void mutt_expand_file_fmt (char *, size_t, const char *, const char *);
void mutt_expand_fmt (char *, size_t, const char *, const char *);
......
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