From: Richard Russon Date: Mon, 23 May 2016 12:31:45 +0000 (+0100) Subject: merge: nntp X-Git-Tag: neomutt-20160530~8 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2b103097596aeaa0b342d31a29dd232282431f28;p=neomutt merge: nntp * feature: nntp * add docs * add ident to PATCHES * doc: check for installed patches --- 2b103097596aeaa0b342d31a29dd232282431f28 diff --cc PATCHES index b1b888298,93fd79aff..e44c30ee9 --- a/PATCHES +++ b/PATCHES @@@ -1,16 -1,1 +1,17 @@@ +patch-quasi-delete-neo-UNKNOWN +patch-progress-neo-UNKNOWN +patch-status-color-neo-UNKNOWN +patch-index-color-neo-UNKNOWN +patch-nested-if-neo-UNKNOWN +patch-cond-date-neo-UNKNOWN +patch-tls-sni-neo-UNKNOWN +patch-sidebar-neo-UNKNOWN +patch-ifdef-neo-UNKNOWN +patch-fmemopen-neo-UNKNOWN +patch-initials-neo-UNKNOWN +patch-trash-neo-UNKNOWN +patch-limit-current-thread-neo-UNKNOWN +patch-skip-quoted-neo-UNKNOWN +patch-compress-neo-UNKNOWN +patch-keywords-neo-UNKNOWN + patch-nntp-neo-UNKNOWN diff --cc browser.c index 2617c380c,cb5968a2e..a5ed4ef42 --- a/browser.c +++ b/browser.c @@@ -33,9 -32,9 +33,12 @@@ #ifdef USE_IMAP #include "imap.h" #endif +#ifdef USE_NOTMUCH +#include "mutt_notmuch.h" +#endif + #ifdef USE_NNTP + #include "nntp.h" + #endif #include #include @@@ -152,17 -138,12 +172,21 @@@ static void browser_sort (struct browse f = browser_compare_date; break; case SORT_SIZE: + #ifdef USE_NNTP + if (option (OPTNEWS)) + return; + #endif f = browser_compare_size; break; + case SORT_DESC: + f = browser_compare_desc; + break; + case SORT_COUNT: + f = browser_compare_count; + break; + case SORT_COUNT_NEW: + f = browser_compare_count_new; + break; case SORT_SUBJECT: default: f = browser_compare_subject; @@@ -394,9 -348,112 +418,112 @@@ folder_format_str (char *dest, size_t d return (src); } + #ifdef USE_NNTP + static const char * + newsgroup_format_str (char *dest, size_t destlen, size_t col, char op, const char *src, + const char *fmt, const char *ifstring, const char *elsestring, + unsigned long data, format_flag flags) + { + char fn[SHORT_STRING], tmp[SHORT_STRING]; + FOLDER *folder = (FOLDER *) data; + + switch (op) + { + case 'C': + snprintf (tmp, sizeof (tmp), "%%%sd", fmt); + snprintf (dest, destlen, tmp, folder->num + 1); + break; + + case 'f': + strncpy (fn, folder->ff->name, sizeof(fn) - 1); + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, fn); + break; + + case 'N': + snprintf (tmp, sizeof (tmp), "%%%sc", fmt); + if (folder->ff->nd->subscribed) + snprintf (dest, destlen, tmp, ' '); + else + snprintf (dest, destlen, tmp, folder->ff->new ? 'N' : 'u'); + break; + + case 'M': + snprintf (tmp, sizeof (tmp), "%%%sc", fmt); + if (folder->ff->nd->deleted) + snprintf (dest, destlen, tmp, 'D'); + else + snprintf (dest, destlen, tmp, folder->ff->nd->allowed ? ' ' : '-'); + break; + + case 's': + if (flags & M_FORMAT_OPTIONAL) + { + if (folder->ff->nd->unread != 0) + mutt_FormatString (dest, destlen, col, ifstring, newsgroup_format_str, + data, flags); + else + mutt_FormatString (dest, destlen, col, elsestring, newsgroup_format_str, + data, flags); + } + else if (Context && Context->data == folder->ff->nd) + { + snprintf (tmp, sizeof (tmp), "%%%sd", fmt); + snprintf (dest, destlen, tmp, Context->unread); + } + else + { + snprintf (tmp, sizeof (tmp), "%%%sd", fmt); + snprintf (dest, destlen, tmp, folder->ff->nd->unread); + } + break; + + case 'n': + if (Context && Context->data == folder->ff->nd) + { + snprintf (tmp, sizeof (tmp), "%%%sd", fmt); + snprintf (dest, destlen, tmp, Context->new); + } + else if (option (OPTMARKOLD) && + folder->ff->nd->lastCached >= folder->ff->nd->firstMessage && + folder->ff->nd->lastCached <= folder->ff->nd->lastMessage) + { + snprintf (tmp, sizeof (tmp), "%%%sd", fmt); + snprintf (dest, destlen, tmp, folder->ff->nd->lastMessage - folder->ff->nd->lastCached); + } + else + { + snprintf (tmp, sizeof (tmp), "%%%sd", fmt); + snprintf (dest, destlen, tmp, folder->ff->nd->unread); + } + break; + + case 'd': + if (folder->ff->nd->desc != NULL) + { + char *buf = safe_strdup (folder->ff->nd->desc); + if (NewsgroupsCharset && *NewsgroupsCharset) + mutt_convert_string (&buf, NewsgroupsCharset, Charset, M_ICONV_HOOK_FROM); + mutt_filter_unprintable (&buf); + + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, buf); + FREE (&buf); + } + else + { + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, ""); + } + break; + } + return (src); + } + #endif /* USE_NNTP */ + static void add_folder (MUTTMENU *m, struct browser_state *state, - const char *name, const char *desc, - const struct stat *s, unsigned int new, unsigned int all) - const char *name, const struct stat *s, - void *data, unsigned int new) ++ const char *name, const char *desc, const struct stat *s, ++ unsigned int new, unsigned int all, void *data) { if (state->entrylen == state->entrymax) { @@@ -420,11 -477,14 +547,15 @@@ } (state->entry)[state->entrylen].new = new; + (state->entry)[state->entrylen].all = all; (state->entry)[state->entrylen].name = safe_strdup (name); - (state->entry)[state->entrylen].desc = safe_strdup (name); + (state->entry)[state->entrylen].desc = safe_strdup(desc ? desc : name); #ifdef USE_IMAP (state->entry)[state->entrylen].imap = 0; + #endif + #ifdef USE_NNTP + if (option (OPTNEWS)) + (state->entry)[state->entrylen].nd = (NNTP_DATA *)data; #endif (state->entrylen)++; } @@@ -444,6 -505,32 +576,31 @@@ static void init_state (struct browser_ static int examine_directory (MUTTMENU *menu, struct browser_state *state, char *d, const char *prefix) { + #ifdef USE_NNTP + if (option (OPTNEWS)) + { + NNTP_SERVER *nserv = CurrentNewsSrv; + unsigned int i; + + /* mutt_buffy_check (0); */ + init_state (state, menu); + + for (i = 0; i < nserv->groups_num; i++) + { + NNTP_DATA *nntp_data = nserv->groups_list[i]; + if (!nntp_data) + continue; + if (prefix && *prefix && + strncmp (prefix, nntp_data->group, strlen (prefix))) + continue; + if (!((regexec (Mask.rx, nntp_data->group, 0, NULL, 0) == 0) ^ Mask.not)) + continue; - add_folder (menu, state, nntp_data->group, NULL, - nntp_data, nntp_data->new); ++ add_folder (menu, state, nntp_data->group, NULL, NULL, nntp_data->new, nntp_data->newsrc_len, nntp_data); + } + } + else + #endif /* USE_NNTP */ + { struct stat s; DIR *dp; struct dirent *de; @@@ -504,44 -591,41 +661,66 @@@ tmp = Incoming; while (tmp && mutt_strcmp (buffer, tmp->path)) tmp = tmp->next; - add_folder (menu, state, de->d_name, NULL, &s, (tmp) ? tmp->new : 0, 0); - add_folder (menu, state, de->d_name, &s, NULL, (tmp) ? tmp->new : 0); ++ add_folder (menu, state, de->d_name, NULL, &s, (tmp) ? tmp->new : 0, (tmp) ? tmp->msg_count : 0, NULL); } closedir (dp); + } browser_sort (state); return 0; } +#ifdef USE_NOTMUCH +static int examine_vfolders (MUTTMENU *menu, struct browser_state *state) +{ + BUFFY *tmp = VirtIncoming; + + if (!VirtIncoming) + return (-1); + mutt_buffy_check (0); + + init_state (state, menu); + + do + { + if (mx_is_notmuch (tmp->path)) + { + nm_nonctx_get_count(tmp->path, &tmp->msg_count, &tmp->msg_unread); - add_folder (menu, state, tmp->path, tmp->desc, NULL, - tmp->msg_unread, tmp->msg_count); ++ add_folder (menu, state, tmp->path, tmp->desc, NULL, tmp->msg_unread, tmp->msg_count, NULL); + continue; + } + } + while ((tmp = tmp->next)); + browser_sort (state); + return 0; +} +#endif + + /* get list of mailboxes/subscribed newsgroups */ static int examine_mailboxes (MUTTMENU *menu, struct browser_state *state) { struct stat s; char buffer[LONG_STRING]; + + #ifdef USE_NNTP + if (option (OPTNEWS)) + { + NNTP_SERVER *nserv = CurrentNewsSrv; + unsigned int i; + + /* mutt_buffy_check (0); */ + init_state (state, menu); + + for (i = 0; i < nserv->groups_num; i++) + { + NNTP_DATA *nntp_data = nserv->groups_list[i]; + if (nntp_data && (nntp_data->new || (nntp_data->subscribed && + (nntp_data->unread || !option (OPTSHOWONLYUNREAD))))) - add_folder (menu, state, nntp_data->group, NULL, - nntp_data, nntp_data->new); ++ add_folder (menu, state, nntp_data->group, NULL, NULL, nntp_data->new, nntp_data->newsrc_len, nntp_data); + } + } + else + #endif + { BUFFY *tmp = Incoming; #ifdef USE_IMAP struct mailbox_state mbox; @@@ -559,14 -643,21 +738,21 @@@ if (mx_is_imap (tmp->path)) { imap_mailbox_state (tmp->path, &mbox); - add_folder (menu, state, tmp->path, NULL, NULL, mbox.new, mbox.messages); - add_folder (menu, state, tmp->path, NULL, NULL, mbox.new); ++ add_folder (menu, state, tmp->path, NULL, NULL, mbox.new, mbox.messages, NULL); continue; } #endif #ifdef USE_POP if (mx_is_pop (tmp->path)) { - add_folder (menu, state, tmp->path, NULL, NULL, tmp->new, 0); - add_folder (menu, state, tmp->path, NULL, NULL, tmp->new); ++ add_folder (menu, state, tmp->path, NULL, NULL, tmp->new, tmp->msg_count, NULL); + continue; + } + #endif + #ifdef USE_NNTP + if (mx_is_nntp (tmp->path)) + { - add_folder (menu, state, tmp->path, NULL, NULL, tmp->new); ++ add_folder (menu, state, tmp->path, NULL, NULL, tmp->new, tmp->msg_count, NULL); continue; } #endif @@@ -595,9 -686,10 +781,10 @@@ strfcpy (buffer, NONULL(tmp->path), sizeof (buffer)); mutt_pretty_mailbox (buffer, sizeof (buffer)); - add_folder (menu, state, buffer, NULL, &s, tmp->new, 0); - add_folder (menu, state, buffer, &s, NULL, tmp->new); ++ add_folder (menu, state, buffer, NULL, &s, tmp->new, tmp->msg_count, NULL); } while ((tmp = tmp->next)); + } browser_sort (state); return 0; } @@@ -814,15 -922,10 +1047,18 @@@ void _mutt_select_file (char *f, size_ if (multiple) menu->tag = file_tag; +#ifdef USE_NOTMUCH + if (flags & M_SEL_VFOLDER) { + menu->make_entry = vfolder_entry; + menu->search = select_vfolder_search; + } else +#endif + menu->make_entry = folder_entry; + menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_FOLDER, + #ifdef USE_NNTP + option (OPTNEWS) ? FolderNewsHelp : + #endif FolderHelp); init_menu (&state, menu, title, sizeof (title), buffy); @@@ -1128,9 -1223,14 +1360,14 @@@ } break; #endif - + case OP_CHANGE_DIRECTORY: + #ifdef USE_NNTP + if (option (OPTNEWS)) + break; + #endif + strfcpy (buf, LastDir, sizeof (buf)); #ifdef USE_IMAP if (!state.imap_browse) @@@ -1408,6 -1496,210 +1645,209 @@@ else mutt_error _("Error trying to view file"); } + break; + + #ifdef USE_NNTP + case OP_CATCHUP: + case OP_UNCATCHUP: + if (option (OPTNEWS)) + { + struct folder_file *f = &state.entry[menu->current]; + int rc; + NNTP_DATA *nntp_data; + + rc = nntp_newsrc_parse (CurrentNewsSrv); + if (rc < 0) + break; + + if (i == OP_CATCHUP) + nntp_data = mutt_newsgroup_catchup (CurrentNewsSrv, f->name); + else + nntp_data = mutt_newsgroup_uncatchup (CurrentNewsSrv, f->name); + + if (nntp_data) + { + /* FOLDER folder; + struct folder_file ff; + char buffer[_POSIX_PATH_MAX + SHORT_STRING]; + + folder.ff = &ff; + folder.ff->name = f->name; + folder.ff->st = NULL; + folder.ff->is_new = nntp_data->new; + folder.ff->nntp_data = nntp_data; + FREE (&f->desc); + mutt_FormatString (buffer, sizeof (buffer), 0, NONULL(GroupFormat), + newsgroup_format_str, (unsigned long) &folder, + M_FORMAT_ARROWCURSOR); + f->desc = safe_strdup (buffer); */ + nntp_newsrc_update (CurrentNewsSrv); + if (menu->current + 1 < menu->max) + menu->current++; + menu->redraw = REDRAW_MOTION_RESYNCH; + } + if (rc) + menu->redraw = REDRAW_INDEX; + nntp_newsrc_close (CurrentNewsSrv); + } + break; + + case OP_LOAD_ACTIVE: + if (option (OPTNEWS)) + { + NNTP_SERVER *nserv = CurrentNewsSrv; + unsigned int i; + + if (nntp_newsrc_parse (nserv) < 0) + break; + + for (i = 0; i < nserv->groups_num; i++) + { + NNTP_DATA *nntp_data = nserv->groups_list[i]; + if (nntp_data) + nntp_data->deleted = 1; + } + nntp_active_fetch (nserv); + nntp_newsrc_update (nserv); + nntp_newsrc_close (nserv); + + destroy_state (&state); + if (buffy) + examine_mailboxes (menu, &state); + else + examine_directory (menu, &state, NULL, NULL); + init_menu (&state, menu, title, sizeof (title), buffy); + } + break; + #endif /* USE_NNTP */ + + #if defined USE_IMAP || defined USE_NNTP + case OP_BROWSER_SUBSCRIBE: + case OP_BROWSER_UNSUBSCRIBE: + #endif + #ifdef USE_NNTP + case OP_SUBSCRIBE_PATTERN: + case OP_UNSUBSCRIBE_PATTERN: + if (option (OPTNEWS)) + { + NNTP_SERVER *nserv = CurrentNewsSrv; + NNTP_DATA *nntp_data; + regex_t *rx = (regex_t *) safe_malloc (sizeof (regex_t)); + char *s = buf; + int rc, j = menu->current; + + if (i == OP_SUBSCRIBE_PATTERN || i == OP_UNSUBSCRIBE_PATTERN) + { + char tmp[STRING]; + int err; + + buf[0] = 0; + if (i == OP_SUBSCRIBE_PATTERN) + snprintf (tmp, sizeof (tmp), _("Subscribe pattern: ")); + else + snprintf (tmp, sizeof (tmp), _("Unsubscribe pattern: ")); + if (mutt_get_field (tmp, buf, sizeof (buf), 0) != 0 || !buf[0]) + { + FREE (&rx); + break; + } + + err = REGCOMP (rx, s, REG_NOSUB); + if (err) + { + regerror (err, rx, buf, sizeof (buf)); + regfree (rx); + FREE (&rx); + mutt_error ("%s", buf); + break; + } + menu->redraw = REDRAW_FULL; + j = 0; + } + else if (!state.entrylen) + { + mutt_error _("No newsgroups match the mask"); + break; + } + + rc = nntp_newsrc_parse (nserv); + if (rc < 0) + break; + + for ( ; j < state.entrylen; j++) + { + struct folder_file *f = &state.entry[j]; + + if (i == OP_BROWSER_SUBSCRIBE || i == OP_BROWSER_UNSUBSCRIBE || + regexec (rx, f->name, 0, NULL, 0) == 0) + { + if (i == OP_BROWSER_SUBSCRIBE || i == OP_SUBSCRIBE_PATTERN) + nntp_data = mutt_newsgroup_subscribe (nserv, f->name); + else + nntp_data = mutt_newsgroup_unsubscribe (nserv, f->name); + /* if (nntp_data) + { + FOLDER folder; + char buffer[_POSIX_PATH_MAX + SHORT_STRING]; + + folder.name = f->name; + folder.f = NULL; + folder.new = nntp_data->new; + folder.nd = nntp_data; + FREE (&f->desc); + mutt_FormatString (buffer, sizeof (buffer), 0, NONULL(GroupFormat), + newsgroup_format_str, (unsigned long) &folder, + M_FORMAT_ARROWCURSOR); + f->desc = safe_strdup (buffer); + } */ + } + if (i == OP_BROWSER_SUBSCRIBE || i == OP_BROWSER_UNSUBSCRIBE) + { + if (menu->current + 1 < menu->max) + menu->current++; + menu->redraw = REDRAW_MOTION_RESYNCH; + break; + } + } + if (i == OP_SUBSCRIBE_PATTERN) + { + unsigned int i; + + for (i = 0; nserv && i < nserv->groups_num; i++) + { + nntp_data = nserv->groups_list[i]; + if (nntp_data && nntp_data->group && !nntp_data->subscribed) + { + if (regexec (rx, nntp_data->group, 0, NULL, 0) == 0) + { + mutt_newsgroup_subscribe (nserv, nntp_data->group); - add_folder (menu, &state, nntp_data->group, NULL, - nntp_data, nntp_data->new); ++ add_folder (menu, &state, nntp_data->group, NULL, NULL, nntp_data->new, nntp_data->newsrc_len, nntp_data); + } + } + } + init_menu (&state, menu, title, sizeof (title), buffy); + } + if (rc > 0) + menu->redraw = REDRAW_FULL; + nntp_newsrc_update (nserv); + nntp_clear_cache (nserv); + nntp_newsrc_close (nserv); + if (i != OP_BROWSER_SUBSCRIBE && i != OP_BROWSER_UNSUBSCRIBE) + regfree (rx); + FREE (&rx); + } + #ifdef USE_IMAP + else + #endif /* USE_IMAP && USE_NNTP */ + #endif /* USE_NNTP */ + #ifdef USE_IMAP + { + if (i == OP_BROWSER_SUBSCRIBE) + imap_subscribe (state.entry[menu->current].name, 1); + else + imap_subscribe (state.entry[menu->current].name, 0); + } + #endif /* USE_IMAP */ } } diff --cc buffy.c index a2c7dd84b,3f4e01635..6befe6862 --- a/buffy.c +++ b/buffy.c @@@ -615,10 -441,10 +615,15 @@@ static void buffy_check(BUFFY *tmp, str tmp->magic = M_POP; else #endif +#ifdef USE_NOTMUCH + if (mx_is_notmuch (tmp->path)) + tmp->magic = M_NOTMUCH; + else ++#endif + #ifdef USE_NNTP + if ((tmp->magic == M_NNTP) || mx_is_nntp (tmp->path)) + tmp->magic = M_NNTP; + else #endif if (stat (tmp->path, &sb) != 0 || (S_ISREG(sb.st_mode) && sb.st_size == 0) || (!tmp->magic && (tmp->magic = mx_get_magic (tmp->path)) <= 0)) @@@ -635,9 -461,13 +640,13 @@@ /* check to see if the folder is the currently selected folder * before polling */ if (!Context || !Context->path || + #ifdef USE_NNTP + (( tmp->magic == M_IMAP || tmp->magic == M_POP || tmp->magic == M_NNTP ) + #else - (( tmp->magic == M_IMAP || tmp->magic == M_POP ) + (( tmp->magic == M_IMAP || tmp->magic == M_POP || tmp->magic == M_NOTMUCH) + #endif ? mutt_strcmp (tmp->path, Context->path) : - (sb.st_dev != contex_sb.st_dev || sb.st_ino != contex_sb.st_ino))) + (sb.st_dev != contex_sb->st_dev || sb.st_ino != contex_sb->st_ino))) { switch (tmp->magic) { @@@ -693,66 -496,7 +702,69 @@@ tmp->notified = 0; else if (!tmp->notified) BuffyNotify++; +} + +int mutt_buffy_check (int force) +{ + BUFFY *tmp; + struct stat contex_sb; + time_t t; + + contex_sb.st_dev=0; + contex_sb.st_ino=0; + +#ifdef USE_IMAP + /* update postponed count as well, on force */ + if (force) + mutt_update_num_postponed (); +#endif + + /* fastest return if there are no mailboxes */ +#ifdef USE_NOTMUCH + if (!Incoming && !VirtIncoming) + return 0; +#else + if (!Incoming) + return 0; +#endif + t = time (NULL); + if (!force && (t - BuffyTime < BuffyTimeout)) + return BuffyCount; + + BuffyTime = t; + BuffyCount = 0; + BuffyNotify = 0; + +#ifdef USE_IMAP + BuffyCount += imap_buffy_check (force); +#endif + + /* check device ID and serial number instead of comparing paths */ + if (!Context || Context->magic == M_IMAP || Context->magic == M_POP ++#ifdef USE_NNTP ++ || Context->magic == M_NNTP ++#endif + || stat (Context->path, &contex_sb) != 0) + { + contex_sb.st_dev=0; + contex_sb.st_ino=0; + } + +#ifdef USE_SIDEBAR + if (sb_should_refresh()) { + for (tmp = Incoming; tmp; tmp = tmp->next) + buffy_check(tmp, &contex_sb); + sb_set_update_time(); } +#else + for (tmp = Incoming; tmp; tmp = tmp->next) + buffy_check(tmp, &contex_sb); +#endif + +#ifdef USE_NOTMUCH + for (tmp = VirtIncoming; tmp; tmp = tmp->next) + buffy_check(tmp, &contex_sb); +#endif BuffyDoneTime = BuffyTime; return (BuffyCount); diff --cc compose.c index 82677e537,0ac05c630..c510ff5c0 --- a/compose.c +++ b/compose.c @@@ -32,9 -32,7 +32,10 @@@ #include "mailbox.h" #include "sort.h" #include "charset.h" +#ifdef USE_SIDEBAR +#include "sidebar.h" +#endif + #include "mx.h" #ifdef MIXMASTER #include "remailer.h" @@@ -73,9 -81,9 +84,9 @@@ enu HDR_ATTACH = (HDR_FCC + 5) /* where to start printing the attachments */ }; - #define HDR_XOFFSET 10 - #define TITLE_FMT "%10s" /* Used for Prompts, which are ASCII */ + #define HDR_XOFFSET 14 + #define TITLE_FMT "%14s" /* Used for Prompts, which are ASCII */ -#define W (COLS - HDR_XOFFSET) +#define W (COLS - HDR_XOFFSET - SidebarWidth) static const char * const Prompts[] = { @@@ -251,17 -290,33 +293,36 @@@ static void draw_envelope_addr (int lin static void draw_envelope (HEADER *msg, char *fcc) { +#ifdef USE_SIDEBAR + sb_draw(); +#endif draw_envelope_addr (HDR_FROM, msg->env->from); + #ifdef USE_NNTP + if (!option (OPTNEWSSEND)) + { + #endif draw_envelope_addr (HDR_TO, msg->env->to); draw_envelope_addr (HDR_CC, msg->env->cc); draw_envelope_addr (HDR_BCC, msg->env->bcc); + #ifdef USE_NNTP + } + else + { + mvprintw (HDR_TO, 0, TITLE_FMT , Prompts[HDR_NEWSGROUPS - 1]); + mutt_paddstr (W, NONULL (msg->env->newsgroups)); + mvprintw (HDR_CC, 0, TITLE_FMT , Prompts[HDR_FOLLOWUPTO - 1]); + mutt_paddstr (W, NONULL (msg->env->followup_to)); + if (option (OPTXCOMMENTTO)) + { + mvprintw (HDR_BCC, 0, TITLE_FMT , Prompts[HDR_XCOMMENTTO - 1]); + mutt_paddstr (W, NONULL (msg->env->x_comment_to)); + } + } + #endif - mvprintw (HDR_SUBJECT, 0, TITLE_FMT, Prompts[HDR_SUBJECT - 1]); + mvprintw (HDR_SUBJECT, SidebarWidth, TITLE_FMT, Prompts[HDR_SUBJECT - 1]); mutt_paddstr (W, NONULL (msg->env->subject)); draw_envelope_addr (HDR_REPLYTO, msg->env->reply_to); - mvprintw (HDR_FCC, 0, TITLE_FMT, Prompts[HDR_FCC - 1]); + mvprintw (HDR_FCC, SidebarWidth, TITLE_FMT, Prompts[HDR_FCC - 1]); mutt_paddstr (W, fcc); if (WithCrypto) diff --cc curs_main.c index 191668439,35f99c63a..4c70d5513 --- a/curs_main.c +++ b/curs_main.c @@@ -41,12 -37,12 +42,16 @@@ #include "imap_private.h" #endif +#ifdef USE_NOTMUCH +#include "mutt_notmuch.h" +#endif + #include "mutt_crypt.h" + #ifdef USE_NNTP + #include "nntp.h" + #endif + #include #include @@@ -488,186 -482,6 +493,192 @@@ static void resort_index (MUTTMENU *men menu->redraw = REDRAW_INDEX | REDRAW_STATUS; } +/** + * mutt_draw_statusline - XXX + */ +void +mutt_draw_statusline (int cols, char *inbuf) +{ + int i = 0; + int cnt = 0; + int last_color = 0; + int color = 0; + int offset = 0; + int found = 0; + int null_rx = 0; + char buf[2048]; + + struct line_t { + short chunks; + struct syntax_t { + int color; + int first; + int last; + } *syntax; + } lineInfo = { 0, NULL }; + + mutt_format_string (buf, sizeof (buf), cols, cols, 0, ' ', inbuf, mutt_strlen (inbuf), 0); + + lineInfo.syntax = safe_malloc (sizeof (struct syntax_t)); + lineInfo.syntax[0].first = -1; + lineInfo.syntax[0].last = -1; + lineInfo.syntax[0].color = ColorDefs[MT_COLOR_STATUS]; + lineInfo.chunks = 1; + + do { + found = 0; + null_rx = 0; + COLOR_LINE *color_line = ColorStatusList; + + if (!buf[offset]) + break; + + while (color_line) { + regmatch_t pmatch[color_line->match + 1]; + + if (regexec (&color_line->rx, buf + offset, color_line->match + 1, pmatch, (offset ? REG_NOTBOL : 0)) == 0) { + if (pmatch[color_line->match].rm_eo != pmatch[color_line->match].rm_so) { + if (!found) { + if (++(lineInfo.chunks) > 1) { + safe_realloc (&(lineInfo.syntax), (lineInfo.chunks) * sizeof (struct syntax_t)); + } + } + i = lineInfo.chunks - 1; + pmatch[color_line->match].rm_so += offset; + pmatch[color_line->match].rm_eo += offset; + if (!found || + (pmatch[color_line->match].rm_so < (lineInfo.syntax)[i].first) || + ((pmatch[color_line->match].rm_so == (lineInfo.syntax)[i].first) && + (pmatch[color_line->match].rm_eo > (lineInfo.syntax)[i].last))) { + (lineInfo.syntax)[i].color = color_line->pair; + (lineInfo.syntax)[i].first = pmatch[color_line->match].rm_so; + (lineInfo.syntax)[i].last = pmatch[color_line->match].rm_eo; + } + found = 1; + null_rx = 0; + } else { + null_rx = 1; /* empty regexp; don't add it, but keep looking */ + } + } + color_line = color_line->next; + } + + if (null_rx) + offset++; /* avoid degenerate cases */ + else + offset = (lineInfo.syntax)[i].last; + } while (found || null_rx); + + for (cnt = 0; cnt < mutt_strlen (buf); cnt++) { + color = lineInfo.syntax[0].color; + for (i = 0; i < lineInfo.chunks; i++) { + /* we assume the chunks are sorted */ + if (cnt > (lineInfo.syntax)[i].last) + continue; + if (cnt < (lineInfo.syntax)[i].first) + break; + if (cnt != (lineInfo.syntax)[i].last) { + color = (lineInfo.syntax)[i].color; + break; + } + /* don't break here, as cnt might be in the next chunk as well */ + } + if (color != last_color) { + attrset (color); + last_color = color; + } + /* XXX more than one char at a time? */ + addch ((unsigned char)buf[cnt]); +#if 0 + waddnstr (stdscr, tgbuf, 10); + SETCOLOR (MT_COLOR_NORMAL); + waddnstr (stdscr, tgbuf + 10, -1); +#endif + } + + safe_free (&lineInfo.syntax); +} + +static int main_change_folder(MUTTMENU *menu, int op, char *buf, size_t bufsz, - int *oldcount, int *index_hint) ++ int *oldcount, int *index_hint, int flags) +{ ++#ifdef USE_NNTP ++ if (option (OPTNEWS)) ++ { ++ unset_option (OPTNEWS); ++ nntp_expand_path (buf, bufsz, &CurrentNewsSrv->conn->account); ++ } ++ else ++#endif + mutt_expand_path (buf, bufsz); +#ifdef USE_SIDEBAR + sb_set_open_buffy (buf); +#endif + if (mx_get_magic (buf) <= 0) + { + mutt_error (_("%s is not a mailbox."), buf); + return -1; + } + mutt_str_replace (&CurrentFolder, buf); + + /* keepalive failure in mutt_enter_fname may kill connection. #3028 */ + if (Context && !Context->path) + FREE (&Context); + + if (Context) + { + int check; + +#ifdef USE_COMPRESSED + if (Context->compress_info && Context->realpath) + mutt_str_replace (&LastFolder, Context->realpath); + else +#endif + mutt_str_replace (&LastFolder, Context->path); + *oldcount = Context ? Context->msgcount : 0; + + if ((check = mx_close_mailbox (Context, index_hint)) != 0) + { + if (check == M_NEW_MAIL || check == M_REOPENED) + update_index (menu, Context, check, *oldcount, *index_hint); + + set_option (OPTSEARCHINVALID); + menu->redraw = REDRAW_INDEX | REDRAW_STATUS; + return 0; + } + FREE (&Context); + } + + if (Labels) + hash_destroy(&Labels, NULL); + + mutt_sleep (0); + + /* Set CurrentMenu to MENU_MAIN before executing any folder + * hooks so that all the index menu functions are available to + * the exec command. + */ + + CurrentMenu = MENU_MAIN; + mutt_folder_hook (buf); + - if ((Context = mx_open_mailbox (buf, - (option (OPTREADONLY) || op == OP_MAIN_CHANGE_FOLDER_READONLY) ? - M_READONLY : 0, NULL)) != NULL) ++ if ((Context = mx_open_mailbox (buf, flags, NULL)) != NULL) + { + Labels = hash_create(131, 0); + mutt_scan_labels(Context); + menu->current = ci_first_message (); + } + else + menu->current = 0; + + mutt_clear_error (); + mutt_buffy_check(1); /* force the buffy check after we have changed the folder */ + menu->redraw = REDRAW_FULL; + set_option (OPTSEARCHINVALID); + + return 0; +} + static const struct mapping_t IndexHelp[] = { { N_("Quit"), OP_QUIT }, { N_("Del"), OP_DELETE }, @@@ -978,11 -782,9 +1008,14 @@@ int mutt_index_menu (void mutt_curs_set (1); /* fallback from the pager */ } +#ifdef USE_NOTMUCH + if (Context) + nm_debug_check(Context); +#endif + + #ifdef USE_NNTP + unset_option (OPTNEWS); /* for any case */ + #endif switch (op) { @@@ -1129,14 -1086,34 +1317,35 @@@ } break; + case OP_LIMIT_CURRENT_THREAD: case OP_MAIN_LIMIT: + case OP_TOGGLE_READ: CHECK_IN_MAILBOX; menu->oldcurrent = (Context->vcount && menu->current >= 0 && menu->current < Context->vcount) ? CURHDR->index : -1; + if (op == OP_TOGGLE_READ) + { + char buf[LONG_STRING]; + + if (!Context->pattern || strncmp (Context->pattern, "!~R!~D~s", 8) != 0) + { + snprintf (buf, sizeof (buf), "!~R!~D~s%s", + Context->pattern ? Context->pattern : ".*"); + set_option (OPTHIDEREAD); + } + else + { + strfcpy (buf, Context->pattern + 8, sizeof(buf)); + if (!*buf || strncmp (buf, ".*", 2) == 0) + snprintf (buf, sizeof(buf), "~A"); + unset_option (OPTHIDEREAD); + } + FREE (&Context->pattern); + Context->pattern = safe_strdup (buf); + } - if ((op == OP_TOGGLE_READ && mutt_pattern_func (M_LIMIT, NULL) == 0) || - mutt_pattern_func (M_LIMIT, _("Limit to messages matching: ")) == 0) + if (((op == OP_LIMIT_CURRENT_THREAD) && mutt_limit_current_thread(CURHDR)) + || ((op == OP_MAIN_LIMIT) && (mutt_pattern_func (M_LIMIT, _("Limit to messages matching: ")) == 0))) { if (menu->oldcurrent >= 0) { @@@ -1380,165 -1354,26 +1589,172 @@@ menu->redraw = REDRAW_FULL; break; + case OP_MAIN_QUASI_DELETE: + if (tag) { + for (j = 0; j < Context->vcount; j++) { + if (Context->hdrs[Context->v2r[j]]->tagged) { + Context->hdrs[Context->v2r[j]]->quasi_deleted = TRUE; + Context->changed = TRUE; + } + } + } else { + CURHDR->quasi_deleted = TRUE; + Context->changed = 1; + } + break; + +#ifdef USE_NOTMUCH + case OP_MAIN_ENTIRE_THREAD: + { + int oldcount = Context->msgcount; + if (Context->magic != M_NOTMUCH) { + mutt_message _("No virtual folder, aborting."); + break; + } + CHECK_MSGCOUNT; + CHECK_VISIBLE; + if (nm_read_entire_thread(Context, CURHDR) < 0) { + mutt_message _("Failed to read thread, aborting."); + break; + } + if (oldcount < Context->msgcount) { + HEADER *oldcur = CURHDR; + + if ((Sort & SORT_MASK) == SORT_THREADS) + mutt_sort_headers (Context, 0); + menu->current = oldcur->virtual; + menu->redraw = REDRAW_STATUS | REDRAW_INDEX; + + if (oldcur->collapsed || Context->collapsed) { + menu->current = mutt_uncollapse_thread(Context, CURHDR); + mutt_set_virtual(Context); + } + } + if (menu->menu == MENU_PAGER) + { + op = OP_DISPLAY_MESSAGE; + continue; + } + break; + } + + case OP_MAIN_MODIFY_LABELS: + case OP_MAIN_MODIFY_LABELS_THEN_HIDE: + { + if (Context->magic != M_NOTMUCH) { + mutt_message _("No virtual folder, aborting."); + break; + } + CHECK_MSGCOUNT; + CHECK_VISIBLE; + *buf = '\0'; + if (mutt_get_field ("Add/remove labels: ", buf, sizeof (buf), M_NM_TAG) || !*buf) + { + mutt_message _("No label specified, aborting."); + break; + } + if (tag) + { + char msgbuf[STRING]; + progress_t progress; + int px; + + if (!Context->quiet) { + snprintf(msgbuf, sizeof (msgbuf), _("Update labels...")); + mutt_progress_init(&progress, msgbuf, M_PROGRESS_MSG, + 1, Context->tagged); + } + nm_longrun_init(Context, TRUE); + for (px = 0, j = 0; j < Context->vcount; j++) { + if (Context->hdrs[Context->v2r[j]]->tagged) { + if (!Context->quiet) + mutt_progress_update(&progress, ++px, -1); + nm_modify_message_tags(Context, Context->hdrs[Context->v2r[j]], buf); + if (op == OP_MAIN_MODIFY_LABELS_THEN_HIDE) + { + Context->hdrs[Context->v2r[j]]->quasi_deleted = TRUE; + Context->changed = TRUE; + } + } + } + nm_longrun_done(Context); + menu->redraw = REDRAW_STATUS | REDRAW_INDEX; + } + else + { + if (nm_modify_message_tags(Context, CURHDR, buf)) { + mutt_message _("Failed to modify labels, aborting."); + break; + } + if (op == OP_MAIN_MODIFY_LABELS_THEN_HIDE) + { + CURHDR->quasi_deleted = TRUE; + Context->changed = TRUE; + } + if (menu->menu == MENU_PAGER) + { + op = OP_DISPLAY_MESSAGE; + continue; + } + if (option (OPTRESOLVE)) + { + if ((menu->current = ci_next_undeleted (menu->current)) == -1) + { + menu->current = menu->oldcurrent; + menu->redraw = REDRAW_CURRENT; + } + else + menu->redraw = REDRAW_MOTION_RESYNCH; + } + else + menu->redraw = REDRAW_CURRENT; + } + menu->redraw |= REDRAW_STATUS; + break; + } + + case OP_MAIN_VFOLDER_FROM_QUERY: + buf[0] = '\0'; + if (mutt_get_field ("Query: ", buf, sizeof (buf), M_NM_QUERY) != 0 || !buf[0]) + { + mutt_message _("No query, aborting."); + break; + } + if (!nm_uri_from_query(Context, buf, sizeof (buf))) + mutt_message _("Failed to create query, aborting."); + else - main_change_folder(menu, op, buf, sizeof (buf), &oldcount, &index_hint); ++ main_change_folder(menu, op, buf, sizeof (buf), &oldcount, &index_hint, 0); + break; + + case OP_MAIN_CHANGE_VFOLDER: +#endif +#ifdef USE_SIDEBAR + case OP_SIDEBAR_OPEN: +#endif case OP_MAIN_CHANGE_FOLDER: case OP_MAIN_NEXT_UNREAD_MAILBOX: - - if (attach_msg) - op = OP_MAIN_CHANGE_FOLDER_READONLY; - - /* fallback to the readonly case */ - case OP_MAIN_CHANGE_FOLDER_READONLY: + #ifdef USE_NNTP + case OP_MAIN_CHANGE_GROUP: + case OP_MAIN_CHANGE_GROUP_READONLY: + unset_option (OPTNEWS); + #endif + if (attach_msg || option (OPTREADONLY) || + #ifdef USE_NNTP + op == OP_MAIN_CHANGE_GROUP_READONLY || + #endif + op == OP_MAIN_CHANGE_FOLDER_READONLY) + flags = M_READONLY; + else + flags = 0; - if ((op == OP_MAIN_CHANGE_FOLDER_READONLY) || option (OPTREADONLY)) + if (flags) cp = _("Open mailbox in read-only mode"); - else +#ifdef USE_NOTMUCH + else if (op == OP_MAIN_CHANGE_VFOLDER) + cp = _("Open virtual folder"); +#endif + else cp = _("Open mailbox"); buf[0] = '\0'; @@@ -1553,32 -1388,26 +1769,48 @@@ break; } } +#ifdef USE_NOTMUCH + else if (op == OP_MAIN_CHANGE_VFOLDER) { + if (Context->magic == M_NOTMUCH) { + strfcpy(buf, Context->path, sizeof (buf)); + mutt_buffy_vfolder (buf, sizeof (buf)); + } + mutt_enter_vfolder (cp, buf, sizeof (buf), &menu->redraw, 1); + if (!buf[0]) + { + CLEARLINE (LINES-1); + break; + } + } +#endif else { + #ifdef USE_NNTP + if (op == OP_MAIN_CHANGE_GROUP || + op == OP_MAIN_CHANGE_GROUP_READONLY) + { + set_option (OPTNEWS); + CurrentNewsSrv = nntp_select_server (NewsServer, 0); + if (!CurrentNewsSrv) + break; + if (flags) + cp = _("Open newsgroup in read-only mode"); + else + cp = _("Open newsgroup"); + nntp_buffy (buf, sizeof (buf)); + } + else + #endif mutt_buffy (buf, sizeof (buf)); +#ifdef USE_SIDEBAR + if (op == OP_SIDEBAR_OPEN) { + const char *path = sb_get_highlight(); + if (!path) + break; + strncpy (buf, path, sizeof (buf)); + } else +#endif if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1) { if (menu->menu == MENU_PAGER) @@@ -1596,7 -1425,72 +1828,12 @@@ } } - main_change_folder(menu, op, buf, sizeof (buf), &oldcount, &index_hint); -#ifdef USE_NNTP - if (option (OPTNEWS)) - { - unset_option (OPTNEWS); - nntp_expand_path (buf, sizeof (buf), &CurrentNewsSrv->conn->account); - } - else -#endif - mutt_expand_path (buf, sizeof (buf)); - if (mx_get_magic (buf) <= 0) - { - mutt_error (_("%s is not a mailbox."), buf); - break; - } - mutt_str_replace (&CurrentFolder, buf); - - /* keepalive failure in mutt_enter_fname may kill connection. #3028 */ - if (Context && !Context->path) - FREE (&Context); - - if (Context) - { - int check; - - mutt_str_replace (&LastFolder, Context->path); - oldcount = Context ? Context->msgcount : 0; - - if ((check = mx_close_mailbox (Context, &index_hint)) != 0) - { - if (check == M_NEW_MAIL || check == M_REOPENED) - update_index (menu, Context, check, oldcount, index_hint); - - set_option (OPTSEARCHINVALID); - menu->redraw = REDRAW_INDEX | REDRAW_STATUS; - break; - } - FREE (&Context); - } - - mutt_sleep (0); - - /* Set CurrentMenu to MENU_MAIN before executing any folder - * hooks so that all the index menu functions are available to - * the exec command. - */ - - CurrentMenu = MENU_MAIN; - mutt_folder_hook (buf); - - if ((Context = mx_open_mailbox (buf, flags, NULL)) != NULL) - { - menu->current = ci_first_message (); - } - else - menu->current = 0; - ++ main_change_folder(menu, op, buf, sizeof (buf), &oldcount, &index_hint, flags); + #ifdef USE_NNTP + /* mutt_buffy_check() must be done with mail-reader mode! */ + menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN, + (Context && (Context->magic == M_NNTP)) ? IndexNewsHelp : IndexHelp); + #endif - mutt_clear_error (); - mutt_buffy_check(1); /* force the buffy check after we have changed - the folder */ - menu->redraw = REDRAW_FULL; - set_option (OPTSEARCHINVALID); break; case OP_DISPLAY_MESSAGE: diff --cc doc/manual.xml.head index 9d227b987,ab55b8219..e76b9d4ad --- a/doc/manual.xml.head +++ b/doc/manual.xml.head @@@ -8914,3234 -8497,233 +9306,3475 @@@ please have a look at the mixmaster doc - Patch Dependencies: - mutt-1.5.24 + Dependencies: + mutt-1.6.1 - This patch is part of the NeoMutt project. + This patch is part of the NeoMutt Project. - + Introduction + + + The quasi-delete function marks an email that should be + hidden from the index, but NOT deleted. + + + + On its own, this patch isn't very useful. It forms a useful part of + the notmuch plugin. + - + + + + Functions + + Quasi-Delete Functions + + + + Menus + Default Key + Function + Description + + + + + index,pager + (none) + <quasi-delete> + delete from mutt, don't touch on disk + + + +
+
+ + + + + Muttrc + +# Example Mutt config file for the 'quasi-delete' feature. + +# The 'quasi-delete' function marks an email that should be hidden +# from the index, but NOT deleted. +bind index,pager Q quasi-delete + +# vim: syntax=muttrc + + + + + See Also + + + NeoMutt Project + notmuch patch + + + + + Known Bugs + None + + + + Credits + + Karel Zak kzak@redhat.com + Richard Russon rich@flatcap.org + + + + + + Progress Bar Patch + Show a visual progress bar on slow operations + + + Patch + + + To check if Mutt supports Progress Bar, look for + patch-progress in the mutt version. + See: . + + + + Dependencies: + mutt-1.6.1 + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + The progress patch shows a visual progress bar on slow + tasks, such as indexing a large folder over the net. + + + + + + + Colors + + Progress Colors + + + + Name + Default Color + Description + + + + + progress + default + Visual progress bar + + + +
+
+ + + + + Muttrc + +# Example Mutt config file for the 'progress' patch. + +# The 'progress' patch provides clear visual feedback for +# slow tasks, such as indexing a large folder over the net. + +# Set the color of the progress bar +# White text on a red background +color progress white red + +# vim: syntax=muttrc + + + + + See Also + + + NeoMutt Project + Color command + + + + + Known Bugs + None + + + + Credits + + Rocco Rutte pdmef@gmx.net + Vincent Lefevre vincent@vinc17.org + Stefan Kuhn wuodan@hispeed.ch + Karel Zak kzak@redhat.com + Richard Russon rich@flatcap.org + + +
+ + + Status Color Patch + Custom rules for theming the status bar + + + Patch + + + To check if Mutt supports Status Color, look for + patch-status-color in the mutt version. + See: . + + + + Dependencies: + mutt-1.6.1 + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + The status-color patch allows you to theme different + parts of the status bar (also when it's used by the index). + + + + Unlike normal color commands, color status can now + take up to 2 extra parameters (regex, num). + + + + + + + Commands + + color + + + + + foreground + + + background + + + + regex + + + + num + + + + + + + With zero parameters, Mutt will set the default color for the entire + status bar. + + + + With one parameter, Mutt will only color the parts matching the + regex. + + + + With two parameters, Mutt will only color the num'th sub-match of + the regex. + + + + + Colors + + + Status Colors + + + + Name + Default Color + Description + + + + + status + reverse + Status bar + + + +
+
+ + + + + Muttrc + +# Example Mutt config file for the 'status-color' patch. + +# The 'status-color' patch allows you to theme different parts of +# the status bar (also when it's used by the index). + +# For the examples below, set some defaults +set status_format='-%r-Mutt: %f [Msgs:%?M?%M/?%m%?n? New:%n?%?o? Old:%o?%?d? Del:%d?%?F? Flag:%F?%?t? Tag:%t?%?p? Post:%p?%?b? Inc:%b?%?l? %l?]---(%s/%S)-%>-(%P)---' +set index_format='%4C %Z %{%b %d} %-15.15L (%?l?%4l&%4c?) %s' +set sort=threads +set sort_aux=last-date-received + +# 'status color' can take up to 2 extra parameters + +# color status foreground background [ regex [ num ]] + +# 0 extra parameters +# Set the default color for the entire status line +color status blue white + +# 1 extra parameter +# Set the color for a matching pattern +# color status foreground background regexp + +# Highlight New, Deleted, or Flagged emails +color status brightred white '(New|Del|Flag):[0-9]+' + +# Highlight mailbox ordering if it's different from the default +# First, highlight anything (*/*) +color status brightred default '\([^)]+/[^)]+\)' + +# Then override the color for one specfic case +color status default default '\(threads/last-date-received\)' + +# 2 extra parameters +# Set the color for the nth submatch of a pattern +# color status foreground background regexp num + +# Highlight the contents of the []s but not the [] themselves +color status red default '\[([^]]+)\]' 1 + +# The '1' refers to the first regex submatch, which is the inner +# part in ()s + +# Highlight the mailbox +color status brightwhite default 'Mutt: ([^ ]+)' 1 + +# Search for 'Mutt: ' but only highlight what comes after it + +# vim: syntax=muttrc + + + + + See Also + + + NeoMutt Project + Compile-Time Features + Regular Expressions + Patterns + index-color patch + Color command + + + + + Known Bugs + None + + + + Credits + + David Sterba dsterba@suse.cz + Thomas Glanzmann thomas@glanzmann.de + Kirill A. Shutemov kirill@shutemov.name + Richard Russon rich@flatcap.org + + +
+ + + Index Color Patch + Custom rules for theming the email index + + + Patch + + + To check if Mutt supports Index Color, look for + patch-index-color in the mutt version. + See: . + + + + Dependencies: + mutt-1.6.1 + status-color patch + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + The index-color patch allows you to specify colors for + individual parts of the email index. e.g. Subject, Author, Flags. + + + + First choose which part of the index you'd like to color. + Then, if needed, pick a pattern to match. + + + + Note: The pattern does not have to refer to the object you wish to + color. e.g. + + + +color index_author red default "~smutt" + + + + The author appears red when the subject (~s) contains mutt. + + + + + + + Colors + + + All the colors default to default, i.e. unset. + + + + The index objects can be themed using the color command. + Some objects require a pattern. + + + +color index-object foreground background +color index-object foreground background pattern + + + + Index Colors + + + + Object + Pattern + Highlights + + + + + index + yes + Entire index line + + + index_author + yes + Author name, %A %a %F %L %n + + + index_collapsed + no + Number of messages in a collapsed thread, %M + + + index_date + no + Date field + + + index_flags + yes + Message flags, %S %Z + + + index_label + no + Message label, %y %Y + + + index_number + no + Message number, %C + + + index_size + no + Message size, %c %l + + + index_subject + yes + Subject, %s + + + +
+
+ + + + + Muttrc + +# Example Mutt config file for the 'index-color' feature. + +# Entire index line +color index white black '.*' + +# Author name, %A %a %F %L %n + +# Give the author column a dark grey background +color index_author default color234 '.*' + +# Highlight a particular from (~f) +color index_author brightyellow color234 '~fRay Charles' + +# Message flags, %S %Z +# Highlight the flags for flagged (~F) emails +color index_flags default red '~F' + +# Subject, %s +# Look for a particular subject (~s) +color index_subject brightcyan default '~s\(closes #[0-9]+\)' + +# Number of messages in a collapsed thread, %M +color index_collapsed default brightblue + +# Date field +color index_date green default + +# Message label, %y %Y +color index_label default brightgreen + +# Message number, %C +color index_number red default + +# Message size, %c %l +color index_size cyan default + +# vim: syntax=muttrc + + + + + See Also + + + NeoMutt Project + Regular Expressions + Patterns + $index_format + Color command + Status-Color patch + Keywords patch + + + + + Known Bugs + None + + + + Credits + + Christian Aichinger Greek0@gmx.net + Christoph Myon Berg myon@debian.org + Elimar Riesebieter riesebie@lxtec.de + Eric Davis edavis@insanum.com + Vladimir Marek Vladimir.Marek@oracle.com + Richard Russon rich@flatcap.org + + +
+ + + Nested If Patch + Allow complex nested conditions in format strings + + + Patch + + + To check if Mutt supports Nested If, look for + patch-nested-if in the mutt version. + See: . + + + + Dependencies: + mutt-1.6.1 + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + Mutt's format strings can contain embedded if-then-else conditions. + They are of the form: + + + +%?VAR?TRUE&FALSE? + + + + If the variable VAR has a value greater than zero, + print the TRUE string, otherwise print the + FALSE string. + + + + e.g. %?S?Size: %S&Empty? + + + Which can be read as: + + + if (%S > 0) { + print "Size: %S" + } else { + print "Empty" + } + + + + These conditions are useful, but in Mutt they cannot be nested + within one another. This patch uses the notation + %<VAR?TRUE&FALSE> and allows them to be nested. + + + + The %<...> notation was used to format the + current local time. but that's not really very useful since mutt + has no means of refreshing the screen periodically. + + + + A simple nested condition might be: + (Some whitespace has been introduced for clarity) + + + + %<x? %<y? XY & X > & %<y? Y & NONE > > Conditions + %<y? XY & X > x>0 + XY x>0,y>0 + X x>0,y=0 + + + + %<x? %<y? XY & X > & %<y? Y & NONE > > Conditions + %<y? Y & NONE > x=0 + Y x=0,y>0 + NONE x=0,y=0 + + + Equivalent to: + + + if (x > 0) { + if (y > 0) { + print 'XY' + } else { + print 'X' + } + } else { + if (y > 0) { + print 'Y' + } else { + print 'NONE' + } + } + + + Examples: + + +set index_format='%4C %Z %{%b %d} %-25.25n %s%> %<M?%M Msgs &%<l?%l Lines&%c Bytes>>' + + + + if a thread is folded + display the number of messages (%M) + else if we know how many lines in the message + display lines in message (%l) + else + display the size of the message in bytes (%c) + + + +set index_format='%4C %Z %{%b %d} %-25.25n %<M?[%M] %s&%s%* %<l?%l&%c>>' + + + + if a thread is folded + display the number of messages (%M) + display the subject (%s) + else if we know how many lines in the message + display lines in message (%l) + else + display the size of the message in bytes (%c) + + + + + + Variables + The nested-if patch doesn't have any config of its own. + It modifies the behavior of the format strings. + + + + + + Muttrc + +# Example Mutt config file for the 'nested-if' feature. + +# This patch uses the format: '%<VAR?TRUE&FALSE>' for conditional +# format strings that can be nested. + +# Example 1 +# if a thread is folded +# display the number of messages (%M) +# else if we know how many lines in the message +# display lines in message (%l) +# else display the size of the message in bytes (%c) +set index_format='%4C %Z %{%b %d} %-25.25n %s%> %<M?%M Msgs &%<l?%l Lines&%c Bytes>>' + +# Example 2 +# if a thread is folded +# display the number of messages (%M) +# display the subject (%s) +# else if we know how many lines in the message +# display lines in message (%l) +# else +# display the size of the message in bytes (%c) +set index_format='%4C %Z %{%b %d} %-25.25n %<M?[%M] %s&%s%* %<l?%l&%c>>' + +# vim: syntax=muttrc + + + + + See Also + + + NeoMutt Project + cond-date patch + $index_format + $status_format + + + + + Known Bugs + Patch overwrites $<fmt> handler in $index_format + + + + Credits + + David Champion dgc@uchicago.edu + Richard Russon rich@flatcap.org + + + + + + Conditional Dates Patch + Use rules to choose date format + + + Patch + + + To check if Mutt supports Conditional Dates, look for + patch-cond-date in the mutt version. + See: . + + + + Dependencies: + mutt-1.6.1 + nested-if patch + + + + This patch is part of the NeoMutt Project. + + + + + Introduction + + + The cond-date patch allows you to construct + $index_format expressions based on the age of the email. + + + + Mutt's default $index_format displays email dates in the + form: abbreviated-month day-of-month — Jan 14. + + + + The format is configurable but only per-mailbox. This patch allows you + to configure the display depending on the age of the email. + + + + Potential Formatting Scheme + + + + Email Sent + Format + Example + + + + + Today + %H:%M + 13:23 + + + This Month + %a %d + Thu 17 + + + This Year + %b %d + Dec 10 + + + Older than 1 Year + %m/%y + 06/14 + + + +
+ + + For an explanation of the date formatting strings, see + strftime(3). + + + + By carefully picking your formats, the dates can remain + unambiguous and compact. + + + + Mutt's conditional format strings have the form: + (whitespace introduced for clarity) + + + %? TEST ? TRUE & FALSE ? + + + The examples below use the test %[ — the date + of the message in the local timezone. They will also work with + %( — the local time that the message arrived. + + + + The date tests are of the form: + + + %[nX? TRUE & FALSE ? + + + n is an optional count (defaults to 1 if missing) + X is the time period + + + + Date Formatting Codes + + + + Letter + Time Period + + + + + y + Years + + + m + Months + + + w + Weeks + + + d + Days + + + H + Hours + + + M + Minutes + + + +
+ + + Example Date Tests + + + + Test + Meaning + + + + + %[y + This year + + + %[1y + This year + + + %[6m + In the last 6 months + + + %[w + This week + + + %[d + Today + + + %[4H + In the last 4 hours + + + +
+ + + Example 1 + + We start with a one-condition test. + + + Example 1 + + + + Test + Date Range + Format String + Example + + + + + %[1m + This month + %[%b %d] + Dec 10 + + + + Older + %[%Y-%m-%d] + 2015-04-23 + + + +
+ + The $index_format string would contain: + +%?[1m?%[%b %d]&%[%Y-%m-%d]? + + + + Reparsed a little, for clarity, you can see the + test condition and the two format strings. + + + +%?[1m? & ? + %[%b %d] %[%Y-%m-%d] + + +
+ + + Example 2 + + + This example contains three test conditions and four date formats. + + + + Example 2 + + + + Test + Date Range + Format String + Example + + + + + %[d + Today + %[%H:%M ] + 12:34 + + + %[m + This month + %[%a %d] + Thu 12 + + + %[y + This year + %[%b %d] + Dec 10 + + + + Older + %[%m/%y ] + 06/15 + + + +
+ + The $index_format string would contain: + + +%<[y?%<[m?%<[d?%[%H:%M ]&%[%a %d]>&%[%b %d]>&%[%m/%y ]> + + + + Reparsed a little, for clarity, you can see the + test conditions and the four format strings. + + + +%<[y? &%[%m/%y ]> Older + %<[m? &%[%b %d]> This year + %<[d? &%[%a %d]> This month + %[%H:%M ] Today + + + + This a another view of the same example, with some whitespace + for clarity. + + + +%<[y? %<[m? %<[d? AAA & BBB > & CCC > & DDD > + + + +AAA = %[%H:%M ] +BBB = %[%a %d] +CCC = %[%b %d] +DDD = %[%m/%y ] + +
+
+ + + Variables + + + The cond-date patch doesn't have any config of its own. + It modifies the behavior of the format strings. + + + + + + + Muttrc + +# Example Mutt config file for the 'index-color' feature. +# +# The default index_format is: +# '%4C %Z %{%b %d} %-15.15L (%?l?%4l&%4c?) %s' +# +# We replace the date field '%{%b %d}', giving: +set index_format='%4C %Z %<[y?%<[m?%<[d?%[%H:%M ]&%[%a %d]>&%[%b %d]>&%[%m/%y ]> %-15.15L (%?l?%4l&%4c?) %s' + +# Test Date Range Format String Example +# -------------------------------------------- +# %[d Today %[%H:%M ] 12:34 +# %[m This month %[%a %d] Thu 12 +# %[y This year %[%b %d] Dec 10 +# - Older %[%m/%y ] 06/15 + +# vim: syntax=muttrc + + + + + See Also + + + NeoMutt Project + $index_format + nested-if patch + strftime(3) + + + + + Known Bugs + + + Date parsing doesn't quite do what you expect. + 1w doesn't mean the in the last 7 days, but + this week. This doesn't match + the normal Mutt behaviour: for example ~d>1w + means emails dated in the last 7 days. + + + + + + Credits + + Aaron Schrab aaron@schrab.com + Eric Davis edavis@insanum.com + Richard Russon rich@flatcap.org + + +
+ + + TLS-SNI Patch + Negotiate with a server for a TSL/SSL certificate + + + Patch + + + To check if Mutt supports TLS-SNI, look for + patch-tls-sni in the mutt version. + See: . + + + + Dependencies: + mutt-1.6.1 + OpenSSL + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + The TLS-SNI patch adds support for TLS virtual hosting. + If your mail server doesn't support this everything will still work + normally. + + + + TLS supports sending the expected server hostname during the + handshake, via the SNI extension. This can be used to select a + server certificate to issue to the client, permitting + virtual-hosting without requiring multiple IP addresses. + + + + This has been tested against Exim 4.80, which optionally logs SNI + and can perform vhosting. + + + + To verify TLS SNI support by a server, you can use: + + + +openssl s_client -host <imap server> -port <port> -tls1 -servername <imap server> + + + + + + + Muttrc + None + + + + See Also + + + NeoMutt Project + + + + + Known Bugs + None + + + + Credits + + Jeremy Katz katzj@linuxpower.org + Phil Pennock mutt-dev@spodhuis.demon.nl + Richard Russon rich@flatcap.org + + + + + + Sidebar Patch + Overview of mailboxes + + + Patch + + + To check if Mutt supports Sidebar, look for + +USE_SIDEBAR in the mutt version. + See: . + + + + Dependencies: + mutt-1.6.1 + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + The Sidebar shows a list of all your mailboxes. The list can be + turned on and off, it can be themed and the list style can be + configured. + + + + This part of the manual is a reference guide. + If you want a simple introduction with examples see the + Sidebar Howto. + If you just want to get started, you could use the sample + Sidebar muttrc. + + + + This version of Sidebar is based on Terry Chan's + 2015-11-11 release. + It contains many + new features, + lots of + bugfixes. + + + + + Variables + + + Sidebar Variables + + + + Name + Type + Default + + + + + sidebar_delim_chars + string + /. + + + sidebar_divider_char + string + | + + + sidebar_folder_indent + boolean + no + + + sidebar_format + string + %B%?F? [%F]?%* %?N?%N/?%S + + + sidebar_indent_string + string +    (two spaces) + + + sidebar_new_mail_only + boolean + no + + + sidebar_next_new_wrap + boolean + no + + + sidebar_refresh_time + number + 60 + + + sidebar_short_path + boolean + no + + + sidebar_sort_method + enum + SORT_ORDER + + + sidebar_visible + boolean + no + + + sidebar_whitelist + list + (empty) + + + sidebar_width + number + 20 + + + +
+
+ + + Functions + + + Sidebar adds the following functions to Mutt. + By default, none of them are bound to keys. + + + + Sidebar Functions + + + + Menus + Function + Description + + + + + index,pager + <sidebar-next> + Move the highlight to next mailbox + + + index,pager + <sidebar-next-new> + Move the highlight to next mailbox with new mail + + + index,pager + <sidebar-open> + Open highlighted mailbox + + + index,pager + <sidebar-page-down> + Scroll the Sidebar down 1 page + + + index,pager + <sidebar-page-up> + Scroll the Sidebar up 1 page + + + index,pager + <sidebar-prev> + Move the highlight to previous mailbox + + + index,pager + <sidebar-prev-new> + Move the highlight to previous mailbox with new mail + + + index,pager + <sidebar-toggle-visible> + Make the Sidebar (in)visible + + + +
+
+ + + Commands + + sidebar_whitelist + + mailbox + + + mailbox + + + + + + Colors + + + Sidebar Colors + + + + Name + Default Color + Description + + + + + sidebar_divider + default + The dividing line between the Sidebar and the Index/Pager panels + + + sidebar_flagged + default + Mailboxes containing flagged mail + + + sidebar_highlight + underline + Cursor to select a mailbox + + + sidebar_indicator + mutt indicator + The mailbox open in the Index panel + + + sidebar_new + default + Mailboxes containing new mail + + + sidebar_spoolfile + default + Mailbox that receives incoming mail + + + +
+ + If the sidebar_indicator color isn't set, then the default Mutt + indicator color will be used (the color used in the index panel). +
+ + + Sort + + + Sidebar Sort + + + + Sort + Description + + + + + alpha + Alphabetically by path + + + count + Total number of messages + + + flagged + Number of flagged messages + + + name + Alphabetically by path + + + new + Number of new messages + + + path + Alphabetically by path + + + unsorted + Do not resort the paths + + + +
+
+ + + Muttrc + +# This is a complete list of sidebar-related configuration. + +# -------------------------------------------------------------------------- +# VARIABLES - shown with their default values +# -------------------------------------------------------------------------- + +# Should the Sidebar be shown? +set sidebar_visible = no + +# How wide should the Sidebar be in screen columns? +# Note: Some characters, e.g. Chinese, take up two columns each. +set sidebar_width = 20 + +# Should the mailbox paths be abbreviated? +set sidebar_short_path = no + +# When abbreviating mailbox path names, use any of these characters as path +# separators. Only the part after the last separators will be shown. +# For file folders '/' is good. For IMAP folders, often '.' is useful. +set sidebar_delim_chars = '/.' + +# If the mailbox path is abbreviated, should it be indented? +set sidebar_folder_indent = no + +# Indent mailbox paths with this string. +set sidebar_indent_string = ' ' + +# Make the Sidebar only display mailboxes that contain new, or flagged, +# mail. +set sidebar_new_mail_only = no + +# Any mailboxes that are whitelisted will always be visible, even if the +# sidebar_new_mail_only option is enabled. +sidebar_whitelist '/home/user/mailbox1' +sidebar_whitelist '/home/user/mailbox2' + +# When searching for mailboxes containing new mail, should the search wrap +# around when it reaches the end of the list? +set sidebar_next_new_wrap = no + +# The character to use as the divider between the Sidebar and the other Mutt +# panels. +# Note: Only the first character of this string is used. +set sidebar_divider_char = '|' + +# Display the Sidebar mailboxes using this format string. +set sidebar_format = '%B%?F? [%F]?%* %?N?%N/?%S' + +# Sidebar will not refresh its list of mailboxes any more frequently than +# this number of seconds. This will help reduce disk/network traffic. +set sidebar_refresh_time = 60 + +# Sort the mailboxes in the Sidebar using this method: +# count - total number of messages +# flagged - number of flagged messages +# new - number of new messages +# path - mailbox path +# unsorted - do not sort the mailboxes +set sidebar_sort_method = 'unsorted' + +# -------------------------------------------------------------------------- +# FUNCTIONS - shown with an example mapping +# -------------------------------------------------------------------------- + +# Move the highlight to the previous mailbox +bind index,pager \Cp sidebar-prev + +# Move the highlight to the next mailbox +bind index,pager \Cn sidebar-next + +# Open the highlighted mailbox +bind index,pager \Co sidebar-open + +# Move the highlight to the previous page +# This is useful if you have a LOT of mailboxes. +bind index,pager <F3> sidebar-page-up + +# Move the highlight to the next page +# This is useful if you have a LOT of mailboxes. +bind index,pager <F4> sidebar-page-down + +# Move the highlight to the previous mailbox containing new, or flagged, +# mail. +bind index,pager <F5> sidebar-prev-new + +# Move the highlight to the next mailbox containing new, or flagged, mail. +bind index,pager <F6> sidebar-next-new + +# Toggle the visibility of the Sidebar. +bind index,pager B sidebar-toggle-visible + +# -------------------------------------------------------------------------- +# COLORS - some unpleasant examples are given +# -------------------------------------------------------------------------- +# Note: All color operations are of the form: +# color OBJECT FOREGROUND BACKGROUND + +# Color of the current, open, mailbox +# Note: This is a general Mutt option which colors all selected items. +color indicator cyan black + +# Color of the highlighted, but not open, mailbox. +color sidebar_highlight black color8 + +# Color of the divider separating the Sidebar from Mutt panels +color sidebar_divider color8 black + +# Color to give mailboxes containing flagged mail +color sidebar_flagged red black + +# Color to give mailboxes containing new mail +color sidebar_new green black + +# -------------------------------------------------------------------------- + +# vim: syntax=muttrc + + + + + See Also + + + Regular Expressions + Patterns + Color command + notmuch patch + + + + + Known Bugs + Unsorted isn't + + + + Credits + + Justin Hibbits jrh29@po.cwru.edu + Thomer M. Gil mutt@thomer.com + David Sterba dsterba@suse.cz + Evgeni Golov evgeni@debian.org + Fabian Groffen grobian@gentoo.org + Jason DeTiberus jdetiber@redhat.com + Stefan Assmann sassmann@kpanic.de + Steve Kemp steve@steve.org.uk + Terry Chan tchan@lunar-linux.org + Tyler Earnest tylere@rne.st + Richard Russon rich@flatcap.org + + +
+ + + Ifdef Patch + Conditional config options + + + Patch + + + To check if Mutt supports ifdef, look for + patch-ifdef in the mutt version. + See: . + + + + Dependencies: + mutt-1.6.1 + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + The ifdef patch introduces three new commands to + Mutt and allow you to share one config file between versions of Mutt + that may have different features compiled in. + + + +ifdef symbol config-command [args...] # If a symbol is defined +ifndef symbol config-command [args...] # If a symbol is not defined +finish # Finish reading the current file + + + + Here a symbol can be a $variable, + <function>, + command or compile-time symbol, such + as USE_IMAP. + + + + finish is particularly useful when combined with + ifndef. e.g. + + + +# Sidebar config file +ifndef USE_SIDEBAR finish + + + + + + + + Commands + + ifdef + + symbol + + + "config-command [args]" + + ifndef + + symbol + + + "config-command [args]" + + finish + + + + + + + Muttrc + +# Example Mutt config file for the 'ifdef' feature. + +# This feature introduces three useful commands which allow you to share +# one config file between versions of Mutt that may have different +# features compiled in. + +# ifdef symbol config-command [args...] +# ifndef symbol config-command [args...] +# finish + +# The 'ifdef' command tests whether Mutt understands the name of +# a variable, function, command or compile-time symbol. +# If it does, then it executes a config command. + +# The 'ifndef' command tests whether a symbol does NOT exist. + +# The 'finish' command tells Mutt to stop reading current config file. + +# If the 'trash' variable exists, set it. +ifdef trash 'set trash=~/Mail/trash' + +# If the 'tag-pattern' function exists, bind a key to it. +ifdef tag-pattern 'bind index <F6> tag-pattern' + +# If the 'imap-fetch-mail' command exists, read my IMAP config. +ifdef imap-fetch-mail 'source ~/.mutt/imap.rc' + +# If the compile-time symbol 'USE_SIDEBAR' does not exist, then +# stop reading the current config file. +ifndef USE_SIDEBAR finish + +# vim: syntax=muttrc + + + + + See Also + + + NeoMutt Project + + + + + Known Bugs + None + + + + Credits + + Cedric Duval cedricduval@free.fr + Matteo F. Vescovi mfvescovi@gmail.com + Richard Russon rich@flatcap.org + + + + + + Fmemopen Patch + Replace some temporary files with memory buffers + + + Patch + + + To check if Mutt supports fmemopen, look for + patch-fmemopen in the mutt version. + See: . + + + + Dependencies: + mutt-1.6.1 + open_memstream(), fmemopen() from glibc + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + The fmemopen patch speeds up some searches. + + + + This patch changes a few places where Mutt creates temporary files. + It replaces them with in-memory buffers. This should improve the + performance when searching the header or body using the + $thorough_search option. + + + + There are no user-configurable parts. + + + + This patch depends on open_memstream() and + fmemopen(). They are provided by glibc. Without + them, Mutt will simply create temporary files. + + + + + + + Muttrc + None + + + + See Also + + + NeoMutt Project + Compile-Time Features + fmemopen(3) + + + + + Known Bugs + None + + + + Credits + + Julius Plenz plenz@cis.fu-berlin.de + Richard Russon rich@flatcap.org + + + + + + Initials Expando Patch + Expando for author's initials + + + Patch + + + To check if Mutt supports Initials, look for + patch-initials in the mutt version. + See: . + + + + Dependencies: + mutt-1.6.1 + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + The initials patch adds an expando (%I) for an author's + initials. + + + + The index panel displays a list of emails. Its layout is controlled by + the $index_format variable. Using + this expando saves space in the index panel. This can be useful if you + are regularly working with a small set of people. + + + + + Variables + + + This patch has no config of its own. It adds an expando which can be + used in the $index_format variable. + + + + + + + Muttrc + +# Example Mutt config file for the 'initials' patch. + +# The 'initials' patch has no config of its own. +# It adds an expando for an author's initials, +# which can be used in the 'index_format' variable. + +# The default 'index_format' is: +set index_format='%4C %Z %{%b %d} %-15.15L (%?l?%4l&%4c?) %s' + +# Where %L represents the author/recipient + +# This might look like: +# 1 + Nov 17 David Bowie Changesbowie ( 689) +# 2 ! Nov 17 Stevie Nicks Rumours ( 555) +# 3 + Nov 16 Jimi Hendrix Voodoo Child ( 263) +# 4 + Nov 16 Debbie Harry Parallel Lines ( 540) + +# Using the %I expando: +set index_format='%4C %Z %{%b %d} %I (%?l?%4l&%4c?) %s' + +# This might look like: +# 1 + Nov 17 DB Changesbowie ( 689) +# 2 ! Nov 17 SN Rumours ( 555) +# 3 + Nov 16 JH Voodoo Child ( 263) +# 4 + Nov 16 DH Parallel Lines ( 540) + +# vim: syntax=muttrc + + + + + See Also + + + NeoMutt Project + $index_format + index-color patch + folder-hook + + + + + Known Bugs + None + + + + Credits + + Vsevolod Volkov vvv@mutt.org.ua + Richard Russon rich@flatcap.org + + + + + + Trash Folder Patch + Automatically move "deleted" emails to a trash bin + + + Patch + + + To check if Mutt supports Trash Folder, look for + patch-trash in the mutt version. + See: . + + + If IMAP is enabled, this patch will use it + + + Dependencies: + mutt-1.6.1 + IMAP support + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + In Mutt, when you delete an email it is first marked + deleted. The email isn't really gone until + <sync-mailbox> is called. + This happens when the user leaves the folder, or the function is called + manually. + + + + After <sync-mailbox> has been called the email is gone forever. + + + + The $trash variable defines a folder in + which to keep old emails. As before, first you mark emails for + deletion. When <sync-mailbox> is called the emails are moved to + the trash folder. + + + + The $trash path can be either a full directory, + or be relative to the $folder + variable, like the mailboxes command. + + + + Emails deleted from the trash folder are gone forever. + + + + + Variables + + Trash Variables + + + + Name + Type + Default + + + + + trash + string + (none) + + + +
+
+ + + Functions + + Trash Functions + + + + Menus + Default Key + Function + Description + + + + + index,pager + (none) + <purge-message> + really delete the current entry, bypassing the trash folder + + + +
+
+ + + + + Muttrc + +# Example Mutt config file for the 'trash' feature. + +# This feature defines a new 'trash' folder. +# When mail is deleted it will be moved to this folder. + +# Folder in which to put deleted emails +set trash='+Trash' +set trash='/home/flatcap/Mail/Trash' + +# The default delete key 'd' will move an email to the 'trash' folder +# Bind 'D' to REALLY delete an email +bind index D purge-message + +# Note: Deleting emails from the 'trash' folder will REALLY delete them. + +# vim: syntax=muttrc + + + + + See Also + + + NeoMutt Project + folder-hook + + + + + Known Bugs + None + + + + Credits + + Cedric Duval cedricduval@free.fr + Benjamin Kuperman kuperman@acm.org + Paul Miller paul@voltar.org + Richard Russon rich@flatcap.org + + +
+ + + Limit-Current-Thread Patch + Focus on one Email Thread + + + Patch + + + To check if Mutt supports limit-current-thread, look for + patch-limit-current-thread in the mutt version. + See: . + + + + Dependencies: + mutt-1.6.1 + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + This patch adds a new way of using the + Limit Command. + The <limit-current-thread> + function restricts the view to just the current thread. + Setting the limit (the l key) to + all will restore the full email list. + + + + + + + Functions + + + Limit-Current-Thread Functions + + + + Menus + Default Key + Function + Description + + + + + index + <Esc> L + <limit-current-thread> + Limit view to current thread + + + +
+ +
+ + + + Muttrc + + +# Example Mutt config file for the 'limit-current-thread' patch. + +# Limit view to current thread +bind index <esc>L limit-current-thread + +# vim: syntax=muttrc + + + + + See Also + + + NeoMutt Project + + + + + Known Bugs + None + + + + Credits + + David Sterba dsterba@suse.cz + Richard Russon rich@flatcap.org + + +
+ + + Skip-Quoted Patch + Leave some context visible + + + Patch + + + To check if Mutt supports skip-quoted, look for + patch-skip-quoted in the mutt version. + See: . + + + + Dependencies: + mutt-1.6.1 + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + When viewing an email, the + <skip-to-quoted> function (by default the + S key) will scroll past any quoted text. + Sometimes, a little context is useful. + + + + By setting the $skip_quoted_offset variable, you + can select how much of the quoted text is left visible. + + + + + Variables + + Skip-Quoted Variables + + + + Name + Type + Default + + + + + skip_quoted_offset + number + 0 + + + +
+
+ + + + + Muttrc + + +# Example Mutt config file for the 'skip-quoted' patch. + +# The 'S' (skip-quoted) command scrolls the pager past the quoted text (usually +# indented with '> '. Setting 'skip_quoted_offset' leaves some lines of quoted +# text on screen for context. + +# Show three quoted lines before the reply +set skip_quoted_offset = 3 + +# vim: syntax=muttrc + + + + + See Also + + + NeoMutt Project + + + + + Known Bugs + None + + + + Credits + + David Sterba dsterba@suse.cz + Richard Russon rich@flatcap.org + + +
+ + + Compressed Folders Patch + Read from/write to compressed mailboxes + + + Patch + + + To check if Mutt supports Compress Folders, look for + +USE_COMPRESSED in the mutt version. + See: . + + + + Dependencies: + mutt-1.5.24 + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + The Compressed Folder patch allows Mutt to read mailbox files that are + compressed. But it isn't limited to compressed files. It works well + with encrypted files, too. In fact, if you can create a program/script + to convert to and from your format, then Mutt can read it. + + + + The patch adds three hooks to Mutt: open-hook, + close-hook and append-hook. They + define commands to: uncompress a file; compress a file; append + messages to an already compressed file. + + + + There are some examples of both compressed and encrypted files, + later. For now, the documentation will just concentrate on + compressed files. + + + + + + + + Commands + + open-hook + + pattern + + + shell-command + + close-hook + + pattern + + + shell-command + + append-hook + + pattern + + + shell-command + + + + + The shell-command must contain two placeholders for filenames: + %f and %t. These represent + from and to filenames. It's a good idea to + put quotes around these placeholders. + + + + If you need the exact string %f or %t in your + command, simply double up the % character, e.g. + %%f or %%t. + + + + Not all Hooks are Required + + + + Open + Close + Append + Effect + Useful if + + + + + Open + - + - + Folder is readonly + The folder is just a backup + + + Open + Close + - + Folder is read/write, but the entire folder must be + written if anything is changed + Your compression format doesn't support appending + + + Open + Close + Append + Folder is read/write and emails can be efficiently added + to the end + Your compression format supports appending + + + Open + - + Append + Folder is readonly, but can be appended to + You want to store emails, but never change them + + + +
+ + + The command: + + should return a non-zero exit status on failure + should not delete any files + + + + + Read from compressed mailbox + + open-hook regexp shell-command + + + If Mutt is unable to open a file, it then looks for + open-hook that matches the filename. + + + + If your compression program doesn't have a well-defined extension, + then you can use . as the regexp. + + + + Example of open-hook + + open-hook '\.gz$' "gzip -cd '%f' > '%t'" + + + Mutt finds a file, example.gz, + that it can't read + Mutt has an open-hook + whose regexp matches the filename: + \.gz$ + Mutt uses the command gzip -cd + to create a temporary file that it can + read + + + + + + Write to a compressed mailbox + + close-hook regexp shell-command + + + When Mutt has finished with a compressed mail folder, it will look + for a matching close-hook to recompress the file. + This hook is optional. + + + + If the folder has not been modifed, the + close-hook will not be called. + + + + Example of close-hook + + close-hook '\.gz$' "gzip -c '%t' > '%f'" + + + Mutt has finished with a folder, example.gz, + that it opened with open-hook + The folder has been modified + Mutt has a close-hook whose regexp + matches the filename: \.gz$ + Mutt uses the command gzip -c + to create a new compressed file + + + + + + Append to a compressed mailbox + + append-hook regexp shell-command + + + When Mutt wants to append an email to a compressed mail folder, it + will look for a matching append-hook. + This hook is optional. + + + + Using the append-hook will save time, but + Mutt won't be able to determine the type of the mail folder + inside the compressed file. + + + + Mutt will assume the type to be that of + the $mbox_type variable. Mutt also uses + this type for temporary files. + + + + Mutt will only use the append-hook for existing files. + The close-hook will be used for empty, or missing files. + + + + Example of append-hook + + append-hook '\.gz$' "gzip -c '%t' >> '%f'" + + + Mutt wants to append an email to a folder, example.gz, + that it opened with open-hook + Mutt has an append-hook whose regexp matches + the filename: \.gz$ + Mutt knows the mailbox type from the $mbox + variable + Mutt uses the command gzip -c + to append to an existing compressed file + + + + + + + Empty Files + + + Mutt assumes that an empty file is not compressed. In this + situation, unset $save_empty, so + that the compressed file will be removed if you delete all of the + messages. + + + + + Security + + + Encrypted files are decrypted into temporary files which are + stored in the $tmpdir directory. + This could be a security risk. + + +
+ + + + + Muttrc + +# Example Mutt config file for the 'compressed folders' feature. + +# This feature adds three hooks to Mutt which allow it to +# work with compressed, or encrypted, mailboxes. + +# The hooks are of the form: +# open-hook regexp "shell-command" +# close-hook regexp "shell-command" +# append-hook regexp "shell-command" + +# The 'append-hook' is optional. + +# Hander for gzip compressed mailboxes +open-hook '\.gz$' "gzip -cd '%f' > '%t'" +close-hook '\.gz$' "gzip -c '%t' > '%f'" +append-hook '\.gz$' "gzip -c '%t' >> '%f'" + +# Hander for bzip2 compressed mailboxes +open-hook '\.bz2$' "bzip2 -cd '%f' > '%t'" +close-hook '\.bz2$' "bzip2 -c '%t' > '%f'" +append-hook '\.bz2$' "bzip2 -c '%t' >> '%f'" + +# Hander for xz compressed mailboxes +open-hook '\.xz$' "xz -cd '%f' > '%t'" +close-hook '\.xz$' "xz -c '%t' > '%f'" +append-hook '\.xz$' "xz -c '%t' >> '%f'" + +# Hander for pgp encrypted mailboxes +# PGP does not support appending to an encrypted file +open-hook '\.pgp$' "pgp -f < '%f' > '%t'" +close-hook '\.pgp$' "pgp -fe YourPgpUserIdOrKeyId < '%t' > '%f'" + +# Hander for gpg encrypted mailboxes +# gpg does not support appending to an encrypted file +open-hook '\.gpg$' "gpg --decrypt < '%f' > '%t'" +close-hook '\.gpg$' "gpg --encrypt --recipient YourGpgUserIdOrKeyId < '%t' > '%f'" + +# vim: syntax=muttrc + + + + + See Also + + + NeoMutt Project + Compile-Time Features + Regular Expressions + $tmpdir + $mbox_type + $save_empty + folder-hook + + + + + Known Bugs + + + The Compressed Folder hooks cannot deal with filenames that contains quotes/apostrophes. + + + + + Credits + + Roland Rosenfeld roland@spinnaker.de + Alain Penders Alain@Finale-Dev.com + Christoph Myon Berg myon@debian.org + Evgeni Golov evgeni@debian.org + Richard Russon rich@flatcap.org + + +
+ + + Keywords Patch + Labels/Tagging for emails + + + Patch + + + To check if Mutt supports Keywords, look for + patch-keywords in the mutt version. + See: . + + + + Dependencies: + mutt-1.5.24 + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + Unify label/keyword handling. + + + + Since x-labels were added to mutt in 2000, a number of other approaches + to what we now call tagging have also emerged. + One of them was even made standard in RFC 2822. + This update unifies the handling of all these strategies. + + + + We start by changing mutt's internal keyword storage from a single + string which may contain whitespace to a list of discrete keywords. + This has advantages for keyword completion as well as for portabilty + among varying "standards" for keyword storage. This may represent + a significant change for existing mutt users who have set x-labels + containing spaces, and should be regarded with suspicion. The + advantages are significant, though. + + + + Next we allow mutt to parse keywords into this internal list from + any of the following headers: X-Label (freeform), X-Keywords + (space-delimited), X-Mozilla-Keys (space-delimited), and Keywords (RFC + 2822, comma-space-delimited). Mutt remembers which headers it sourced + keywords from, and can rewrite those headers when saving messages for + compatibility with the mailer of origin. + + + + (X-Label was specified as freeform text by mutt, its only known + implementation. X-Labels have been used both as a + tagging device, probably with space delimiting, and as a + memo field, where space-delimited parsing would ruin the + semantics of the memo. By default mutt will not split X-Labels at all. + Set $xlabel_delimiter if your needs vary.) + + + + Finally we add two booleans: $keywords_legacy=true and + $keywords_standard=FALSE. When $keywords_legacy is true, mutt will + always save keyword to whatever original header it came from. When + $keywords_standard=true, mutt will save to the Keywords: header. If + both are true mutt saves to both; if neither is true, mutt saves only + to legacy headers to avoid complete loss of keywords. + + + + Overall this represents convergence path for all competing + labelling/tagging/keywording systems toward one that is specified by + RFC. + + + + You can change or delete the X-Label: field within + Mutt using the edit-label command, bound to the + y key by default. This works for tagged messages, too. + + + + + Variables + + + Keywords Variables + + + + Name + Type + Default + + + + + keywords_legacy + boolean + yes + + + keywords_standard + boolean + no + + + xlabel_delimiter + string + (empty) + + + +
+
+ + + Functions + + + Keyword Functions + + + + Menus + Default Key + Function + Description + + + + + index,pager + y + <edit-label> + add, change, or delete a message's label + + + +
+
+ + + + + Sort + + Keywords Sort + + + + Sort + Description + + + + + label + Sort by label + + + +
+
+ + + Muttrc + + + + See Also + + + NeoMutt Project + $index_format + index-color patch + folder-hook + + + + + Known Bugs + + + + Credits + + David Champion dgc@uchicago.edu + Richard Russon rich@flatcap.org + + +
+ ++ ++ NNTP Patch ++ Talk to a Usenet news server ++ ++ ++ Patch ++ ++ ++ To check if Mutt supports NNTP, look for ++ +USE_NNTP in the mutt version. ++ See: . ++ ++ ++ ++ Patch Dependencies: ++ mutt-1.5.24 ++ ++ ++ This patch is part of the NeoMutt project. ++ ++ ++ ++ Introduction ++ ++ ++ + Variables + + + + Functions + + + NNTP Functions + + + + Menus + Default Key + Function + Description + + + + + browser,index + y + <catchup> + mark all articles in newsgroup as read + + + index,pager + i + <change-newsgroup> + open a different newsgroup + + + pager + X + <change-vfolder> + open a different virtual folder + + + compose + o + <edit-followup-to> + edit the Followup-To field + + + compose + N + <edit-newsgroups> + edit the newsgroups list + + + compose + x + <edit-x-comment-to> + edit the X-Comment-To field + + + pager + + + <entire-thread> + read entire thread of the current message + + + attachment,index,pager + F + <followup-message> + followup to newsgroup + + + pager + ` + <modify-labels> + modify (notmuch) tags + + + index,pager + P + <post-message> + post message to newsgroup + + + browser + g + <reload-active> + load list of all newsgroups from NNTP server + + + browser + s + <subscribe> + subscribe to current mbox (IMAP/NNTP only) + + + browser + S + <subscribe-pattern> + subscribe to newsgroups matching a pattern + + + browser + Y + <uncatchup> + mark all articles in newsgroup as unread + + + browser + u + <unsubscribe> + unsubscribe from current mbox (IMAP/NNTP only) + + + browser + U + <unsubscribe-pattern> + unsubscribe from newsgroups matching a pattern + + + index,pager + Alt-i + <change-newsgroup-readonly> + open a different newsgroup in read only mode + + + attachment,index,pager + Alt-F + <forward-to-group> + forward to newsgroup + + + index + (none) + <get-children> + get all children of the current message + + + index + Alt-G + <get-parent> + get parent of the current message + + + index,pager + (none) + <imap-fetch-mail> + force retrieval of mail from IMAP server + + + index,pager + (none) + <imap-logout-all> + logout from all IMAP servers + + + pager + (none) + <modify-labels-then-hide> + modify labeld and then hide message + + + index + (none) + <reconstruct-thread> + reconstruct thread containing current message + + + pager + Alt-X + <vfolder-from-query> + generate virtual folder from query + + + index + Ctrl-G + <get-message> + get message with Message-Id + + + +
+
+ + + Commands + + + + Colors + None + + + + Sort + None + + + + Muttrc + + + + See Also + + + + Known Bugs + + + + Credits + + Vsevolod Volkov vvv@mutt.org.ua + Felix von Leitner leitner@fefe.de + Richard Russon rich@flatcap.org + + +
+ diff --cc functions.h index 506cad844,22c0de797..574742502 --- a/functions.h +++ b/functions.h @@@ -99,10 -103,17 +103,18 @@@ const struct binding_t OpMain[] = { /* { "delete-thread", OP_DELETE_THREAD, "\004" }, { "delete-subthread", OP_DELETE_SUBTHREAD, "\033d" }, { "edit", OP_EDIT_MESSAGE, "e" }, + { "edit-label", OP_EDIT_LABEL, "y" }, { "edit-type", OP_EDIT_TYPE, "\005" }, { "forward-message", OP_FORWARD_MESSAGE, "f" }, - { "flag-message", OP_FLAG_MESSAGE, "F" }, + #ifdef USE_NNTP + { "forward-to-group", OP_FORWARD_TO_GROUP, "\033F" }, + { "followup-message", OP_FOLLOWUP, "F" }, + { "get-children", OP_GET_CHILDREN, NULL }, + { "get-message", OP_GET_MESSAGE, "\007" }, + { "get-parent", OP_GET_PARENT, "\033G" }, + { "reconstruct-thread", OP_RECONSTRUCT_THREAD, NULL }, + #endif + { "flag-message", OP_FLAG_MESSAGE, "\033f" }, { "group-reply", OP_GROUP_REPLY, "g" }, #ifdef USE_POP { "fetch-mail", OP_MAIN_FETCH_MAIL, "G" }, @@@ -209,10 -210,13 +232,14 @@@ const struct binding_t OpPager[] = { / { "set-flag", OP_MAIN_SET_FLAG, "w" }, { "clear-flag", OP_MAIN_CLEAR_FLAG, "W" }, { "edit", OP_EDIT_MESSAGE, "e" }, + { "edit-label", OP_EDIT_LABEL, "y" }, { "edit-type", OP_EDIT_TYPE, "\005" }, + #ifdef USE_NNTP + { "followup-message", OP_FOLLOWUP, "F" }, + { "forward-to-group", OP_FORWARD_TO_GROUP, "\033F" }, + #endif { "forward-message", OP_FORWARD_MESSAGE, "f" }, - { "flag-message", OP_FLAG_MESSAGE, "F" }, + { "flag-message", OP_FLAG_MESSAGE, "\033f" }, { "group-reply", OP_GROUP_REPLY, "g" }, #ifdef USE_IMAP { "imap-fetch-mail", OP_MAIN_IMAP_FETCH, NULL }, @@@ -234,9 -238,11 +261,12 @@@ { "sort-mailbox", OP_SORT, "o" }, { "sort-reverse", OP_SORT_REVERSE, "O" }, { "print-message", OP_PRINT, "p" }, + #ifdef USE_NNTP + { "post-message", OP_POST, "P" }, + #endif { "previous-thread", OP_MAIN_PREV_THREAD, "\020" }, { "previous-subthread",OP_MAIN_PREV_SUBTHREAD, "\033p" }, + { "purge-message", OP_PURGE_MESSAGE, NULL }, { "quit", OP_QUIT, "Q" }, { "exit", OP_EXIT, "q" }, { "reply", OP_REPLY, "r" }, diff --cc hcache.c index d91b9c645,0299850ad..2f4b71d0b --- a/hcache.c +++ b/hcache.c @@@ -445,8 -446,13 +445,14 @@@ dump_envelope(ENVELOPE * e, unsigned ch d = dump_list(e->references, d, off, 0); d = dump_list(e->in_reply_to, d, off, 0); d = dump_list(e->userhdrs, d, off, convert); + d = dump_list(e->labels, d, off, convert); + #ifdef USE_NNTP + d = dump_char(e->xref, d, off, 0); + d = dump_char(e->followup_to, d, off, 0); + d = dump_char(e->x_comment_to, d, off, convert); + #endif + return d; } @@@ -482,7 -489,12 +488,13 @@@ restore_envelope(ENVELOPE * e, const un restore_list(&e->references, d, off, 0); restore_list(&e->in_reply_to, d, off, 0); restore_list(&e->userhdrs, d, off, convert); + restore_list(&e->labels, d, off, convert); + + #ifdef USE_NNTP + restore_char(&e->xref, d, off, 0); + restore_char(&e->followup_to, d, off, 0); + restore_char(&e->x_comment_to, d, off, convert); + #endif } static int diff --cc hdrline.c index ffa99b757,9bd90d704..e8aeba600 --- a/hdrline.c +++ b/hdrline.c @@@ -247,9 -211,8 +247,10 @@@ int mutt_user_is_recipient (HEADER *h * %E = number of messages in current thread * %f = entire from line * %F = like %n, unless from self + * %g = message labels (e.g. notmuch tags) + * %g = newsgroup name (if compiled with NNTP support) * %i = message-id + * %I = initials of author * %l = number of lines in the message * %L = like %F, except `lists' are displayed first * %m = number of messages in the mailbox @@@ -616,6 -462,12 +619,12 @@@ hdr_format_str (char *dest break; + #ifdef USE_NNTP - case 'g': ++ case 'q': + mutt_format_s (dest, destlen, prefix, hdr->env->newsgroups ? hdr->env->newsgroups : ""); + break; + #endif + case 'i': mutt_format_s (dest, destlen, prefix, hdr->env->message_id ? hdr->env->message_id : ""); break; diff --cc init.h index 25b127c18,f25884472..94f2128a0 --- a/init.h +++ b/init.h @@@ -1316,7 -1367,7 +1368,8 @@@ struct option_t MuttVars[] = ** .dt %E .dd number of messages in current thread ** .dt %f .dd sender (address + real name), either From: or Return-Path: ** .dt %F .dd author name, or recipient name if the message is from you + ** .dt %g .dd message labels (e.g. notmuch tags) + ** .dt %g .dd newsgroup name (if compiled with NNTP support) ** .dt %H .dd spam attribute(s) of this message ** .dt %i .dd message-id of the current message ** .dt %l .dd number of lines in the message (does not work with maildir, @@@ -1691,59 -1746,105 +1774,159 @@@ ** See also $$read_inc, $$write_inc and $$net_inc. */ #endif + #ifdef USE_NNTP + { "news_cache_dir", DT_PATH, R_NONE, UL &NewsCacheDir, UL "~/.mutt" }, + /* + ** .pp + ** This variable pointing to directory where Mutt will save cached news + ** articles and headers in. If \fIunset\fP, articles and headers will not be + ** saved at all and will be reloaded from the server each time. + */ + { "news_server", DT_STR, R_NONE, UL &NewsServer, 0 }, + /* + ** .pp + ** This variable specifies domain name or address of NNTP server. It + ** defaults to the news server specified in the environment variable + ** $$$NNTPSERVER or contained in the file /etc/nntpserver. You can also + ** specify username and an alternative port for each news server, ie: + ** .pp + ** [[s]news://][username[:password]@]server[:port] + */ + { "newsgroups_charset", DT_STR, R_NONE, UL &NewsgroupsCharset, UL "utf-8" }, + /* + ** .pp + ** Character set of newsgroups descriptions. + */ + { "newsrc", DT_PATH, R_NONE, UL &NewsRc, UL "~/.newsrc" }, + /* + ** .pp + ** The file, containing info about subscribed newsgroups - names and + ** indexes of read articles. The following printf-style sequence + ** is understood: + ** .dl + ** .dt %a .dd account url + ** .dt %p .dd port + ** .dt %P .dd port if specified + ** .dt %s .dd news server name + ** .dt %S .dd url schema + ** .dt %u .dd username + ** .de + */ + { "nntp_authenticators", DT_STR, R_NONE, UL &NntpAuthenticators, UL 0 }, + /* + ** .pp + ** This is a colon-delimited list of authentication methods mutt may + ** attempt to use to log in to a news server, in the order mutt should + ** try them. Authentication methods are either ``user'' or any + ** SASL mechanism, e.g. ``digest-md5'', ``gssapi'' or ``cram-md5''. + ** This option is case-insensitive. If it's \fIunset\fP (the default) + ** mutt will try all available methods, in order from most-secure to + ** least-secure. + ** .pp + ** Example: + ** .ts + ** set nntp_authenticators="digest-md5:user" + ** .te + ** .pp + ** \fBNote:\fP Mutt will only fall back to other authentication methods if + ** the previous methods are unavailable. If a method is available but + ** authentication fails, mutt will not connect to the IMAP server. + */ + { "nntp_context", DT_NUM, R_NONE, UL &NntpContext, 1000 }, + /* + ** .pp + ** This variable defines number of articles which will be in index when + ** newsgroup entered. If active newsgroup have more articles than this + ** number, oldest articles will be ignored. Also controls how many + ** articles headers will be saved in cache when you quit newsgroup. + */ + { "nntp_listgroup", DT_BOOL, R_NONE, OPTLISTGROUP, 1 }, + /* + ** .pp + ** This variable controls whether or not existence of each article is + ** checked when newsgroup is entered. + */ + { "nntp_load_description", DT_BOOL, R_NONE, OPTLOADDESC, 1 }, + /* + ** .pp + ** This variable controls whether or not descriptions for each newsgroup + ** must be loaded when newsgroup is added to list (first time list + ** loading or new newsgroup adding). + */ + { "nntp_user", DT_STR, R_NONE, UL &NntpUser, UL "" }, + /* + ** .pp + ** Your login name on the NNTP server. If \fIunset\fP and NNTP server requires + ** authentification, Mutt will prompt you for your account name when you + ** connect to news server. + */ + { "nntp_pass", DT_STR, R_NONE, UL &NntpPass, UL "" }, + /* + ** .pp + ** Your password for NNTP account. + */ + { "nntp_poll", DT_NUM, R_NONE, UL &NewsPollTimeout, 60 }, + /* + ** .pp + ** The time in seconds until any operations on newsgroup except post new + ** article will cause recheck for new news. If set to 0, Mutt will + ** recheck newsgroup on each operation in index (stepping, read article, + ** etc.). + */ ++#endif +#ifdef USE_NOTMUCH + { "nm_open_timeout", DT_NUM, R_NONE, UL &NotmuchOpenTimeout, 5 }, + /* + ** .pp + ** This variable specifies the timeout for database open in seconds. + */ + + { "nm_default_uri", DT_STR, R_NONE, UL &NotmuchDefaultUri, 0 }, + /* + ** .pp + ** This variable specifies the default Notmuch database in format + ** notmuch://. + */ + + { "nm_hidden_tags", DT_STR, R_NONE, UL &NotmuchHiddenTags, UL "unread,draft,flagged,passed,replied,attachment,signed,encrypted" }, + /* + ** .pp + ** This variable specifies private notmuch tags which should not be printed + ** on screen. + */ + { "nm_exclude_tags", DT_STR, R_NONE, UL &NotmuchExcludeTags, 0 }, + /* + ** .pp + ** The messages tagged with these tags are excluded and not loaded + ** from notmuch DB to mutt unless specified explicitly. + */ + { "nm_unread_tag", DT_STR, R_NONE, UL &NotmuchUnreadTag, UL "unread" }, + /* + ** .pp + ** This variable specifies notmuch tag which is used for unread messages. The + ** variable is used to count unread messages in DB only. All other mutt commands + ** use standard (e.g. maildir) flags. + */ + { "nm_db_limit", DT_NUM, R_NONE, UL &NotmuchDBLimit, 0 }, + /* + ** .pp + ** This variable specifies the default limit used in notmuch queries. + */ + { "nm_query_type", DT_STR, R_NONE, UL &NotmuchQueryType, UL "messages" }, + /* + ** .pp + ** This variable specifies the default query type (threads or messages) used in notmuch queries. + */ + { "nm_record", DT_BOOL, R_NONE, OPTNOTMUCHRECORD, 0 }, + /* + ** .pp + ** This variable specifies if the mutt record should indexed by notmuch. + */ + { "nm_record_tags", DT_STR, R_NONE, UL &NotmuchRecordTags, 0 }, + /* + ** .pp + ** This variable specifies the default tags applied to messages stored to the mutt record. + */ #endif { "pager", DT_PATH, R_NONE, UL &Pager, UL "builtin" }, /* @@@ -2747,145 -2858,27 +2940,167 @@@ ** Command to use when spawning a subshell. By default, the user's login ** shell from \fC/etc/passwd\fP is used. */ + #ifdef USE_NNTP + { "save_unsubscribed", DT_BOOL, R_NONE, OPTSAVEUNSUB, 0 }, + /* + ** .pp + ** When \fIset\fP, info about unsubscribed newsgroups will be saved into + ** ``newsrc'' file and into cache. + */ + { "show_new_news", DT_BOOL, R_NONE, OPTSHOWNEWNEWS, 1 }, + /* + ** .pp + ** If \fIset\fP, news server will be asked for new newsgroups on entering + ** the browser. Otherwise, it will be done only once for a news server. + ** Also controls whether or not number of new articles of subscribed + ** newsgroups will be then checked. + */ + { "show_only_unread", DT_BOOL, R_NONE, OPTSHOWONLYUNREAD, 0 }, + /* + ** .pp + ** If \fIset\fP, only subscribed newsgroups that contain unread articles + ** will be displayed in browser. + */ ++#endif +#ifdef USE_SIDEBAR + { "sidebar_divider_char", DT_STR, R_BOTH, UL &SidebarDividerChar, UL "|" }, + /* + ** .pp + ** This specifies the characters to be drawn between the sidebar (when + ** visible) and the other Mutt panels. ASCII and Unicode line-drawing + ** characters are supported. + */ + { "sidebar_delim_chars", DT_STR, R_NONE, UL &SidebarDelimChars, UL "/." }, + /* + ** .pp + ** This contains the list of characters which you would like to treat + ** as folder separators for displaying paths in the sidebar. + ** .pp + ** Local mail is often arranged in directories: `dir1/dir2/mailbox'. + ** .ts + ** set sidebar_delim_chars='/' + ** .te + ** IMAP mailboxes are often named: `folder1.folder2.mailbox'. + ** .ts + ** set sidebar_delim_chars='.' + ** .te + ** .pp + ** \fBSee also:\fP $$sidebar_short_path, $$sidebar_folder_indent, $$sidebar_indent_string. + */ + { "sidebar_folder_indent", DT_BOOL, R_BOTH, OPTSIDEBARFOLDERINDENT, 0 }, + /* + ** .pp + ** Set this to indent mailboxes in the sidebar. + ** .pp + ** \fBSee also:\fP $$sidebar_short_path, $$sidebar_indent_string, $$sidebar_delim_chars. + */ + { "sidebar_format", DT_STR, R_NONE, UL &SidebarFormat, UL "%B%?F? [%F]?%* %?N?%N/?%S" }, + /* + ** .pp + ** This variable allows you to customize the sidebar display. This string is + ** similar to $$index_format, but has its own set of \fCprintf(3)\fP-like + ** sequences: + ** .dl + ** .dt %B .dd Name of the mailbox + ** .dt %S .dd * Size of mailbox (total number of messages) + ** .dt %N .dd * Number of New messages in the mailbox + ** .dt %F .dd * Number of Flagged messages in the mailbox + ** .dt %! .dd ``!'' : one flagged message; + ** ``!!'' : two flagged messages; + ** ``n!'' : n flagged messages (for n > 2). + ** Otherwise prints nothing. + ** .dt %d .dd * @ Number of deleted messages + ** .dt %L .dd * @ Number of messages after limiting + ** .dt %t .dd * @ Number of tagged messages + ** .dt %>X .dd right justify the rest of the string and pad with ``X'' + ** .dt %|X .dd pad to the end of the line with ``X'' + ** .dt %*X .dd soft-fill with character ``X'' as pad + ** .de + ** .pp + ** * = Can be optionally printed if nonzero + ** @ = Only applicable to the current folder + */ + { "sidebar_indent_string", DT_STR, R_BOTH, UL &SidebarIndentString, UL " " }, + /* + ** .pp + ** This specifies the string that is used to indent mailboxes in the sidebar. + ** It defaults to two spaces. + ** .pp + ** \fBSee also:\fP $$sidebar_short_path, $$sidebar_folder_indent, $$sidebar_delim_chars. + */ + { "sidebar_new_mail_only", DT_BOOL, R_BOTH, OPTSIDEBARNEWMAILONLY, 0 }, + /* + ** .pp + ** When set, the sidebar will only display mailboxes containing new, or + ** flagged, mail. + ** .pp + ** \fBSee also:\fP $sidebar_whitelist. + */ + { "sidebar_next_new_wrap", DT_BOOL, R_BOTH, UL OPTSIDEBARNEXTNEWWRAP, 0 }, + /* + ** .pp + ** When set, the \fC\fP command will not stop and the end of + ** the list of mailboxes, but wrap around to the beginning. The + ** \fC\fP command is similarly affected, wrapping around to + ** the end of the list. + */ + { "sidebar_refresh_time", DT_NUM, R_BOTH, UL &SidebarRefreshTime, 60 }, + /* + ** .pp + ** Set sidebar_refresh_time to the minimum number of seconds between refreshes. + ** This will reduced network traffic. + ** .pp + ** \fBNote:\fP Set to 0 to disable refreshing. + */ + { "sidebar_short_path", DT_BOOL, R_BOTH, OPTSIDEBARSHORTPATH, 0 }, + /* + ** .pp + ** By default the sidebar will show the mailbox's path, relative to the + ** $$folder variable. Setting \fCsidebar_shortpath=yes\fP will shorten the + ** names relative to the previous name. Here's an example: + ** .dl + ** .dt \fBshortpath=no\fP .dd \fBshortpath=yes\fP .dd \fBshortpath=yes, folderindent=yes, indentstr=".."\fP + ** .dt \fCfruit\fP .dd \fCfruit\fP .dd \fCfruit\fP + ** .dt \fCfruit.apple\fP .dd \fCapple\fP .dd \fC..apple\fP + ** .dt \fCfruit.banana\fP .dd \fCbanana\fP .dd \fC..banana\fP + ** .dt \fCfruit.cherry\fP .dd \fCcherry\fP .dd \fC..cherry\fP + ** .de + ** .pp + ** \fBSee also:\fP $$sidebar_delim_chars, $$sidebar_folder_indent, $$sidebar_indent_string. + */ + { "sidebar_sort_method", DT_SORT|DT_SORT_SIDEBAR, R_NONE, UL &SidebarSortMethod, SORT_ORDER }, + /* + ** .pp + ** Specifies how to sort entries in the file browser. By default, the + ** entries are sorted alphabetically. Valid values: + ** .il + ** .dd alpha (alphabetically) + ** .dd count (all message count) + ** .dd date + ** .dd desc (description) + ** .dd new (new message count) + ** .dd size + ** .dd unsorted + ** .ie + ** .pp + ** You may optionally use the ``reverse-'' prefix to specify reverse sorting + ** order (example: ``\fCset sort_browser=reverse-date\fP''). + */ + { "sidebar_visible", DT_BOOL, R_BOTH, OPTSIDEBAR, 0 }, + /* + ** .pp + ** This specifies whether or not to show sidebar. The sidebar shows a list of + ** all your mailboxes. + ** .pp + ** \fBSee also:\fP $$sidebar_format, $$sidebar_width + */ + { "sidebar_width", DT_NUM, R_BOTH, UL &SidebarWidth, 0 }, + /* + ** .pp + ** This controls the width of the sidebar. It is measured in screen columns. + ** For example: sidebar_width=20 could display 20 ASCII characters, or 10 + ** Chinese characters. + */ #endif { "sig_dashes", DT_BOOL, R_NONE, OPTSIGDASHES, 1 }, /* @@@ -3857,20 -3805,14 +4072,28 @@@ {"xterm_set_titles", DT_SYN, R_NONE, UL "ts_enabled", 0 }, /* */ + { "xlabel_delimiter", DT_STR, R_NONE, UL &XlabelDelim, UL "" }, + /* + ** .pp + ** The character used to delimit distinct keywords in X-Label headers. + ** X-Label is primarily a Mutt artifact, and the semantics of the field + ** were never defined: it is free-form text. However interaction with + ** X-Keywords:, X-Mozilla-Keys:, and Keywords: requires that we adopt + ** some means of identifying separate keywords within the field. Set + ** this to your personal convention. + ** .pp + ** This affect both parsing existing X-Label headers and writing new + ** X-Label headers. You can modify this variable in runtime to accomplish + ** various kinds of conversion. + */ + #ifdef USE_NNTP + { "x_comment_to", DT_BOOL, R_NONE, OPTXCOMMENTTO, 0 }, + /* + ** .pp + ** If \fIset\fP, Mutt will add ``X-Comment-To:'' field (that contains full + ** name of original article author) to article that followuped to newsgroup. + */ + #endif /*--*/ { NULL, 0, 0, 0, 0 } }; diff --cc main.c index 561e892e4,3182c1b0e..5a019706e --- a/main.c +++ b/main.c @@@ -66,6 -62,50 +66,10 @@@ #include #endif + #ifdef USE_NNTP + #include "nntp.h" + #endif + -static const char *ReachingUs = N_("\ -To contact the developers, please mail to .\n\ -To report a bug, please visit http://bugs.mutt.org/.\n"); - -static const char *Notice = N_("\ -Copyright (C) 1996-2016 Michael R. Elkins and others.\n\ -Mutt comes with ABSOLUTELY NO WARRANTY; for details type `mutt -vv'.\n\ -Mutt is free software, and you are welcome to redistribute it\n\ -under certain conditions; type `mutt -vv' for details.\n"); - -static const char *Copyright = N_("\ -Copyright (C) 1996-2014 Michael R. Elkins \n\ -Copyright (C) 1996-2002 Brandon Long \n\ -Copyright (C) 1997-2009 Thomas Roessler \n\ -Copyright (C) 1998-2005 Werner Koch \n\ -Copyright (C) 1999-2014 Brendan Cully \n\ -Copyright (C) 1999-2002 Tommi Komulainen \n\ -Copyright (C) 2000-2004 Edmund Grimley Evans \n\ -Copyright (C) 2006-2009 Rocco Rutte \n\ -Copyright (C) 2014-2015 Kevin J. McCarthy \n\ -\n\ -Many others not mentioned here contributed code, fixes,\n\ -and suggestions.\n"); - -static const char *Licence = N_("\ - This program is free software; you can redistribute it and/or modify\n\ - it under the terms of the GNU General Public License as published by\n\ - the Free Software Foundation; either version 2 of the License, or\n\ - (at your option) any later version.\n\ -\n\ - This program is distributed in the hope that it will be useful,\n\ - but WITHOUT ANY WARRANTY; without even the implied warranty of\n\ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\ - GNU General Public License for more details.\n"); -static const char *Obtaining = N_("\ - You should have received a copy of the GNU General Public License\n\ - along with this program; if not, write to the Free Software\n\ - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n\ -"); - void mutt_exit (int code) { mutt_endwin (NULL); @@@ -797,17 -1227,17 +836,26 @@@ int main (int argc, char **argv if (!folder[0]) strfcpy (folder, NONULL(Spoolfile), sizeof (folder)); + + #ifdef USE_NNTP + if (option (OPTNEWS)) + { + unset_option (OPTNEWS); + nntp_expand_path (folder, sizeof (folder), &CurrentNewsSrv->conn->account); + } + else + #endif mutt_expand_path (folder, sizeof (folder)); +#ifdef USE_SIDEBAR + { + char tmpfolder[PATH_MAX] = ""; + strfcpy (tmpfolder, folder, sizeof (tmpfolder)); + if (!realpath (tmpfolder, folder)) + strfcpy (folder, tmpfolder, sizeof (tmpfolder)); + } +#endif + mutt_str_replace (&CurrentFolder, folder); mutt_str_replace (&LastFolder, folder); diff --cc mutt.h index bdef33f54,fb2ac1ac3..405cb0619 --- a/mutt.h +++ b/mutt.h @@@ -250,10 -223,10 +250,13 @@@ enu M_CRYPT_ENCRYPT, M_PGP_KEY, M_XLABEL, +#ifdef USE_NOTMUCH + M_NOTMUCH_LABEL, +#endif M_MIMEATTACH, + #ifdef USE_NNTP + M_NEWSGROUPS, + #endif /* Options for Mailcap lookup */ M_EDIT, @@@ -567,10 -547,10 +593,14 @@@ enu OPTDONTHANDLEPGPKEYS, /* (pseudo) used to extract PGP keys */ OPTIGNOREMACROEVENTS, /* (pseudo) don't process macro/push/exec events while set */ +#ifdef USE_NOTMUCH + OPTVIRTSPOOLFILE, + OPTNOTMUCHRECORD, +#endif + #ifdef USE_NNTP + OPTNEWS, /* (pseudo) used to change reader mode */ + OPTNEWSSEND, /* (pseudo) used to change behavior when posting */ + #endif OPTMAX }; @@@ -840,9 -822,8 +878,9 @@@ typedef struct heade int refno; /* message number on server */ #endif - #if defined USE_POP || defined USE_IMAP || defined USE_NOTMUCH -#if defined USE_POP || defined USE_IMAP || defined USE_NNTP ++#if defined USE_POP || defined USE_IMAP || defined USE_NOTMUCH || defined USE_NNTP void *data; /* driver-specific data */ + void (*free_cb)(struct header *); /* driver-specific data free function */ #endif char *maildir_flags; /* unknown maildir flags */ diff --cc muttlib.c index 5b4f4dde3,3b17b490d..5457f2b46 --- a/muttlib.c +++ b/muttlib.c @@@ -336,9 -329,7 +336,9 @@@ void mutt_free_header (HEADER **h #ifdef MIXMASTER mutt_free_list (&(*h)->chain); #endif - #if defined USE_POP || defined USE_IMAP || defined USE_NOTMUCH -#if defined USE_POP || defined USE_IMAP || defined USE_NNTP ++#if defined USE_POP || defined USE_IMAP || defined USE_NOTMUCH || defined USE_NNTP + if ((*h)->free_cb) + (*h)->free_cb(*h); FREE (&(*h)->data); #endif FREE (h); /* __FREE_CHECKED__ */ diff --cc mx.c index 9a76313f3,3fee78c64..c06390449 --- a/mx.c +++ b/mx.c @@@ -45,10 -38,10 +45,14 @@@ #include "pop.h" #endif +#ifdef USE_NOTMUCH +#include "mutt_notmuch.h" +#endif + + #ifdef USE_NNTP + #include "nntp.h" + #endif + #include "buffy.h" #ifdef USE_DOTLOCK @@@ -358,24 -347,22 +362,40 @@@ int mx_is_pop (const char *p } #endif + #ifdef USE_NNTP + int mx_is_nntp (const char *p) + { + url_scheme_t scheme; + + if (!p) + return 0; + + scheme = url_check_scheme (p); + if (scheme == U_NNTP || scheme == U_NNTPS) + return 1; + + return 0; + } + #endif + +#ifdef USE_NOTMUCH + +int mx_is_notmuch(const char *p) +{ + url_scheme_t scheme; + + if (!p) + return 0; + + scheme = url_check_scheme (p); + if (scheme == U_NOTMUCH) + return 1; + + return 0; +} + +#endif + int mx_get_magic (const char *path) { struct stat st; @@@ -393,11 -380,11 +413,16 @@@ return M_POP; #endif /* USE_POP */ +#ifdef USE_NOTMUCH + if (mx_is_notmuch(path)) + return M_NOTMUCH; +#endif + + #ifdef USE_NNTP + if (mx_is_nntp (path)) + return M_NNTP; + #endif /* USE_NNTP */ + if (stat (path, &st) == -1) { dprint (1, (debugfile, "mx_get_magic(): unable to stat %s: %s (errno %d).\n", @@@ -727,12 -693,12 +752,18 @@@ CONTEXT *mx_open_mailbox (const char *p break; #endif /* USE_POP */ +#ifdef USE_NOTMUCH + case M_NOTMUCH: + rc = nm_read_query (ctx); + break; +#endif /* USE_IMAP */ + + #ifdef USE_NNTP + case M_NNTP: + rc = nntp_open_mailbox (ctx); + break; + #endif /* USE_NNTP */ + default: rc = -1; break; @@@ -851,12 -796,11 +882,17 @@@ static int sync_mailbox (CONTEXT *ctx, break; #endif /* USE_POP */ +#ifdef USE_NOTMUCH + case M_NOTMUCH: + rc = nm_sync (ctx, index_hint); + break; +#endif /* USE_NOTMUCH */ + + #ifdef USE_NNTP + case M_NNTP: + rc = nntp_sync_mailbox (ctx); + break; + #endif /* USE_NNTP */ } #if 0 @@@ -967,14 -868,14 +1022,20 @@@ int mx_close_mailbox (CONTEXT *ctx, in if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->read && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) read_msgs++; +#ifdef USE_SIDEBAR + if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->read) + ctx->unread--; + if (ctx->hdrs[i]->deleted && ctx->hdrs[i]->flagged) + ctx->flagged--; +#endif } + #ifdef USE_NNTP + /* don't need to move articles from newsgroup */ + if (ctx->magic == M_NNTP) + read_msgs = 0; + #endif + if (read_msgs && quadoption (OPT_MOVE) != M_NO) { char *p; @@@ -1537,10 -1412,10 +1598,15 @@@ int mx_check_mailbox (CONTEXT *ctx, in return (pop_check_mailbox (ctx, index_hint)); #endif /* USE_POP */ +#ifdef USE_NOTMUCH + case M_NOTMUCH: + return nm_check_database(ctx, index_hint); +#endif ++ + #ifdef USE_NNTP + case M_NNTP: + return (nntp_check_mailbox (ctx, 0)); + #endif /* USE_NNTP */ } } @@@ -1689,8 -1560,10 +1764,11 @@@ int mx_close_message (MESSAGE **msg int r = 0; if ((*msg)->magic == M_MH || (*msg)->magic == M_MAILDIR - || (*msg)->magic == M_IMAP || (*msg)->magic == M_POP - || (*msg)->magic == M_NOTMUCH) + #ifdef USE_NNTP + || (*msg)->magic == M_NNTP + #endif ++ || (*msg)->magic == M_NOTMUCH + || (*msg)->magic == M_IMAP || (*msg)->magic == M_POP) { r = safe_fclose (&(*msg)->fp); } diff --cc mx.h index 2920dc2fd,75be3f3a1..a0275e08d --- a/mx.h +++ b/mx.h @@@ -35,12 -34,11 +35,15 @@@ enu M_MMDF, M_MH, M_MAILDIR, + #ifdef USE_NNTP + M_NNTP, + #endif M_IMAP, + M_NOTMUCH, M_POP +#ifdef USE_COMPRESSED + , M_COMPRESSED +#endif }; WHERE short DefaultMagic INITVAL (M_MBOX); diff --cc parse.c index b02a044bb,cb3ea3065..afee665c6 --- a/parse.c +++ b/parse.c @@@ -1275,17 -1299,25 +1307,31 @@@ int mutt_parse_rfc822_line (ENVELOPE *e } else if (ascii_strcasecmp (line+1, "-label") == 0) { - FREE(&e->x_label); - e->x_label = safe_strdup(p); - matched = 1; + kwtype = M_X_LABEL; + } + else if (!ascii_strcasecmp (line+1, "-keywords")) + { + kwtype = M_X_KEYWORDS; + } + else if (!ascii_strcasecmp (line+1, "-mozilla-keys")) + { + kwtype = M_X_MOZILLA_KEYS; } + #ifdef USE_NNTP + else if (!mutt_strcasecmp (line + 1, "-comment-to")) + { + if (!e->x_comment_to) + e->x_comment_to = safe_strdup (p); + matched = 1; + } + else if (!mutt_strcasecmp (line + 1, "ref")) + { + if (!e->xref) + e->xref = safe_strdup (p); + matched = 1; + } + #endif - + default: break; } diff --cc send.c index 3cbf81b69,48c6f982b..a00ccb4f3 --- a/send.c +++ b/send.c @@@ -1906,13 -2037,13 +2044,18 @@@ full_fcc goto cleanup; } } - else if (!option (OPTNOCURSES) && ! (flags & SENDMAILX)) + else if (!option (OPTNOCURSES) && ! (flags & SENDMAILX)) { - mutt_message (i == 0 ? _("Mail sent.") : _("Sending in background.")); + mutt_message (i != 0 ? _("Sending in background.") : + #ifdef USE_NNTP + (flags & SENDNEWS) ? _("Article posted.") : _("Mail sent.")); + #else + _("Mail sent.")); + #endif +#ifdef USE_NOTMUCH + if (option(OPTNOTMUCHRECORD)) + nm_record_message(ctx, finalpath, cur); +#endif + } if (WithCrypto && (msg->security & ENCRYPT)) FREE (&pgpkeylist); diff --cc sendlib.c index 5cf9e5750,66922979a..ccaea8ac0 --- a/sendlib.c +++ b/sendlib.c @@@ -2483,8 -2556,12 +2550,11 @@@ void mutt_prepare_envelope (ENVELOPE *e rfc2047_encode_adrlist (env->from, "From"); rfc2047_encode_adrlist (env->mail_followup_to, "Mail-Followup-To"); rfc2047_encode_adrlist (env->reply_to, "Reply-To"); - rfc2047_encode_string (&env->x_label); if (env->subject) + #ifdef USE_NNTP + if (!option (OPTNEWSSEND) || option (OPTMIMESUBJECT)) + #endif { rfc2047_encode_string (&env->subject); } diff --cc url.c index 51b1949fd,799e95619..d11b8d73a --- a/url.c +++ b/url.c @@@ -39,10 -39,9 +39,12 @@@ static const struct mapping_t UrlMap[] { "imaps", U_IMAPS }, { "pop", U_POP }, { "pops", U_POPS }, + { "news", U_NNTP }, + { "snews", U_NNTPS }, { "mailto", U_MAILTO }, +#ifdef USE_NOTMUCH + { "notmuch", U_NOTMUCH }, +#endif { "smtp", U_SMTP }, { "smtps", U_SMTPS }, { NULL, U_UNKNOWN } diff --cc version.c index c6cdce3fd,000000000..bc3546fbb mode 100644,000000..100644 --- a/version.c +++ b/version.c @@@ -1,511 -1,0 +1,516 @@@ +/** + * Copyright (C) 1996-2007 Michael R. Elkins + * Copyright (C) 1999-2007 Thomas Roessler + * Copyright (C) 2016 Richard Russon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#ifdef HAVE_STRINGPREP_H +#include +#elif defined (HAVE_IDN_STRINGPREP_H) +#include +#endif +#ifdef USE_SLANG_CURSES +#include "slang.h" +#endif + +#include "lib.h" + +// #include "protos.h" +const char * mutt_make_version (void); +void mutt_print_patchlist (void); + +// #include "hcache.h" +const char * mutt_hcache_backend (void); + +const int SCREEN_WIDTH = 80; + +extern const char cc_version[]; +extern const char cc_cflags[]; +extern const char configure_options[]; + +static const char *Copyright = N_( + "Copyright (C) 1996-2014 Michael R. Elkins \n" + "Copyright (C) 1996-2002 Brandon Long \n" + "Copyright (C) 1997-2009 Thomas Roessler \n" + "Copyright (C) 1998-2005 Werner Koch \n" + "Copyright (C) 1999-2014 Brendan Cully \n" + "Copyright (C) 1999-2002 Tommi Komulainen \n" + "Copyright (C) 2000-2004 Edmund Grimley Evans \n" + "Copyright (C) 2006-2009 Rocco Rutte \n" + "Copyright (C) 2014-2015 Kevin J. McCarthy \n" + "\n" + "Many others not mentioned here contributed code, fixes,\n" + "and suggestions.\n" +); + +static const char *License = N_( + " This program is free software; you can redistribute it and/or modify\n" + " it under the terms of the GNU General Public License as published by\n" + " the Free Software Foundation; either version 2 of the License, or\n" + " (at your option) any later version.\n" + "\n" + " This program is distributed in the hope that it will be useful,\n" + " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + " GNU General Public License for more details.\n" +); + +static const char *Obtaining = N_( + " You should have received a copy of the GNU General Public License\n" + " along with this program; if not, write to the Free Software\n" + " Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n" +); + +static const char *ReachingUs = N_( + "To learn more about NeoMutt, visit: http://www.neomutt.org/\n" + "If you find a bug in NeoMutt, please raise an issue at:\n" + " https://github.com/neomutt/neomutt/issues\n" + "or contact the lead developer: Richard Russon \n" +); + +static const char *Notice = N_( + "Copyright (C) 1996-2016 Michael R. Elkins and others.\n" + "Mutt comes with ABSOLUTELY NO WARRANTY; for details type `mutt -vv'.\n" + "Mutt is free software, and you are welcome to redistribute it\n" + "under certain conditions; type `mutt -vv' for details.\n" +); + +struct compile_options { + const char *name; + int enabled; +}; + +static struct compile_options comp_opts[] = { +#ifdef CRYPT_BACKEND_CLASSIC_PGP + { "CRYPT_BACKEND_CLASSIC_PGP", 1 }, +#else + { "CRYPT_BACKEND_CLASSIC_PGP", 0 }, +#endif +#ifdef CRYPT_BACKEND_CLASSIC_SMIME + { "CRYPT_BACKEND_CLASSIC_SMIME", 1 }, +#else + { "CRYPT_BACKEND_CLASSIC_SMIME", 0 }, +#endif +#ifdef CRYPT_BACKEND_GPGME + { "CRYPT_BACKEND_GPGME", 1 }, +#else + { "CRYPT_BACKEND_GPGME", 0 }, +#endif +#ifdef DEBUG + { "DEBUG", 1 }, +#else + { "DEBUG", 0 }, +#endif +#ifdef DL_STANDALONE + { "DL_STANDALONE", 1 }, +#else + { "DL_STANDALONE", 0 }, +#endif +#ifdef ENABLE_NLS + { "ENABLE_NLS", 1 }, +#else + { "ENABLE_NLS", 0 }, +#endif +#ifdef EXACT_ADDRESS + { "EXACT_ADDRESS", 1 }, +#else + { "EXACT_ADDRESS", 0 }, +#endif +#ifdef HOMESPOOL + { "HOMESPOOL", 1 }, +#else + { "HOMESPOOL", 0 }, +#endif +#ifdef LOCALES_HACK + { "LOCALES_HACK", 1 }, +#else + { "LOCALES_HACK", 0 }, +#endif +#ifdef SUN_ATTACHMENT + { "SUN_ATTACHMENT", 1 }, +#else + { "SUN_ATTACHMENT", 0 }, +#endif +#ifdef HAVE_BKGDSET + { "HAVE_BKGDSET", 1 }, +#else + { "HAVE_BKGDSET", 0 }, +#endif +#ifdef HAVE_COLOR + { "HAVE_COLOR", 1 }, +#else + { "HAVE_COLOR", 0 }, +#endif +#ifdef HAVE_CURS_SET + { "HAVE_CURS_SET", 1 }, +#else + { "HAVE_CURS_SET", 0 }, +#endif +#ifdef HAVE_GETADDRINFO + { "HAVE_GETADDRINFO", 1 }, +#else + { "HAVE_GETADDRINFO", 0 }, +#endif +#ifdef HAVE_GETSID + { "HAVE_GETSID", 1 }, +#else + { "HAVE_GETSID", 0 }, +#endif +#ifdef HAVE_ICONV + { "HAVE_ICONV", 1 }, +#else + { "HAVE_ICONV", 0 }, +#endif +#ifdef HAVE_LANGINFO_CODESET + { "HAVE_LANGINFO_CODESET", 1 }, +#else + { "HAVE_LANGINFO_CODESET", 0 }, +#endif +#ifdef HAVE_LANGINFO_YESEXPR + { "HAVE_LANGINFO_YESEXPR", 1 }, +#else + { "HAVE_LANGINFO_YESEXPR", 0 }, +#endif +#ifdef HAVE_LIBIDN + { "HAVE_LIBIDN", 1 }, +#else + { "HAVE_LIBIDN", 0 }, +#endif +#ifdef HAVE_META + { "HAVE_META", 1 }, +#else + { "HAVE_META", 0 }, +#endif +#ifdef HAVE_REGCOMP + { "HAVE_REGCOMP", 1 }, +#else + { "HAVE_REGCOMP", 0 }, +#endif +#ifdef HAVE_RESIZETERM + { "HAVE_RESIZETERM", 1 }, +#else + { "HAVE_RESIZETERM", 0 }, +#endif +#ifdef HAVE_START_COLOR + { "HAVE_START_COLOR", 1 }, +#else + { "HAVE_START_COLOR", 0 }, +#endif +#ifdef HAVE_TYPEAHEAD + { "HAVE_TYPEAHEAD", 1 }, +#else + { "HAVE_TYPEAHEAD", 0 }, +#endif +#ifdef HAVE_WC_FUNCS + { "HAVE_WC_FUNCS", 1 }, +#else + { "HAVE_WC_FUNCS", 0 }, +#endif +#ifdef ICONV_NONTRANS + { "ICONV_NONTRANS", 1 }, +#else + { "ICONV_NONTRANS", 0 }, +#endif +#ifdef USE_COMPRESSED + { "USE_COMPRESSED", 1 }, +#else + { "USE_COMPRESSED", 0 }, +#endif +#ifdef USE_DOTLOCK + { "USE_DOTLOCK", 1 }, +#else + { "USE_DOTLOCK", 0 }, +#endif +#ifdef USE_FCNTL + { "USE_FCNTL", 1 }, +#else + { "USE_FCNTL", 0 }, +#endif +#ifdef USE_FLOCK + { "USE_FLOCK", 1 }, +#else + { "USE_FLOCK", 0 }, +#endif +#ifdef USE_GNU_REGEX + { "USE_GNU_REGEX", 1 }, +#else + { "USE_GNU_REGEX", 0 }, +#endif +#ifdef USE_GSS + { "USE_GSS", 1 }, +#else + { "USE_GSS", 0 }, +#endif +#ifdef USE_HCACHE + { "USE_HCACHE", 1 }, +#else + { "USE_HCACHE", 0 }, +#endif +#ifdef USE_IMAP + { "USE_IMAP", 1 }, +#else + { "USE_IMAP", 0 }, +#endif +#ifdef USE_NOTMUCH + { "USE_NOTMUCH", 1 }, +#else + { "USE_NOTMUCH", 0 }, +#endif ++#ifdef USE_NNTP ++ { "USE_NNTP", 1 }, ++#else ++ { "USE_NNTP", 0 }, ++#endif +#ifdef USE_POP + { "USE_POP", 1 }, +#else + { "USE_POP", 0 }, +#endif +#ifdef USE_SASL + { "USE_SASL", 1 }, +#else + { "USE_SASL", 0 }, +#endif +#ifdef USE_SETGID + { "USE_SETGID", 1 }, +#else + { "USE_SETGID", 0 }, +#endif +#ifdef USE_SIDEBAR + { "USE_SIDEBAR", 1 }, +#else + { "USE_SIDEBAR", 0 }, +#endif +#ifdef USE_SMTP + { "USE_SMTP", 1 }, +#else + { "USE_SMTP", 0 }, +#endif +#ifdef USE_SSL_GNUTLS + { "USE_SSL_GNUTLS", 1 }, +#else + { "USE_SSL_GNUTLS", 0 }, +#endif +#ifdef USE_SSL_OPENSSL + { "USE_SSL_OPENSSL", 1 }, +#else + { "USE_SSL_OPENSSL", 0 }, +#endif + { NULL, 0 } +}; + +/** + * print_compile_options - Print a list of enabled/disabled features + * + * The configure script lets uses enable/disable features. + * This shows the Mutt user which features are/aren't available. + * + * The output is of the form: "+ENABLED_FEATURE -DISABLED_FEATURE" and is + * wrapped to SCREEN_WIDTH characters. + */ +static void +print_compile_options (void) +{ + int i; + char c; + int len; + int used = 0; + + for (i = 0; comp_opts[i].name; i++) { + len = strlen (comp_opts[i].name) + 2; /* +/- and a space */ + if ((used + len) > SCREEN_WIDTH) { + used = 0; + puts (""); + } + used += len; + c = comp_opts[i].enabled ? '+' : '-'; + printf ("%c%s ", c, comp_opts[i].name); + } + puts (""); +} + +/** + * rstrip_in_place - Strip a trailing carriage return + * @s: String to be modified + * + * The string has its last carriage return set to NUL. + * Returns: + * The modified string + */ +static char * +rstrip_in_place (char *s) +{ + if (!s) + return NULL; + + char *p; + + p = &s[strlen (s)]; + if (p == s) + return s; + p--; + while ((p >= s) && ((*p == '\n') || (*p == '\r'))) + *p-- = '\0'; + return s; +} + +/** + * print_version - Print system and compile info + * + * Print information about the current system Mutt is running on. + * Also print a list of all the compile-time information. + */ +void +print_version (void) +{ + struct utsname uts; + + puts (mutt_make_version()); + puts (_(Notice)); + + uname (&uts); + +#ifdef _AIX + printf ("System: %s %s.%s", uts.sysname, uts.version, uts.release); +#elif defined (SCO) + printf ("System: SCO %s", uts.release); +#else + printf ("System: %s %s", uts.sysname, uts.release); +#endif + + printf (" (%s)", uts.machine); + +#ifdef NCURSES_VERSION + printf ("\nncurses: %s (compiled with %s)", curses_version(), NCURSES_VERSION); +#elif defined (USE_SLANG_CURSES) + printf ("\nslang: %d", SLANG_VERSION); +#endif + +#ifdef _LIBICONV_VERSION + printf ("\nlibiconv: %d.%d", _LIBICONV_VERSION >> 8, + _LIBICONV_VERSION & 0xff); +#endif + +#ifdef HAVE_LIBIDN + printf ("\nlibidn: %s (compiled with %s)", stringprep_check_version (NULL), + STRINGPREP_VERSION); +#endif + +#ifdef USE_HCACHE + printf ("\nhcache backend: %s", mutt_hcache_backend()); +#endif + + puts ("\n\nCompiler:"); + rstrip_in_place ((char *) cc_version); + puts (cc_version); + + rstrip_in_place ((char *) configure_options); + printf ("\nConfigure options: %s\n", configure_options); + + rstrip_in_place ((char *) cc_cflags); + printf ("\nCompilation CFLAGS: %s\n", cc_cflags); + + puts (_("\nCompile options:")); + print_compile_options(); + +#ifdef DOMAIN + printf ("DOMAIN=\"%s\"\n", DOMAIN); +#else + puts ("-DOMAIN"); +#endif + +#ifdef MIXMASTER + printf ("MIXMASTER=\"%s\"\n", MIXMASTER); +#else + puts ("-MIXMASTER"); +#endif + +#ifdef ISPELL + printf ("ISPELL=\"%s\"\n", ISPELL); +#else + puts ("-ISPELL"); +#endif + + printf ("SENDMAIL=\"%s\"\n", SENDMAIL); + printf ("MAILPATH=\"%s\"\n", MAILPATH); + printf ("PKGDATADIR=\"%s\"\n", PKGDATADIR); + printf ("SYSCONFDIR=\"%s\"\n", SYSCONFDIR); + printf ("EXECSHELL=\"%s\"\n", EXECSHELL); + + puts (""); + mutt_print_patchlist(); + + puts (""); + puts (_(ReachingUs)); +} + +/** + * print_copyright - Print copyright message + * + * Print the authors' copyright messages, the GPL license and some contact + * information for the Mutt project. + */ +void +print_copyright (void) +{ + puts (mutt_make_version()); + puts (_(Copyright)); + puts (_(License)); + puts (_(Obtaining)); + puts (_(ReachingUs)); +} + +/** + * feature_enabled - Test is a compile-time feature is enabled + * @name: Compile-time symbol of the feature + * + * Many of the larger features of mutt can be disabled at compile time. + * They define a symbol and use #ifdef's around their code. + * The symbols are mirrored in "struct compile_options comp_opts[]" in this + * file. + * + * This function checks if one of these symbols is present in the code. + * + * These symbols are also seen in the output of "mutt -v". + * + * Returns: + * 1: Feature enables + * 0: Feature not enabled, or not compiled in + */ +int +feature_enabled (const char *name) +{ + if (!name) + return 0; + + int i; + for (i = 0; comp_opts[i].name; i++) { + if (mutt_strcmp (name, comp_opts[i].name) == 0) { + return 1; + } + } + return 0; +} +