Skip to content

Commit

Permalink
Support new email count.
Browse files Browse the repository at this point in the history
  • Loading branch information
elshize committed Jul 1, 2022
1 parent 0cf1981 commit a77e3b3
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 19 deletions.
5 changes: 4 additions & 1 deletion core/mailbox.h
Expand Up @@ -182,12 +182,15 @@ enum NotifyMailbox
NT_MAILBOX_NEW_MAIL, ///< New messages have been added
};

ARRAY_HEAD(EmailArray, struct Email *);

/**
* struct EventMailbox - An Event that happened to a Mailbox
*/
struct EventMailbox
{
struct Mailbox *mailbox; ///< The Mailbox this Event relates to
struct Mailbox *mailbox; ///< The Mailbox this Event relates to
struct EmailArray emails; ///< List of emails associated with the event
};

void mailbox_changed (struct Mailbox *m, enum NotifyMailbox action);
Expand Down
2 changes: 2 additions & 0 deletions docs/config.c
Expand Up @@ -986,6 +986,7 @@
** or when you save it to another folder.
*/

#ifdef USE_DEVEL_NEW_MAIL
{ "devel_new_mail_command", DT_COMMAND, 0 },
/*
** .pp
Expand All @@ -996,6 +997,7 @@
** .dt %f .dd Mailbox folder path
** .de
*/
#endif

{ "digest_collapse", DT_BOOL, true },
/*
Expand Down
2 changes: 2 additions & 0 deletions mutt_config.c
Expand Up @@ -407,9 +407,11 @@ static struct ConfigDef MainVars[] = {
{ "new_mail_command", DT_STRING|DT_COMMAND, 0, 0, NULL,
"External command to run when new mail arrives"
},
#ifdef USE_DEVEL_NEW_MAIL
{ "devel_new_mail_command", DT_STRING|DT_COMMAND, 0, 0, NULL,
"External command to run when new mail arrives (in development, clashes with new_mail_command)"
},
#endif
{ "pager", DT_STRING|DT_COMMAND, IP "builtin", 0, NULL,
"External command for viewing messages, or 'builtin' to use NeoMutt's"
},
Expand Down
32 changes: 27 additions & 5 deletions mx.c
Expand Up @@ -85,6 +85,10 @@
#include <xlocale.h>
#endif

#ifdef USE_DEVEL_NEW_MAIL
static time_t last_notified = 0; ///< Time of last new mail notification.
#endif

static const struct Mapping MboxTypeMap[] = {
// clang-format off
{ "mbox", MUTT_MBOX, },
Expand Down Expand Up @@ -1792,10 +1796,21 @@ int mx_ac_remove(struct Mailbox *m, bool keep_account)
return 0;
}

void find_new_emails(const struct Mailbox *mailbox, time_t last_notified,
struct EmailArray *emails)
{
int i = 0;
for (; i < mailbox->msg_count; i++)
{
if (last_notified < mailbox->emails[i]->received)
ARRAY_ADD(emails, mailbox->emails[i]);
}
}

/**
* mx_mbox_check_stats - Check the statistics for a mailbox - Wrapper for MxOps::mbox_check_stats()
*
* @note Emits: #NT_MAILBOX_CHANGE
* @note Emits: #NT_MAILBOX_CHANGE and #NT_MAILBOX_NEW_MAIL
*/
enum MxStatus mx_mbox_check_stats(struct Mailbox *m, uint8_t flags)
{
Expand All @@ -1808,12 +1823,19 @@ enum MxStatus mx_mbox_check_stats(struct Mailbox *m, uint8_t flags)
struct EventMailbox ev_m = { m };
notify_send(m->notify, NT_MAILBOX, NT_MAILBOX_CHANGE, &ev_m);
}
if (rc == MX_STATUS_NEW_MAIL && !m->notified)
#ifdef USE_DEVEL_NEW_MAIL
if (rc == MX_STATUS_NEW_MAIL)
{
struct EventMailbox ev_m = { m };
notify_send(m->notify, NT_MAILBOX, NT_MAILBOX_NEW_MAIL, &ev_m);
m->notified = true;
if (last_notified > 0)
{
struct EventMailbox ev_m = { m, ARRAY_HEAD_INITIALIZER };
find_new_emails(m, last_notified, &ev_m.emails);
if (!ARRAY_EMPTY(&ev_m.emails))
notify_send(m->notify, NT_MAILBOX, NT_MAILBOX_NEW_MAIL, &ev_m);
}
last_notified = mutt_date_epoch();
}
#endif

return rc;
}
Expand Down
3 changes: 2 additions & 1 deletion newmail/lib.h
Expand Up @@ -25,9 +25,10 @@

#include <stdint.h>
#include <stdio.h>
#include "mutt/notify.h"
#include "format_flags.h"

struct NotifyCallback;

typedef int(Execute)(const char *cmd);

const char *new_mail_format_str(char *buf, size_t buflen, size_t col, int cols,
Expand Down
31 changes: 24 additions & 7 deletions newmail/new_mail.c
Expand Up @@ -26,7 +26,9 @@
* Use an external command to send a system notification when new mail arrives.
*/

#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "newmail/lib.h"
#include "mutt_mailbox.h"
#include "muttlib.h"
Expand All @@ -38,30 +40,45 @@
* @param[in] buflen Buffer length
* @param[in] col Starting column
* @param[in] cols Number of screen columns
* @param[in] src Printf-like format string
* @param[in] op printf-like operator, e.g. 't'
* @param[in] src printf-like format string
* @param[in] prec Field precision, e.g. "-3.4"
* ############# TODO #############
* @param[in] if_str If condition is met, display this string
* @param[in] else_str Otherwise, display this string
* @param[in] data Private data
* @param[in] flags Flags, see #MuttFormatFlags
* @retval ptr src (unchanged)
*
* | Expando | Description
* | :------ | :-------------------------------------------------------
* | \%c | New messages
* | \%n | Folder name
* | \%f | Folder path
* | \%u | Unread messages
*/
const char *new_mail_format_str(char *buf, size_t buflen, size_t col, int cols,
char op, const char *src, const char *prec,
const char *if_str, const char *else_str,
intptr_t data, MuttFormatFlags flags)
{
struct Mailbox *mailbox = (struct Mailbox *) data;
struct EventMailbox *ev_m = (struct EventMailbox *) data;
struct Mailbox *mailbox = ev_m->mailbox;
struct EmailArray *emails = &ev_m->emails;

switch (op)
{
case 'n':
snprintf(buf, buflen, "%s", NONULL(mailbox->name));
case 'c':
snprintf(buf, buflen, "%ld", ARRAY_SIZE(emails));
break;
case 'f':
snprintf(buf, buflen, "%s", NONULL(mailbox_path(mailbox)));
break;
case 'n':
snprintf(buf, buflen, "%s", NONULL(mailbox->name));
break;
case 'u':
snprintf(buf, buflen, "%d", mailbox->msg_unread);
break;
}
return src;
}
Expand All @@ -75,11 +92,11 @@ int handle_new_mail_event(const char *cmd, struct NotifyCallback *nc, Execute *e
if (!ev_m || !ev_m->mailbox)
return 0;

struct Mailbox *mailbox = ev_m->mailbox;
char expanded_cmd[1024];
mutt_expando_format(expanded_cmd, 1024, 0, 1024, cmd, new_mail_format_str,
(intptr_t) mailbox, MUTT_FORMAT_NO_FLAGS);
(intptr_t) ev_m, MUTT_FORMAT_NO_FLAGS);
execute(expanded_cmd);
ARRAY_FREE(&ev_m->emails);
return 0;
}

Expand Down
25 changes: 23 additions & 2 deletions test/newmail/new_mail_format_str.c
Expand Up @@ -24,8 +24,9 @@
#define TEST_NO_MAIN
#include "config.h"
#include "acutest.h"
#include "newmail/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "newmail/lib.h"

void test_new_mail_format_str(void)
{
Expand All @@ -40,8 +41,14 @@ void test_new_mail_format_str(void)
struct Mailbox *mailbox = mailbox_new();
mailbox->name = mutt_str_dup("MailBox");
mailbox->pathbuf = mutt_buffer_make(16);
mailbox->msg_unread = 7;
mutt_buffer_strcpy(&mailbox->pathbuf, "/path");
intptr_t data = (intptr_t) mailbox;

struct EventMailbox ev_m = { mailbox, ARRAY_HEAD_INITIALIZER };
ARRAY_ADD(&ev_m.emails, email_new());
ARRAY_ADD(&ev_m.emails, email_new());

intptr_t data = (intptr_t) &ev_m;

new_mail_format_str((char *) buf, 64, col, cols, 'n', NULL, NULL, NULL, NULL, data, 0);
TEST_CHECK(mutt_str_equal(buf, "MailBox"));
Expand All @@ -51,5 +58,19 @@ void test_new_mail_format_str(void)
TEST_CHECK(mutt_str_equal(buf, "/path"));
TEST_MSG("Check failed: %s != /path", buf);

new_mail_format_str((char *) buf, 64, col, cols, 'u', NULL, NULL, NULL, NULL, data, 0);
TEST_CHECK(mutt_str_equal(buf, "7"));
TEST_MSG("Check failed: %s != 7", buf);

new_mail_format_str((char *) buf, 64, col, cols, 'c', NULL, NULL, NULL, NULL, data, 0);
TEST_CHECK(mutt_str_equal(buf, "2"));
TEST_MSG("Check failed: %s != 2", buf);

struct Email **email;
ARRAY_FOREACH(email, &ev_m.emails)
{
email_free(email);
}
ARRAY_FREE(&ev_m.emails);
mailbox_free(&mailbox);
}
5 changes: 2 additions & 3 deletions test/newmail/new_mail_observer.c
Expand Up @@ -26,8 +26,8 @@
#define TEST_NO_MAIN
#include "config.h"
#include "acutest.h"
#include "newmail/lib.h"
#include "core/lib.h"
#include "newmail/lib.h"

static char *message = NULL;

Expand All @@ -48,8 +48,7 @@ void test_new_mail_observer(void)
notify_observer_add(notify, NT_MAILBOX, dummy_new_mail_observer, NULL);
struct Mailbox *mailbox = mailbox_new();
mailbox->name = mutt_str_dup("Mailbox");
struct EventMailbox event;
event.mailbox = mailbox;
struct EventMailbox event = { mailbox, ARRAY_HEAD_INITIALIZER };

notify_send(notify, NT_MAILBOX, NT_MAILBOX_NEW_MAIL, NULL);
TEST_CHECK(message == NULL);
Expand Down

0 comments on commit a77e3b3

Please sign in to comment.