From: Kevin McCarthy Date: Sun, 22 Apr 2018 20:02:06 +0000 (-0700) Subject: Add Error History function and config var. X-Git-Tag: mutt-1-10-rel~22 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=26b822025b258d99e05b6c236669847efe9b3dfb;p=mutt Add Error History function and config var. , 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. --- diff --git a/OPS b/OPS index f53cd63a..679f5dbd 100644 --- a/OPS +++ b/OPS @@ -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" diff --git a/curs_lib.c b/curs_lib.c index ecac6d95..eef8dd29 100644 --- a/curs_lib.c +++ b/curs_lib.c @@ -44,6 +44,16 @@ #include #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), diff --git a/curs_main.c b/curs_main.c index b2c18cad..09226113 100644 --- a/curs_main.c +++ b/curs_main.c @@ -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) diff --git a/functions.h b/functions.h index 2985c6eb..95d00d8b 100644 --- a/functions.h +++ b/functions.h @@ -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 }, diff --git a/globals.h b/globals.h index 14f37295..2aa96f90 100644 --- a/globals.h +++ b/globals.h @@ -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; diff --git a/init.c b/init.c index 535f371a..f5a89bff 100644 --- a/init.c +++ b/init.c @@ -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 diff --git a/init.h b/init.h index c86c4ae9..f5837be3 100644 --- a/init.h +++ b/init.h @@ -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\fP function. The history is cleared each + ** time this variable is set. + */ { "escape", DT_STR, R_NONE, UL &EscChar, UL "~" }, /* ** .pp diff --git a/menu.c b/menu.c index 8a6be010..dfd8fa75 100644 --- a/menu.c +++ b/menu.c @@ -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; diff --git a/pager.c b/pager.c index 7507ea26..69341d88 100644 --- a/pager.c +++ b/pager.c @@ -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) { diff --git a/protos.h b/protos.h index 0b37fc1e..8bcda67f 100644 --- a/protos.h +++ b/protos.h @@ -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 *);