Distributed Notmuch
Hi guys, It's kind of academic for me right now because I'm mostly just using one computer, but one reason I've hesitated to switch over entirely to notmuch is that it's hard to distribute across many machines. The last time I wrote the list about this, David Bremner pointed me to gitmuch in the notmuch-scripts package, which uses git to synchronize tags. He wrote, "No one claims this is a great solution, but it works now." In brainstorming about the One True Mail Setup, my friend suggested to me that Maildir/IMAP are not really the best choices for mail storage. Among other flaws: to synchronize mail via IMAP you have to check the headers of each message, which means a lot of bandwidth; you can't compress Maildir, meaning lots of wasted space; mechanisms to synchronize arbitrary tags have to be bolted on top. My friend suggested that instead it might be better to dump mail into some kind of database, for example CouchDB, and synchronize it that way. Of course, doing full-text indexing and tagging using an arbitrary DB would be a ton of work, so instead it probably makes the most sense to keep a Xapian instance on each node and feed all the mail to that. Tagging operations still have to be replicated, probably by an oplog that's also kept in Couch, so it's still a lot of work, but keeping things in Couch automatically gets you a lot of the replication mechanisms, offline access, etc., that would have to be bolted on/hacked up using tools like nmbug/gitmuch/rsync. I also see in the wiki that someone proposes to use git as the mail store, presumably for similar reasons. Xapian itself has the idea of master/slave replication but that doesn't really get you full offline access. So my question for the wizards on this list is what their idea of the One True Mail Setup would be in a perfect, or slightly better, world, and what needs to be done to get there. I know some people use one notmuch install that they access remotely. For myself, I'm on a pretty limited Internet connection, so low bandwidth/offline access are big for me, and despite Nicolas Sebrecht and Sebastian Spaeth's heroic work on OfflineIMAP, it still uses a lot of bandwidth to sync. And obviously the whole point of this exercise is tag synchronization.. Ethan ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 1/2] clean up "compare thread ids" python test
On Mon, 2 Jan 2012 14:51:26 +, Patrick Totzke wrote: > This makes the test script open the database in READ_ONLY mode > and use the libraries own sorting methods instead of "sort". +1 I don't want to fudge the tests (I don't know a thing about them), so I can't judge the test outcome, but it is certainly good from the python side of things. So I'll push this one. pgp8sAgAYxj7U.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 1/4] Add the option "--reply-to" to notmuch reply.
On Fri, 6 Jan 2012 13:34:14 +, Mark Walters wrote: > Possible values for this option are "sender" which replies just to > sender and "all" (the default). > > More precisely reply to sender follows these rules: > reply only to sender unless it was the user > reply only to all people on the "to" line unless they were all the user > reply to all people on the "cc" line > > Implementation details > > We continue parsing addresses beyond the ones we reply to because > we want to make sure the from address is correct. (At the very least it > is the same as it would be if we replied to all.) > > We overload the message variable in add_recipients_for_address_list so > if it is NULL we parse the address (looking for the users address) > but do not add to the message recipients list > > We add the variable reply_to_all to the function chain to keep track > of whether we should reply to everyone. > --- > notmuch-reply.c | 48 +--- > 1 files changed, 37 insertions(+), 11 deletions(-) > > diff --git a/notmuch-reply.c b/notmuch-reply.c > index f8d5f64..9a77fe6 100644 > --- a/notmuch-reply.c > +++ b/notmuch-reply.c > @@ -212,7 +212,8 @@ add_recipients_for_address_list (GMimeMessage *message, > if (ret == NULL) > ret = addr; > } else { > - g_mime_message_add_recipient (message, type, name, addr); > + if (message) > + g_mime_message_add_recipient (message, type, name, addr); > } > } > } > @@ -292,7 +293,8 @@ reply_to_header_is_redundant (notmuch_message_t *message) > static const char * > add_recipients_from_message (GMimeMessage *reply, >notmuch_config_t *config, > - notmuch_message_t *message) > + notmuch_message_t *message, > + int reply_to_all) > { > struct { > const char *header; > @@ -332,9 +334,20 @@ add_recipients_from_message (GMimeMessage *reply, > recipients = notmuch_message_get_header (message, >reply_to_map[i].fallback); > > - addr = add_recipients_for_string (reply, config, > - reply_to_map[i].recipient_type, > - recipients); > + > + /* We add the addresses if we are replying to all or we have not yet > found > + * a non-user address. We have to keep parsing to make sure we do find > the > + * correct from address for the user, but we pass a NULL message > + */ > + if ((reply_to_all) || (g_mime_message_get_all_recipients (reply) == > NULL)) Looking into this, it occurred to me g_mime_message_get_all_recipients() allocates a new InternetAddressList when the return value is non-NULL. Thus this leaks memory. OTOH allocating and deallocating for this purpose seems suboptimal. I'll think this over. BR, Jani. > + addr = add_recipients_for_string (reply, config, > + reply_to_map[i].recipient_type, > + recipients); > + else > + addr = add_recipients_for_string (NULL, config, > +reply_to_map[i].recipient_type, > +recipients); > + > if (from_addr == NULL) > from_addr = addr; > } > @@ -480,7 +493,8 @@ static int > notmuch_reply_format_default(void *ctx, >notmuch_config_t *config, >notmuch_query_t *query, > - notmuch_show_params_t *params) > + notmuch_show_params_t *params, > + int reply_to_all) > { > GMimeMessage *reply; > notmuch_messages_t *messages; > @@ -509,7 +523,7 @@ notmuch_reply_format_default(void *ctx, > g_mime_message_set_subject (reply, subject); > } > > - from_addr = add_recipients_from_message (reply, config, message); > + from_addr = add_recipients_from_message (reply, config, message, > reply_to_all); > > if (from_addr == NULL) > from_addr = guess_from_received_header (config, message); > @@ -558,7 +572,8 @@ static int > notmuch_reply_format_headers_only(void *ctx, > notmuch_config_t *config, > notmuch_query_t *query, > - unused (notmuch_show_params_t *params)) > + unused (notmuch_show_params_t *params), > + int reply_to_all) > { > GMimeMessage *reply; > notmuch_messages_t *messages; > @@ -598,7 +613,7 @@ notmuch_reply_format_headers_only(void *ctx, > g_mime_object_set_header (GMIME_OBJECT (reply), >
Re: [PATCH 2/2] python test "compare message ids"
On Mon, 2 Jan 2012 14:51:27 +, Patrick Totzke wrote: > Introduces a second (trivial) test for the python > bindings that searches for message ids and compares > the output with that of `notmuch search`. Test passes, so it went in. pgpOPxhSYny4e.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
notmuch git's disk is full! ERROR pushing.
Actually trying to push the above 2 patches, I get Writing objects: 100% (8/8), 1.25 KiB, done. Total 8 (delta 5), reused 0 (delta 0) error: unable to create temporary sha1 filename : No space left on device fatal: failed to write object error: unpack failed: unpack-objects abnormal exit To ssh://spa...@notmuchmail.org/git/notmuch ! [remote rejected] master -> master (n/a (unpacker error)) error: failed to push some refs to 'ssh://spa...@notmuchmail.org/git/notmuch' Sebastian pgpqPdR7nAG9s.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: Info about notmuch database
On Thu, 05 Jan 2012 16:04:22 +0100, Thomas Jost wrote: > There's a description of the DB "schema" in lib/database.cc in the > notmuch source code. But you may also consider just using libnotmuch > instead, if that's enough for what you want to do. > > Also: why Xapian? I'm already using something similar I wrote with > Python, storing everything in a dictionary, using Pickle to save that to > disk: 162 lines of code and 45 kb of data are enough to store my > addressbook and have completion in Emacs... Ohh, that sounds nice. Is that public somewhere? Sebastian pgpfzTxwiF37m.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 5/7] py3k: the basestring and unicode types are removed in python 3
Hi Tomi, Hi Sebastian :) Quoting Tomi Ollila (2012-01-04 19:07:11) >On Mon, 02 Jan 2012 16:15:58 +0100, Sebastian Spaeth >wrote: >> Happy new year. Pushed patches 1-4 of this series so far. Looking fine, nice, thanks. >> but ugh, the below seems like a rather ugly hack in a function that is >> probably called quite often. >> >> Isn't there a more pretty variant avoiding these sys.version_info checks >> all over the place? Well, I rebased and updated this patch. There are now two different implementations of _str like there are two Python3StringMixIn classes. I'll send this patch as reply to this message. >Does the Python3StringMixIn stuff in later patches already handle this >patch -- and making this obsolete ? No, that only handles the __str__ and __unicode__ stuff. Cheers, Justus ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] py3k: the basestring and unicode types are removed in python 3
--- bindings/python/notmuch/globals.py | 34 ++ 1 files changed, 22 insertions(+), 12 deletions(-) diff --git a/bindings/python/notmuch/globals.py b/bindings/python/notmuch/globals.py index 32ed9ae..4138460 100644 --- a/bindings/python/notmuch/globals.py +++ b/bindings/python/notmuch/globals.py @@ -31,12 +31,34 @@ if sys.version_info[0] == 2: class Python3StringMixIn(object): def __str__(self): return unicode(self).encode('utf-8') + + +def _str(value): +"""Ensure a nicely utf-8 encoded string to pass to libnotmuch + +C++ code expects strings to be well formatted and +unicode strings to have no null bytes.""" +if not isinstance(value, basestring): +raise TypeError("Expected str or unicode, got %s" % type(value)) +if isinstance(value, unicode): +return value.encode('UTF-8') +return value else: class Python3StringMixIn(object): def __str__(self): return self.__unicode__() +def _str(value): +"""Ensure a nicely utf-8 encoded string to pass to libnotmuch + +C++ code expects strings to be well formatted and +unicode strings to have no null bytes.""" +if not isinstance(value, str): +raise TypeError("Expected str, got %s" % type(value)) +return value.encode('UTF-8') + + class Enum(object): """Provides ENUMS as "code=Enum(['a','b','c'])" where code.a=0 etc...""" def __init__(self, names): @@ -202,18 +224,6 @@ class NotInitializedError(NotmuchError): status = STATUS.NOT_INITIALIZED -def _str(value): -"""Ensure a nicely utf-8 encoded string to pass to libnotmuch - -C++ code expects strings to be well formatted and -unicode strings to have no null bytes.""" -if not isinstance(value, basestring): -raise TypeError("Expected str or unicode, got %s" % str(type(value))) -if isinstance(value, unicode): -return value.encode('UTF-8') -return value - - class NotmuchDatabaseS(Structure): pass NotmuchDatabaseP = POINTER(NotmuchDatabaseS) -- 1.7.7.3 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: Info about notmuch database
On Sun, 08 Jan 2012 13:59:30 +0100, Sebastian Spaeth wrote: > On Thu, 05 Jan 2012 16:04:22 +0100, Thomas Jost wrote: > > There's a description of the DB "schema" in lib/database.cc in the > > notmuch source code. But you may also consider just using libnotmuch > > instead, if that's enough for what you want to do. > > > > Also: why Xapian? I'm already using something similar I wrote with > > Python, storing everything in a dictionary, using Pickle to save that to > > disk: 162 lines of code and 45 kb of data are enough to store my > > addressbook and have completion in Emacs... > > Ohh, that sounds nice. Is that public somewhere? > > Sebastian https://github.com/Schnouki/dotfiles/blob/master/notmuch/addrbook.py Maybe I should add more comments in it :) Regards, -- Thomas/Schnouki pgpjufUuWWH1R.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 1/4] Add the option "--reply-to" to notmuch reply.
On Sun, 08 Jan 2012 14:47:33 +0200, Jani Nikula wrote: > > + /* We add the addresses if we are replying to all or we have not yet > > found > > +* a non-user address. We have to keep parsing to make sure we do find > > the > > +* correct from address for the user, but we pass a NULL message > > +*/ > > + if ((reply_to_all) || (g_mime_message_get_all_recipients (reply) == > > NULL)) > > Looking into this, it occurred to me g_mime_message_get_all_recipients() > allocates a new InternetAddressList when the return value is > non-NULL. Thus this leaks memory. OTOH allocating and deallocating for > this purpose seems suboptimal. I'll think this over. If we are happy with reply-to-sender stopping at the to: line (so if you reply-to-sender to an email which you sent and has no-one (apart from possibly you) on the to: line it would not give any recipients) then we only have two cases and we could do something like add_recipients_for_string for reply-to:/from: if return value is non-null then we were the sender so then add_recipients_for_string for to: and then stop regardless (well we want to carry on parsing headers to find the correct from: address to use but not adding any more recipients). It feels a bit hackish (it relies on the fact that if we found our address in the Reply-to:/From: line we didn't find anyone else's address). I think replying to an email which we sent and which does not have any other person on the to: line is sufficiently rare that it doesn't really matter what we do in this case. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 1/4] Add the option "--reply-to" to notmuch reply.
On Sun, 08 Jan 2012 15:08:20 +, Mark Walters wrote: > I think replying to an email which we sent and which does not have any > other person on the to: line is sufficiently rare that it doesn't really > matter what we do in this case. I ended up fixing all of this properly. I'm hoping to send the patches later today so you can have a look - the code will do a better job of explaining itself than I'd do now. :) BR, Jani. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: Python bindings for adoption
Hi Sebastian, hi everyone :) Quoting Sebastian Spaeth (2012-01-02 17:14:58) >Hi all, a happy new year! > >After a few weeks of notmuch abstinence I am being overwhelmed with 750 >new notmuch mails, and I really don't have the time or will (nor does my >family approve) to spend enormous amounts of time on notmuch. I am >already neglecting offlineimap, which also needs some attention. > >As I have repeatedly stated that I want to hand over the maintainership >of the notmuch python bindings, and I would like to do it asap. I feel >that people like Patrick Totzke, or Justus Winter who generally have >been working on this far more intensely than I recently did are both >very well positioned to take on that role :-). Most importantly, they >actually work with the bindings while I don't use them myself anymore. > >I will only merge bug fixes as of now, and not invest time to refactor >the code or add lots of bells and whistles. Let me know if anyone would >volunteer to take them on. I've decided to step up as a new maintainer for the libnotmuch python bindings. I assume that I'll have to mail an ssh public key to someone for repository access, right? Cheers, Justus ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: nmbug changes
Hey David, Quoting David Bremner (2011-12-23 22:56:31) >For those of you following/using the nmbug experiment, I made some >slightly disruptive changes, in order to support auto-updating the web >view on push. I'm having trouble with nmbug, I did follow the instructions in this mail and in the wiki, but nmbug never adds tags to my notmuch database (it is supposed to do that, right?). Consequently, nmbug status displays a long list of tags that aren't in my notmuch database. Executing nmbug merge does not help, and stracing nmbug revealed that it does only invoke notmuch with the search and dump actions. Any pointers? Thanks, Justus ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 4/4 v2] emacs: use pop-at-end functionality in archive/delete-message functions
This provides a smoother message processing flow by reducing the number of key presses needed for these common operations. --- Sorry, there were some errant extra parens at the end of these function definitions. emacs/notmuch-show.el |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 4c2b507..a706637 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -1454,7 +1454,7 @@ thread. " (interactive) (notmuch-show-remove-tag "inbox") -(notmuch-show-next-open-message))) +(notmuch-show-next-open-message t)) (defun notmuch-show-archive-thread () "Archive each message in thread, then show next thread from search. @@ -1485,7 +1485,7 @@ thread. " (interactive) (notmuch-show-add-tag "deleted") -(notmuch-show-next-open-message))) +(notmuch-show-next-open-message t)) (defun notmuch-show-delete-thread () "Delete each message in thread, then show next thread from search. -- 1.7.7.3 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 1/4 v2] emacs: add show-mode functions to archive/delete only current message
This adds two new function, notmuch-show-{archive,delete}-message, that archive/delete the current message, and then move to the next open one. --- Sorry, there were some errant extra parens at the end of these function definitions. emacs/notmuch-show.el | 24 1 files changed, 24 insertions(+), 0 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index e1d15f4..b2e7829 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -1436,6 +1436,18 @@ argument, hide all of the messages." (if show-next (notmuch-search-show-thread))) +(defun notmuch-show-archive-message () + "Archive the current message and advance. + +After the last message is reached, either the buffer will be +closed and the cursor will move to the search result if +available, or the cursor will move to the end of the current +thread. +" +(interactive) +(notmuch-show-remove-tag "inbox") +(notmuch-show-next-open-message)) + (defun notmuch-show-archive-thread () "Archive each message in thread, then show next thread from search. @@ -1455,6 +1467,18 @@ buffer." (interactive) (notmuch-show-tag-thread-internal "-" "inbox" nil)) +(defun notmuch-show-delete-message () + "Delete the current message and advance. + +After the last message is reached, either the buffer will be +closed and the cursor will move to the search result if +available, or the cursor will move to the end of the current +thread. +" +(interactive) +(notmuch-show-add-tag "deleted") +(notmuch-show-next-open-message)) + (defun notmuch-show-delete-thread () "Delete each message in thread, then show next thread from search. -- 1.7.7.3 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 4/4 v3] emacs: use pop-at-end functionality in archive/delete-message functions
This provides a smoother message processing flow by reducing the number of key presses needed for these common operations. --- Sorry sorry. I originally missed the problem in patch 1/4, so I had to modify this patch again to apply against the new version of the previous. So sorry for the noise, and thanks to amdragon for pointing all of this out. emacs/notmuch-show.el |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index b9ec584..a706637 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -1454,7 +1454,7 @@ thread. " (interactive) (notmuch-show-remove-tag "inbox") -(notmuch-show-next-open-message)) +(notmuch-show-next-open-message t)) (defun notmuch-show-archive-thread () "Archive each message in thread, then show next thread from search. @@ -1485,7 +1485,7 @@ thread. " (interactive) (notmuch-show-add-tag "deleted") -(notmuch-show-next-open-message)) +(notmuch-show-next-open-message t)) (defun notmuch-show-delete-thread () "Delete each message in thread, then show next thread from search. -- 1.7.7.3 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] man: add missing SEE ALSO header to notmuch reply man page
Signed-off-by: Jani Nikula --- man/man1/notmuch-reply.1 |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/man/man1/notmuch-reply.1 b/man/man1/notmuch-reply.1 index 099d808..db464d8 100644 --- a/man/man1/notmuch-reply.1 +++ b/man/man1/notmuch-reply.1 @@ -58,6 +58,9 @@ thread, replying to the entire thread allows for the reply to comment on issue found in multiple patches. .RE .RE + +.SH SEE ALSO + \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1), \fBnotmuch-dump\fR(5), \fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1), \fBnotmuch-part\fR(1), \fBnotmuch-restore\fR(1), -- 1.7.5.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 0/6] reply to sender
Hi all, here's v2 of the reply-to-sender series. Patches 1 & 2 are exactly the same as before. Changes since first version: - Patch 3: Settle on --reply-to=(all|sender) option for "notmuch reply". This was originally Carl Worth's suggestion, predates this patch set, and, as you'd expect, is in line with the rest of the CLI. Acked by David on IRC. - Patch 3: Handle replying to user's own messages gracefully. Credits to Mark Walters for his earlier work on this. - Patch 3: Update man page. - Patch 4: Change emacs implementation to keep old function names for old reply-to-all functionality, and add new reply-to-sender versions for new functionality, instead of vice versa. Suggested by Mark Walters. - Add patch 5 to change emacs keybindings, 'r' for reply-to-sender, 'R' for reply-to-all. I think everyone was in favour of this. - Add patch 6, written by Mark Winters, to test the cli. Comments are, as always, welcome. BR, Jani. Jani Nikula (5): cli: fix use of uninitialized variable in "notmuch reply" cli: convert "notmuch reply" to use the new argument parser cli: add support for replying just to the sender in "notmuch reply" emacs: add support for replying just to the sender emacs: bind 'r' to reply-to-sender and 'R' to reply-to-all Mark Walters (1): test: add tests for "notmuch reply" --reply-to=sender emacs/notmuch-mua.el |9 ++- emacs/notmuch-show.el| 12 ++- emacs/notmuch.el | 11 ++- man/man1/notmuch-reply.1 | 28 +- notmuch-reply.c | 155 ++ test/notmuch-test|1 + test/reply-to-sender | 209 ++ 7 files changed, 356 insertions(+), 69 deletions(-) create mode 100755 test/reply-to-sender -- 1.7.5.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 1/6] cli: fix use of uninitialized variable in "notmuch reply"
notmuch_show_params_t params is only initialized partially in notmuch_reply_command(). The only field that is used uninitialized is params.decrypt. It is usually non-zero, making "notmuch reply" on encrypted messages work by coincidence. Initialize params properly, and set params.decrypt as needed. Signed-off-by: Jani Nikula --- notmuch-reply.c | 10 +- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/notmuch-reply.c b/notmuch-reply.c index f8d5f64..1f33a86 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -621,11 +621,9 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) char *opt, *query_string; int i, ret = 0; int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params); -notmuch_show_params_t params; +notmuch_show_params_t params = { .part = -1 }; reply_format_func = notmuch_reply_format_default; -params.part = -1; -params.cryptoctx = NULL; argc--; argv++; /* skip subcommand argument */ @@ -647,10 +645,12 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) } else if ((STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) { if (params.cryptoctx == NULL) { GMimeSession* session = g_object_new(g_mime_session_get_type(), NULL); - if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg"))) + if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg"))) { fprintf (stderr, "Failed to construct gpg context.\n"); - else + } else { + params.decrypt = TRUE; g_mime_gpg_context_set_always_trust((GMimeGpgContext*)params.cryptoctx, FALSE); + } g_object_unref (session); session = NULL; } -- 1.7.5.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 2/6] cli: convert "notmuch reply" to use the new argument parser
Use the new notmuch argument parser to handle arguments in "notmuch reply". There should be no functional changes. Signed-off-by: Jani Nikula --- notmuch-reply.c | 75 +++ 1 files changed, 37 insertions(+), 38 deletions(-) diff --git a/notmuch-reply.c b/notmuch-reply.c index 1f33a86..000f6da 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -612,62 +612,61 @@ notmuch_reply_format_headers_only(void *ctx, return 0; } +enum { +FORMAT_DEFAULT, +FORMAT_HEADERS_ONLY, +}; + int notmuch_reply_command (void *ctx, int argc, char *argv[]) { notmuch_config_t *config; notmuch_database_t *notmuch; notmuch_query_t *query; -char *opt, *query_string; -int i, ret = 0; +char *query_string; +int opt_index, ret = 0; int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params); notmuch_show_params_t params = { .part = -1 }; +int format = FORMAT_DEFAULT; +notmuch_bool_t decrypt = FALSE; + +notmuch_opt_desc_t options[] = { + { NOTMUCH_OPT_KEYWORD, &format, "format", 'f', + (notmuch_keyword_t []){ { "default", FORMAT_DEFAULT }, + { "headers-only", FORMAT_HEADERS_ONLY }, + { 0, 0 } } }, + { NOTMUCH_OPT_BOOLEAN, &decrypt, "decrypt", 'd', 0 }, + { 0, 0, 0, 0, 0 } +}; -reply_format_func = notmuch_reply_format_default; - -argc--; argv++; /* skip subcommand argument */ +opt_index = parse_arguments (argc, argv, options, 1); +if (opt_index < 0) { + /* diagnostics already printed */ + return 1; +} -for (i = 0; i < argc && argv[i][0] == '-'; i++) { - if (strcmp (argv[i], "--") == 0) { - i++; - break; - } -if (STRNCMP_LITERAL (argv[i], "--format=") == 0) { - opt = argv[i] + sizeof ("--format=") - 1; - if (strcmp (opt, "default") == 0) { - reply_format_func = notmuch_reply_format_default; - } else if (strcmp (opt, "headers-only") == 0) { - reply_format_func = notmuch_reply_format_headers_only; - } else { - fprintf (stderr, "Invalid value for --format: %s\n", opt); - return 1; - } - } else if ((STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) { - if (params.cryptoctx == NULL) { - GMimeSession* session = g_object_new(g_mime_session_get_type(), NULL); - if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg"))) { - fprintf (stderr, "Failed to construct gpg context.\n"); - } else { - params.decrypt = TRUE; - g_mime_gpg_context_set_always_trust((GMimeGpgContext*)params.cryptoctx, FALSE); - } - g_object_unref (session); - session = NULL; - } +if (format == FORMAT_HEADERS_ONLY) + reply_format_func = notmuch_reply_format_headers_only; +else + reply_format_func = notmuch_reply_format_default; + +if (decrypt) { + GMimeSession* session = g_object_new (g_mime_session_get_type(), NULL); + params.cryptoctx = g_mime_gpg_context_new (session, "gpg"); + if (params.cryptoctx) { + g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) params.cryptoctx, FALSE); + params.decrypt = TRUE; } else { - fprintf (stderr, "Unrecognized option: %s\n", argv[i]); - return 1; + fprintf (stderr, "Failed to construct gpg context.\n"); } + g_object_unref (session); } -argc -= i; -argv += i; - config = notmuch_config_open (ctx, NULL, NULL); if (config == NULL) return 1; -query_string = query_string_from_args (ctx, argc, argv); +query_string = query_string_from_args (ctx, argc-opt_index, argv+opt_index); if (query_string == NULL) { fprintf (stderr, "Out of memory\n"); return 1; -- 1.7.5.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 3/6] cli: add support for replying just to the sender in "notmuch reply"
Add new option --reply-to=(all|sender) to "notmuch reply" to select whether to reply to all (sender and all recipients), or just sender. Reply to all remains the default. Credits to Mark Walters for his similar earlier work where I picked up the basic idea of handling reply-to-sender in add_recipients_from_message(). All bugs are mine, though. Signed-off-by: Jani Nikula --- Settled on --reply-to=(all|sender) per Carl's earlier suggestion (id:87pqn5cg4g@yoom.home.cworth.org) and David's approval on IRC. --- man/man1/notmuch-reply.1 | 28 +--- notmuch-reply.c | 78 -- 2 files changed, 84 insertions(+), 22 deletions(-) diff --git a/man/man1/notmuch-reply.1 b/man/man1/notmuch-reply.1 index 099d808..21afa35 100644 --- a/man/man1/notmuch-reply.1 +++ b/man/man1/notmuch-reply.1 @@ -14,11 +14,13 @@ Constructs a reply template for a set of messages. To make replying to email easier, .B notmuch reply takes an existing set of messages and constructs a suitable mail -template. The Reply-to header (if any, otherwise From:) is used for -the To: address. Vales from the To: and Cc: headers are copied, but -not including any of the current user's email addresses (as configured -in primary_mail or other_email in the .notmuch\-config file) in the -recipient list +template. The Reply-to: header (if any, otherwise From:) is used for +the To: address. Unless +.BR \-\-reply-to=sender +is specified, values from the To: and Cc: headers are copied, but not +including any of the current user's email addresses (as configured in +primary_mail or other_email in the .notmuch\-config file) in the +recipient list. It also builds a suitable new subject, including Re: at the front (if not already present), and adding the message IDs of the messages being @@ -45,6 +47,22 @@ Includes subject and quoted message body. Only produces In\-Reply\-To, References, To, Cc, and Bcc headers. .RE .RE +.RS +.TP 4 +.BR \-\-reply\-to= ( all | sender ) +.RS +.TP 4 +.BR all " (default)" +Replies to all addresses. +.TP 4 +.BR sender +Replies only to the sender. If Reply-to: header (if any, otherwise +From:) is any of the current user's configured email addresses +(replying to user's own message), try To:, Cc:, and Bcc: headers in +this order, and use the addresses in the first that contains something +other than only the user's addresses for the To: address. +.RE +.RE See \fBnotmuch-search-terms\fR(7) for details of the supported syntax for . diff --git a/notmuch-reply.c b/notmuch-reply.c index 000f6da..71946b3 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -170,7 +170,7 @@ address_is_users (const char *address, notmuch_config_t *config) /* For each address in 'list' that is not configured as one of the * user's addresses in 'config', add that address to 'message' as an - * address of 'type'. + * address of 'type', if 'add' is true. * * The first address encountered that *is* the user's address will be * returned, (otherwise NULL is returned). @@ -179,7 +179,8 @@ static const char * add_recipients_for_address_list (GMimeMessage *message, notmuch_config_t *config, GMimeRecipientType type, -InternetAddressList *list) +InternetAddressList *list, +notmuch_bool_t add) { InternetAddress *address; int i; @@ -197,7 +198,7 @@ add_recipients_for_address_list (GMimeMessage *message, continue; add_recipients_for_address_list (message, config, -type, group_list); +type, group_list, add); } else { InternetAddressMailbox *mailbox; const char *name; @@ -211,7 +212,7 @@ add_recipients_for_address_list (GMimeMessage *message, if (address_is_users (addr, config)) { if (ret == NULL) ret = addr; - } else { + } else if (add) { g_mime_message_add_recipient (message, type, name, addr); } } @@ -222,7 +223,7 @@ add_recipients_for_address_list (GMimeMessage *message, /* For each address in 'recipients' that is not configured as one of * the user's addresses in 'config', add that address to 'message' as - * an address of 'type'. + * an address of 'type', if 'add' is true. * * The first address encountered that *is* the user's address will be * returned, (otherwise NULL is returned). @@ -231,7 +232,8 @@ static const char * add_recipients_for_string (GMimeMessage *message, notmuch_config_t *config, GMimeRecipientType type, - const char *recipients) + const char *recipients, + notmuch_bool_t add) { InternetAddressLi
[PATCH v2 4/6] emacs: add support for replying just to the sender
Provide reply to sender counterparts to the search and show reply functions. Add key binding 'R' to reply to sender, while keeping 'r' as reply to all, both in search and show views. Signed-off-by: Jani Nikula --- emacs/notmuch-mua.el |9 ++--- emacs/notmuch-show.el | 10 -- emacs/notmuch.el |9 - 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index 7114e48..5b15255 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -71,12 +71,15 @@ list." (push header message-hidden-headers))) notmuch-mua-hidden-headers)) -(defun notmuch-mua-reply (query-string &optional sender) +(defun notmuch-mua-reply (query-string &optional sender reply-all) (let (headers body (args '("reply"))) (if notmuch-show-process-crypto (setq args (append args '("--decrypt" +(if reply-all + (setq args (append args '("--reply-to=all"))) + (setq args (append args '("--reply-to=sender" (setq args (append args (list query-string))) ;; This make assumptions about the output of `notmuch reply', but ;; really only that the headers come first followed by a blank @@ -217,13 +220,13 @@ the From: address first." (notmuch-mua-forward-message)) (notmuch-mua-forward-message))) -(defun notmuch-mua-new-reply (query-string &optional prompt-for-sender) +(defun notmuch-mua-new-reply (query-string &optional prompt-for-sender reply-all) "Invoke the notmuch reply window." (interactive "P") (let ((sender (when prompt-for-sender (notmuch-mua-prompt-for-sender -(notmuch-mua-reply query-string sender))) +(notmuch-mua-reply query-string sender reply-all))) (defun notmuch-mua-send-and-exit (&optional arg) (interactive "P") diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 5502efd..96eea19 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -933,6 +933,7 @@ thread id. If a prefix is given, crypto processing is toggled." (define-key map "m" 'notmuch-mua-new-mail) (define-key map "f" 'notmuch-show-forward-message) (define-key map "r" 'notmuch-show-reply) + (define-key map "R" 'notmuch-show-reply-sender) (define-key map "|" 'notmuch-show-pipe-message) (define-key map "w" 'notmuch-show-save-attachments) (define-key map "V" 'notmuch-show-view-raw-message) @@ -1237,9 +1238,14 @@ any effects from previous calls to (notmuch-show-previous-message) (defun notmuch-show-reply (&optional prompt-for-sender) - "Reply to the current message." + "Reply to the sender and all recipients of the current message." (interactive "P") - (notmuch-mua-new-reply (notmuch-show-get-message-id) prompt-for-sender)) + (notmuch-mua-new-reply (notmuch-show-get-message-id) prompt-for-sender t)) + +(defun notmuch-show-reply-sender (&optional prompt-for-sender) + "Reply to the sender of the current message." + (interactive "P") + (notmuch-mua-new-reply (notmuch-show-get-message-id) prompt-for-sender nil)) (defun notmuch-show-forward-message (&optional prompt-for-sender) "Forward the current message." diff --git a/emacs/notmuch.el b/emacs/notmuch.el index fde2377..5974d6b 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -207,6 +207,7 @@ For a mouse binding, return nil." (define-key map "p" 'notmuch-search-previous-thread) (define-key map "n" 'notmuch-search-next-thread) (define-key map "r" 'notmuch-search-reply-to-thread) +(define-key map "R" 'notmuch-search-reply-to-thread-sender) (define-key map "m" 'notmuch-mua-new-mail) (define-key map "s" 'notmuch-search) (define-key map "o" 'notmuch-search-toggle-order) @@ -441,10 +442,16 @@ Complete list of currently available key bindings: (error "End of search results" (defun notmuch-search-reply-to-thread (&optional prompt-for-sender) + "Begin composing a reply-all to the entire current thread in a new buffer." + (interactive "P") + (let ((message-id (notmuch-search-find-thread-id))) +(notmuch-mua-new-reply message-id prompt-for-sender t))) + +(defun notmuch-search-reply-to-thread-sender (&optional prompt-for-sender) "Begin composing a reply to the entire current thread in a new buffer." (interactive "P") (let ((message-id (notmuch-search-find-thread-id))) -(notmuch-mua-new-reply message-id prompt-for-sender))) +(notmuch-mua-new-reply message-id prompt-for-sender nil))) (defun notmuch-call-notmuch-process (&rest args) "Synchronously invoke \"notmuch\" with the given list of arguments. -- 1.7.5.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 5/6] emacs: bind 'r' to reply-to-sender and 'R' to reply-to-all
Change the default reply key bindings, making 'r' reply-to-sender and 'R' reply-to-all. Signed-off-by: Jani Nikula --- It seemed to me that most people wanted this, and nobody spoke for keeping the old binding now that we have reply-to-sender. This as a separate patch so it's easy to drop if needed. --- emacs/notmuch-show.el |4 ++-- emacs/notmuch.el |4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 96eea19..8f8ea93 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -932,8 +932,8 @@ thread id. If a prefix is given, crypto processing is toggled." (define-key map "s" 'notmuch-search) (define-key map "m" 'notmuch-mua-new-mail) (define-key map "f" 'notmuch-show-forward-message) - (define-key map "r" 'notmuch-show-reply) - (define-key map "R" 'notmuch-show-reply-sender) + (define-key map "r" 'notmuch-show-reply-sender) + (define-key map "R" 'notmuch-show-reply) (define-key map "|" 'notmuch-show-pipe-message) (define-key map "w" 'notmuch-show-save-attachments) (define-key map "V" 'notmuch-show-view-raw-message) diff --git a/emacs/notmuch.el b/emacs/notmuch.el index 5974d6b..e158138 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -206,8 +206,8 @@ For a mouse binding, return nil." (define-key map ">" 'notmuch-search-last-thread) (define-key map "p" 'notmuch-search-previous-thread) (define-key map "n" 'notmuch-search-next-thread) -(define-key map "r" 'notmuch-search-reply-to-thread) -(define-key map "R" 'notmuch-search-reply-to-thread-sender) +(define-key map "r" 'notmuch-search-reply-to-thread-sender) +(define-key map "R" 'notmuch-search-reply-to-thread) (define-key map "m" 'notmuch-mua-new-mail) (define-key map "s" 'notmuch-search) (define-key map "o" 'notmuch-search-toggle-order) -- 1.7.5.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 6/6] test: add tests for "notmuch reply" --reply-to=sender
From: Mark Walters --- This is Mark's work; just a one line change by Jani to take into account a minor change in replying to one's own message. --- test/notmuch-test|1 + test/reply-to-sender | 209 ++ 2 files changed, 210 insertions(+), 0 deletions(-) create mode 100755 test/reply-to-sender diff --git a/test/notmuch-test b/test/notmuch-test index e40ef86..6a99ae3 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -33,6 +33,7 @@ TESTS=" thread-naming raw reply + reply-to-sender dump-restore uuencode thread-order diff --git a/test/reply-to-sender b/test/reply-to-sender new file mode 100755 index 000..caceeb2 --- /dev/null +++ b/test/reply-to-sender @@ -0,0 +1,209 @@ +#!/usr/bin/env bash +test_description="\"notmuch reply --reply-to=sender\" in several variations" +. ./test-lib.sh + +test_begin_subtest "Basic reply-to-sender" +add_message '[from]="Sender "' \ + [to]=test_su...@notmuchmail.org \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="basic reply-to-sender test"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -, Sender wrote: +> basic reply-to-sender test" + +test_begin_subtest "From Us, Basic reply to message" +add_message '[from]="Notmuch Test Suite "' \ +'[to]="Recipient "' \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="basic reply-to-from-us test"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Recipient +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -, Notmuch Test Suite wrote: +> basic reply-to-from-us test" + +test_begin_subtest "Multiple recipients" +add_message '[from]="Sender "' \ +'[to]="test_su...@notmuchmail.org, Someone Else "' \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="Multiple recipients"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -, Sender wrote: +> Multiple recipients" + +test_begin_subtest "From Us, Multiple TO recipients" +add_message '[from]="Notmuch Test Suite "' \ +'[to]="Recipient , Someone Else "' \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="From Us, Multiple TO recipients"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Recipient , Someone Else +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -, Notmuch Test Suite wrote: +> From Us, Multiple TO recipients" + +test_begin_subtest "Reply with CC" +add_message '[from]="Sender "' \ + [to]=test_su...@notmuchmail.org \ +'[cc]="Other Parties "' \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="reply with CC"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -, Sender wrote: +> reply with CC" + +test_begin_subtest "From Us, Reply with CC" +add_message '[from]="Notmuch Test Suite "' \ +'[to]="Recipient "' \ +'[cc]="Other Parties "' \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="reply with CC"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Recipient +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -, Notmuch Test Suite wrote: +> reply with CC" + +test_begin_subtest "From Us, Reply no TO but with CC" +add_message '[from]="Notmuch Test Suite "' \ +'[cc]="Other Parties "' \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="reply with CC"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-te
Re: [PATCH v2 5/6] emacs: bind 'r' to reply-to-sender and 'R' to reply-to-all
On Sun, Jan 8, 2012 at 14:48, Jani Nikula wrote: > It seemed to me that most people wanted this, and nobody spoke for keeping > the old binding now that we have reply-to-sender. This as a separate patch > so it's easy to drop if needed. FWIW, I generally prefer reply-all as the default. In my experience, when a message is sent to a bunch of people, it's usually treated as a "forum" discussion where everybody wants to be in on everything. Also, once you've started composing, it's much easier to delete people you don't want included than to add people who are no longer referenced in the new buffer at all. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: nmbug changes
On Sun, 08 Jan 2012 16:24:06 -, Justus Winter <4win...@informatik.uni-hamburg.de> wrote: > I'm having trouble with nmbug, I did follow the instructions in this > mail and in the wiki, but nmbug never adds tags to my notmuch database > (it is supposed to do that, right?). In case you just want to load the tags in the git repo into your notmuch database, try running "nmbug checkout". It might be the instructions on "getting started" could be updated here? Perhaps someone who has gotten started more recently can chime in here. David ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: Python bindings for adoption
On Sun, 08 Jan 2012 16:16:06 -, Justus Winter <4win...@informatik.uni-hamburg.de> wrote: > > I've decided to step up as a new maintainer for the libnotmuch python > bindings. I assume that I'll have to mail an ssh public key to someone > for repository access, right? > That's right. Carl (in copy) handles repository access. d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v2 3/6] cli: add support for replying just to the sender in "notmuch reply"
I like this version (of the whole series) but have two queries. (Note I haven't actually tried it out yet: I have just been reading the code.) > + /* Force recipient type in reply-to-sender mode just in case replying to > + * user's own message finds recipients in Cc/Bcc fields only. > + */ > + if (reply_all) > + recipient_type = reply_to_map[i].recipient_type; > + else > + recipient_type = GMIME_RECIPIENT_TYPE_TO; > + > + addr = add_recipients_for_string (reply, config, recipient_type, > + recipients, add_recipients); > + Why force the recipient type? I do not think notmuch should ever move bcc people onto a different header. I think that will bite someone when it leaks information. I would be happy with either empty headers or with the people staying as bcc. In the cc: case I have no preference (as those addresses are already public) but I would suggest being consistent with bcc so either empty headers or keep them in the cc line. > for (messages = notmuch_query_search_messages (query); > notmuch_messages_valid (messages); > notmuch_messages_move_to_next (messages)) > { [...] > (void)add_recipients_from_message (reply, config, message, reply_all); Since the above logic is applied to each email individually I think working out the recipients when replying to multiple emails (e.g., reply-to-sender on a thread) could be very confusing. Some of the people being replied to will have been senders, some recipients (it is very likely that the thread contains messages we sent), some could even be cc, bcc people. Personally, I would have no idea what to expect from reply-to-sender in this case. (My personal choice would be not to allow notmuch-reply-to-sender if multiple messages are specified. But I can obtain that by unbinding "r" in the notmuch-search-mode-map keymap.) Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v2 5/6] emacs: bind 'r' to reply-to-sender and 'R' to reply-to-all
On Sun, 8 Jan 2012 15:01:30 -0700, Jeremy Nickurak wrote: > FWIW, I generally prefer reply-all as the default. In my experience, > when a message is sent to a bunch of people, it's usually treated as a > "forum" discussion where everybody wants to be in on everything. Also, > once you've started composing, it's much easier to delete people you > don't want included than to add people who are no longer referenced in > the new buffer at all. That's a good point. I think that maybe people are wanting to protect against the accidental reply to all when you only mean to reply to the sender. jamie. pgphsy5YZmGB9.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v2 5/6] emacs: bind 'r' to reply-to-sender and 'R' to reply-to-all
On Sun, Jan 8, 2012 at 16:32, Jameson Graef Rollins wrote: > That's a good point. I think that maybe people are wanting to protect > against the accidental reply to all when you only mean to reply to the > sender. Certainly a worthy cause. All I'm saying is I make the mistake in the other direction more frequently ;) ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH] emacs: call "notmuch tag" only once when archiving a thread
On Thu, 05 Jan 2012 22:32:16 +0200, Jani Nikula wrote: [...] > In the show view it only modifies the messages that are currently > visible. This is to make sure you don't accidentally archive things that > have arrived after refreshing the buffer. I think this is safest. Hmm. Perhaps it would make sense to add a check in the search view that the thread being archived[1] has the same number of messages as it did when the buffer was constructed. (The information on how many messages the thread has is in the buffer; we would then compare this to the result of “notmuch count thread:000foo” when the user requests to archive.) If the counts don’t match, the interface should show a message in the echo area and (probably) refuse to do the tagging. We could also optionally use this strategy in the search view too. The error message is simple there: “New messages have arrived; refresh thread view before archiving.” (It doesn’t make as much sense to tell people to refresh a search view – it could be an expensive operation and/or may not be idempotent if some thread’s tags have been changed. So it’s harder to say what the advice should be in that case.) If other people think it would be useful, I can work on a patch to implement this approach. Footnotes: [1] Or having its tags changed generally. -- Aaron Ecay ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 2/4] emacs: repurpose notmuch-show-archive-thread-internal function for general thread tagging
Jameson, Some comments below: On Sat, 7 Jan 2012 14:28:12 -0800, Jameson Graef Rollins wrote: > Instead of having a function that is only used for archiving a thread, > we instead make it useful for any tagging operation. The new > function, notmuch-show-tag-thread-internal, now takes two more > arguments, for the "sign" of the tagging operation ("-" or "+"), and > the tag to be added or removed. This will allow this function to be > used for any generic thread tagging operation. > > The higher level functions that call this function are modified > accordingly. > --- > emacs/notmuch-show.el | 34 -- > 1 files changed, 20 insertions(+), 14 deletions(-) > > diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el > index 5502efd..1e16f05 100644 > --- a/emacs/notmuch-show.el > +++ b/emacs/notmuch-show.el > @@ -1414,20 +1414,26 @@ argument, hide all of the messages." >(interactive) >(backward-button 1)) > > -(defun notmuch-show-archive-thread-internal (show-next) > +(defun notmuch-show-tag-thread-internal (sign tag show-next) A couple of comments on the arguments: - It would be good to make show-next &optional. This will enable code to call the fn with only two arguments, and not showing next will be the default behavior. - A more lispy way of specifying the sign would be to use a boolean. Perhaps you could call this “remove”; a value of ‘t’ would remove the tag; ‘nil’ would add it. Moving this argument after ‘tag’ and also making it &optional woudl allow this fn to be called with one arg to add a tag. (Maybe this is too minimalist and API, however.) >;; Remove the tag from the current set of messages. >(goto-char (point-min)) > - (loop do (notmuch-show-remove-tag "inbox") > - until (not (notmuch-show-goto-message-next))) > - ;; Move to the next item in the search results, if any. > - (let ((parent-buffer notmuch-show-parent-buffer)) > -(notmuch-kill-this-buffer) > -(if parent-buffer > - (progn > - (switch-to-buffer parent-buffer) > - (forward-line) > - (if show-next > - (notmuch-search-show-thread)) > + (let ((tag-function)) No second set of parens is needed around tag-function. > +(cond > + ((string= sign "-") > + (setq tag-function 'notmuch-show-remove-tag)) > + ((string= sign "+") > + (setq tag-function 'notmuch-show-add-tag))) > +(loop do (funcall tag-function tag) > + until (not (notmuch-show-goto-message-next))) > +;; Move to the next item in the search results, if any. Does it make sense to separate the tagging and the movement? It seems plausible that some code somewhere might want to add/remove a tag from all messages in the thread w/o changing the display. > +(let ((parent-buffer notmuch-show-parent-buffer)) > + (notmuch-kill-this-buffer) > + (if parent-buffer > + (progn > + (switch-to-buffer parent-buffer) > + (forward-line) > + (if show-next > + (notmuch-search-show-thread))) -- Aaron Ecay ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 2/4] emacs: add option to notmuch-show-next-open-message to pop out to parent buffer if at end
Jameson, One small, stylistic/nitpicky comment :) On Sat, 7 Jan 2012 17:26:53 -0800, Jameson Graef Rollins wrote: > This will allow for keybindings that achieve a smoother message > processing flow by reducing the number of key presses needed for most > common operations. > --- > emacs/notmuch-show.el | 12 +--- > 1 files changed, 9 insertions(+), 3 deletions(-) > > diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el > index 8bb052e..e7bb958 100644 > --- a/emacs/notmuch-show.el > +++ b/emacs/notmuch-show.el > @@ -1264,17 +1264,23 @@ any effects from previous calls to >(notmuch-show-mark-read) >(notmuch-show-message-adjust)) > > -(defun notmuch-show-next-open-message () > +(defun notmuch-show-next-open-message (&optional pop-at-end) >"Show the next message." >(interactive) > - (let (r) > + (let ((r) > + (parent-buffer notmuch-show-parent-buffer)) No second set of parentheses is needed around r. Also, it is more idiomatic to put the initialized variable (i.e. parent-buffer) before the uninitialized one (r). > (while (and (setq r (notmuch-show-goto-message-next)) > (not (notmuch-show-message-visible-p > (if r > (progn > (notmuch-show-mark-read) > (notmuch-show-message-adjust)) > - (goto-char (point-max) > + (if (and parent-buffer pop-at-end) > + (progn > + (kill-this-buffer) > + (switch-to-buffer parent-buffer) > + (forward-line 1)) > + (goto-char (point-max)) > > (defun notmuch-show-previous-open-message () >"Show the previous message." > -- > 1.7.7.3 > > ___ > notmuch mailing list > notmuch@notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch -- Aaron Ecay ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH] emacs: call "notmuch tag" only once when archiving a thread
Quoth Aaron Ecay on Jan 08 at 7:56 pm: > On Thu, 05 Jan 2012 22:32:16 +0200, Jani Nikula wrote: > > [...] > > > In the show view it only modifies the messages that are currently > > visible. This is to make sure you don't accidentally archive things that > > have arrived after refreshing the buffer. I think this is safest. > > Hmm. Perhaps it would make sense to add a check in the search view that > the thread being archived[1] has the same number of messages as it did > when the buffer was constructed. (The information on how many messages > the thread has is in the buffer; we would then compare this to the result > of “notmuch count thread:000foo” when the user requests to archive.) If > the counts don’t match, the interface should show a message in the echo > area and (probably) refuse to do the tagging. That sounds like a clever workaround. There's been quite a bit of discussion on fixing this properly. See, for example id:"CAH-f9WsPj=1Eu=g3soepjgctbfs6hrldlq18xmenj8az00y...@mail.gmail.com". The gist is that we need to include message IDs (or document IDs) in the search output and use these in tagging operations, rather than the unstable thread:XXX queries. Unfortunately, actually fixing this got stalled since adding this information the text format is a fool's errand (having been the fool, I can say this!), so we need to switch Emacs over to using the JSON search format first. However, once that's done, it's a relatively simple change. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 1/4] emacs: new customization variable to exclude "deleted" messages from search
Jameson, One comment On Sat, 7 Jan 2012 14:28:11 -0800, Jameson Graef Rollins wrote: > The new customization variable, notmuch-search-exclude-deleted, when > set to t, will exclude any messages with the "deleted" tag from > searches. > > Additionally, specifying "tag:deleted" in the search directly will > override the exclusion and will included deleted messages in the > search results. > --- > emacs/notmuch.el |8 > test/emacs | 42 > > .../notmuch-search-tag-inbox-deleted-excluded | 24 +++ > 3 files changed, 74 insertions(+), 0 deletions(-) > create mode 100644 > test/emacs.expected-output/notmuch-search-tag-inbox-deleted-excluded > > diff --git a/emacs/notmuch.el b/emacs/notmuch.el > index fde2377..c519687 100644 > --- a/emacs/notmuch.el > +++ b/emacs/notmuch.el > @@ -905,6 +905,11 @@ PROMPT is the string to prompt with." >(read-from-minibuffer prompt nil keymap nil > 'notmuch-query-history nil nil > > +(defcustom notmuch-search-exclude-deleted nil > + "Exclude deleted messages (with \"deleted\" tag) from search results." > + :group 'notmuch > + :type 'boolean) > + > ;;;###autoload > (defun notmuch-search (query &optional oldest-first target-thread > target-line continuation) >"Run \"notmuch search\" with the given query string and display results. > @@ -927,6 +932,9 @@ The optional parameters are used as follows: > (set 'notmuch-search-target-thread target-thread) > (set 'notmuch-search-target-line target-line) > (set 'notmuch-search-continuation continuation) > +(when (and notmuch-search-exclude-deleted > +(not (string-match "tag:deleted[ )]*" query))) “is:” is a synonym for “tag:” in searches – so this section of the code should look for it too. -- Aaron Ecay ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 4/4] emacs: Use the new JSON reply format.
Adam, One comment below. On Sun, 8 Jan 2012 00:52:42 -0700, Adam Wolfe Gordon wrote: > From: Adam Wolfe Gordon > > Using the new JSON reply format allows emacs to quote HTML parts > nicely by first parsing them with w3m, then quoting them. This is > very useful for users who regularly receive HTML-only email. > > The behavior for messages that contain plain text parts should be > unchanged, except that an additional quoted line is added to the end > of the reply message. The test has been updated to reflect this. > --- > emacs/notmuch-mua.el | 62 +++-- > test/emacs |1 + > 2 files changed, 50 insertions(+), 13 deletions(-) > > diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el > index 7114e48..7f894cb 100644 > --- a/emacs/notmuch-mua.el > +++ b/emacs/notmuch-mua.el > @@ -19,6 +19,7 @@ > ;; > ;; Authors: David Edmondson > > +(require 'json) > (require 'message) > > (require 'notmuch-lib) > @@ -71,27 +72,62 @@ list." > (push header message-hidden-headers))) > notmuch-mua-hidden-headers)) > > +(defun w3m-region (start end)) ;; From `w3m.el'. What is the purpose of the above line? If it is to make the compiler aware of the function, you should use ‘declare-function’ instead. Defun will erase the original definition of the w3m-region function. -- Aaron Ecay ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 0/4] Quoting HTML-only emails in replies redux
On Sun, 8 Jan 2012 00:52:38 -0700, Adam Wolfe Gordon wrote: [...] > > There should probably be some customize variables for this in emacs, to > control > (for example) whether to quote HTML parts and whether to prefer HTML or > plaintext parts for quoting. Any suggestions for what should be customizable > would be appreciated. I think two variables should suffice: one (boolean) to control whether to quote standalone text/html parts, and one to control which parts of a multipart/alternative part to quote. The latter should take possible values 'text, 'html, and 'both. This requires the emacs reply functionality to distinguish between html parts that are part of a multipart/alternative and those which are not, which (AFAICT) the current code doesn’t do. I haven’t tested the patch yet, but it looks very promising. Thanks! -- Aaron Ecay ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 1/4] emacs: new customization variable to exclude "deleted" messages from search
> > @@ -927,6 +932,9 @@ The optional parameters are used as follows: > > (set 'notmuch-search-target-thread target-thread) > > (set 'notmuch-search-target-line target-line) > > (set 'notmuch-search-continuation continuation) > > +(when (and notmuch-search-exclude-deleted > > + (not (string-match "tag:deleted[ )]*" query))) > > “is:” is a synonym for “tag:” in searches – so this section of the code > should look for it too. There are several other things that could also trip up this regexp. xtag:deletedx would be falsely matched, as would a quoted phrase containing "tag:deleted", while tag:"deleted" and tag:(deleted) would incorrectly not be matched. Getting this right is hard, though I'd be happy with "\\<\\(tag\\|is\\):deleted\\>" or maybe "\\<\\(tag\\|is\\):\\(\"?\\)deleted\\>\\2" Implicit exclusions like this were actually one of my target features for the custom query parser, but I think hacking around that by inspecting the query string is a fine interim solution. (One of these months I'll dust off the query parser, really!) ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 1/4] emacs: new customization variable to exclude "deleted" messages from search
On Sun, 8 Jan 2012 20:49:38 -0500, Austin Clements wrote: > > > @@ -927,6 +932,9 @@ The optional parameters are used as follows: > > > (set 'notmuch-search-target-thread target-thread) > > > (set 'notmuch-search-target-line target-line) > > > (set 'notmuch-search-continuation continuation) > > > +(when (and notmuch-search-exclude-deleted > > > +(not (string-match "tag:deleted[ )]*" query))) > > > > “is:” is a synonym for “tag:” in searches – so this section of the code > > should look for it too. > > There are several other things that could also trip up this regexp. > xtag:deletedx would be falsely matched, as would a quoted phrase > containing "tag:deleted", while tag:"deleted" and tag:(deleted) would > incorrectly not be matched. Thanks so much for the review, guys. I should have mentioned in this patch that the my regex skills are very weak, and that it was surely incomplete. I always forget about the is: prefix as well. > Getting this right is hard, though I'd be happy with > > "\\<\\(tag\\|is\\):deleted\\>" Every time I think I start to understand regex I am reminded that it's black magic and I really know nothing. For instance, I am not familiar with "<" or ">", although they appear to be a "word" boundaries (although I'm not sure how "word" is defined). Also, why is all the \\ (double?) escaping needed? I'll certainly take your word for it, though. > or maybe > > "\\<\\(tag\\|is\\):\\(\"?\\)deleted\\>\\2" After staring at this for 10 minutes I think I'm getting the extra bits here. It matches an initial \", and then a second at the end if the first matched. That's clever. Why \\>\\2 instead of \\2\\> ? I'm definitely confused by why so much apparent escaping is needed, though. > Implicit exclusions like this were actually one of my target features > for the custom query parser, but I think hacking around that by > inspecting the query string is a fine interim solution. (One of these > months I'll dust off the query parser, really!) Very much looking forward to it! jamie. pgpkzMZ4QhJrn.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 1/4] emacs: new customization variable to exclude "deleted" messages from search
Quoth Jameson Graef Rollins on Jan 08 at 6:34 pm: > On Sun, 8 Jan 2012 20:49:38 -0500, Austin Clements wrote: > > > > @@ -927,6 +932,9 @@ The optional parameters are used as follows: > > > > (set 'notmuch-search-target-thread target-thread) > > > > (set 'notmuch-search-target-line target-line) > > > > (set 'notmuch-search-continuation continuation) > > > > +(when (and notmuch-search-exclude-deleted > > > > + (not (string-match "tag:deleted[ )]*" query))) > > > > > > “is:” is a synonym for “tag:” in searches – so this section of the code > > > should look for it too. > > > > There are several other things that could also trip up this regexp. > > xtag:deletedx would be falsely matched, as would a quoted phrase > > containing "tag:deleted", while tag:"deleted" and tag:(deleted) would > > incorrectly not be matched. > > Thanks so much for the review, guys. I should have mentioned in this > patch that the my regex skills are very weak, and that it was surely > incomplete. I always forget about the is: prefix as well. > > > Getting this right is hard, though I'd be happy with > > > > "\\<\\(tag\\|is\\):deleted\\>" > > Every time I think I start to understand regex I am reminded that it's > black magic and I really know nothing. For instance, I am not familiar > with "<" or ">", although they appear to be a "word" boundaries > (although I'm not sure how "word" is defined). Also, why is all the \\ > (double?) escaping needed? I'll certainly take your word for it, > though. I'm not positive, but I think \> matches on the transition from a "word-constituent" character to a non-word-constituent character, as defined by Emacs' active syntax table. The slashes are all doubled because I was writing it as an Emacs string for easy pasting (sorry, I should have been explicit about that). The regexp itself is \<\(tag\|is\):deleted\> > > or maybe > > > > "\\<\\(tag\\|is\\):\\(\"?\\)deleted\\>\\2" > > After staring at this for 10 minutes I think I'm getting the extra bits > here. It matches an initial \", and then a second at the end if the > first matched. That's clever. Why Exactly. > \\>\\2 > > instead of > > \\2\\> > > ? Okay, that can qualify as black magic. The problem is that a " will mess up the word-boundary matching because " isn't a word constituent character. So, if it is looking for a quote at the end, the \2 in \2\> would match and consume the ", but then the \> wouldn't match. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 2/4] emacs: repurpose notmuch-show-archive-thread-internal function for general thread tagging
Thanks so much for the review, Aaron. On Sun, 08 Jan 2012 20:08:59 -0500, Aaron Ecay wrote: > A couple of comments on the arguments: > - It would be good to make show-next &optional. This will enable code > to call the fn with only two arguments, and not showing next will be > the default behavior. That's a nice idea. Probably better for a separate patch, though. > - A more lispy way of specifying the sign would be to use a > boolean. Perhaps you could call this “remove”; a value of ‘t’ would > remove the tag; ‘nil’ would add it. Moving this argument after ‘tag’ > and also making it &optional woudl allow this fn to be called with one > arg to add a tag. (Maybe this is too minimalist and API, however.) That might be more lispy, but it seems a lot less clear to me. It might save a few keystrokes when coding, but it would definitely make the code a lot harder to read ("remove" to add a tag?). I think I would prefer people to give the sign explicitly. > No second set of parens is needed around tag-function. Yeah, I've seen this either way. I guess it's just a stylistic choice. I think it might make sense, but again I think that's out of the scope of this patch series. The point was to make a minimal set of modifications here. If we want to separate out the functionality, we should do that in a separate patch. Thanks again for the review. jamie. pgpIvCV7XaEoi.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 1/4] emacs: new customization variable to exclude "deleted" messages from search
Quoth myself on Jan 08 at 8:49 pm: > > > @@ -927,6 +932,9 @@ The optional parameters are used as follows: > > > (set 'notmuch-search-target-thread target-thread) > > > (set 'notmuch-search-target-line target-line) > > > (set 'notmuch-search-continuation continuation) > > > +(when (and notmuch-search-exclude-deleted > > > +(not (string-match "tag:deleted[ )]*" query))) > > > > “is:” is a synonym for “tag:” in searches – so this section of the code > > should look for it too. > > There are several other things that could also trip up this regexp. > xtag:deletedx would be falsely matched, as would a quoted phrase > containing "tag:deleted", while tag:"deleted" and tag:(deleted) would > incorrectly not be matched. Getting this right is hard, though I'd be > happy with > > "\\<\\(tag\\|is\\):deleted\\>" > > or maybe > > "\\<\\(tag\\|is\\):\\(\"?\\)deleted\\>\\2" For the record, here's a More Correct (TM) version "\\(^\\|[-+ ()]\\)\\(tag\\|is\\):\\(\"?\\)deleted\\3\\($\\|[ ()]\\)" However, as we discussed on IRC, it's probably better to fix this in the CLI/library by adding a config option for auto-excluded tags, an API to register these with the library (probably part of the query API), and to iterate over the terms in the parsed query to determine which tag exclusions should be automatically added. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 2/4] emacs: repurpose notmuch-show-archive-thread-internal function for general thread tagging
On Sun, 08 Jan 2012 18:49:56 -0800, Jameson Graef Rollins wrote: > Thanks so much for the review, Aaron. > > On Sun, 08 Jan 2012 20:08:59 -0500, Aaron Ecay wrote: > > A couple of comments on the arguments: > > - It would be good to make show-next &optional. This will enable code > > to call the fn with only two arguments, and not showing next will be > > the default behavior. > > That's a nice idea. Probably better for a separate patch, though. This patch introduces show-next as a new argument to the function. So it can and should make it &optional, if that is the appropriate semantics for it to have. > > > - A more lispy way of specifying the sign would be to use a > > boolean. Perhaps you could call this “remove”; a value of ‘t’ would > > remove the tag; ‘nil’ would add it. Moving this argument after ‘tag’ > > and also making it &optional woudl allow this fn to be called with one > > arg to add a tag. (Maybe this is too minimalist and API, however.) > > That might be more lispy, but it seems a lot less clear to me. It might > save a few keystrokes when coding, but it would definitely make the code > a lot harder to read ("remove" to add a tag?). I think I would prefer > people to give the sign explicitly. Using a string value makes it harder to interface with other code. For example, the prefix argument (C-u) is delivered to emacs commands as a boolean value (nil if no arg, something truthy if the arg is given). A plausible custom end user function/keybinding would be one to add a tag to the open messages, or remove that tag if the prefix arg is given to the same command. (So that ‘d’ deletes and ‘C-u d’ undeletes, for example.) In order to do that, the user’s code has to convert the prefix arg into a string. Making something “lispy” isn’t just about code readability/saving keystrokes, but also refers to how well the code interfaces with the conventions used by the rest of the emacs environment. That said, here’s an alternate proposal: provide two functions as the “external” API, namely ‘notmuch-show-{add,remove}-tag-thread’ (by parallelism with ‘notmuch-show-{add,remove}-tag’). These could be thin wrappers around ‘notmuch-show-tag-thread-internal’, which would then not be intended to be called by user code. > > > No second set of parens is needed around tag-function. > > Yeah, I've seen this either way. I guess it's just a stylistic > choice. Using double parens is semantically correct, but makes the code less idiomatic and harder to read (IMO). To test my intuition, I looked at ‘let’ invocations in the Emacs source that have a non-initialized variable (because the multiple variable case is hard to grep for). Double parens are used only 3% of the time (44 double vs 1468 single). Make of this data what you will. -- Aaron Ecay ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: notmuch git's disk is full! ERROR pushing.
On Sun, 08 Jan 2012 13:55:53 +0100, Sebastian Spaeth wrote: > Actually trying to push the above 2 patches, I get > > Writing objects: 100% (8/8), 1.25 KiB, done. > Total 8 (delta 5), reused 0 (delta 0) > error: unable to create temporary sha1 filename : No space left on > device My apologies! I've relieved the immediate problem for now. (And I'm hoping to soon move notmuchmail.org to a different server with a disk that's a couple of orders of magnitude larger.) -Carl pgpiSNTzVnsTM.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: Python bindings for adoption
Hurray, thanks Justus. That is much appreciated. Spaetz David Bremner schrieb: >On Sun, 08 Jan 2012 16:16:06 -, Justus Winter ><4win...@informatik.uni-hamburg.de> wrote: >> >> I've decided to step up as a new maintainer for the libnotmuch python >> bindings. I assume that I'll have to mail an ssh public key to >someone >> for repository access, right? >> > >That's right. Carl (in copy) handles repository access. > >d ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[RFC PATCH 0/9] -std=c99 / -std=c++0x -pedantic
Hi all, this series was borne of curiousity about compiling the notmuch codebase using -std=c99 / -std=c++0x -pedantic options. The C part is split into separate patches to make it easier to see each warning and fix; with C++ I didn't bother so much. Turns out there are a few specific issues, but overall it's not too bad. However my gut feeling is that some of the fixes to get standards compliance are uglier than just using the GCC extensions. The question is, do we care about anything other than GCC? Comments and discussion welcome; that was the whole point here rather than any serious effort for merging these. (But that can follow if people think this is worth it.) BR, Jani. Jani Nikula (9): build: use -std=c99 -pedantic for C source xutil: #define _POSIX_C_SOURCE to get strdup() lib: fix messages.c build warn lib: HACK: avoid warnings from talloc_steal() cli: fix warning about variadic macros cli: fix another warning about variadic macros util: fix warning about variadic macros lib: use -std=c++0x -pedantic test: smtp-dummy: fixes for -std=c99 -pedantic configure |4 ++-- lib/database.cc |3 +-- lib/message.cc|2 +- lib/messages.c|6 -- lib/notmuch-private.h |8 +--- lib/tags.c|5 - lib/thread.cc |2 +- notmuch-client.h |9 ++--- notmuch-setup.c |7 +-- test/smtp-dummy.c |4 +++- util/error_util.h |8 +--- util/xutil.c |2 ++ 12 files changed, 39 insertions(+), 21 deletions(-) -- 1.7.5.4
[RFC PATCH 1/9] build: use -std=c99 -pedantic for C source
Signed-off-by: Jani Nikula --- configure |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index e90b76f..f84262d 100755 --- a/configure +++ b/configure @@ -25,8 +25,8 @@ fi # environment variables) CC=${CC:-gcc} CXX=${CXX:-g++} -CFLAGS=${CFLAGS:--O2} -CXXFLAGS=${CXXFLAGS:-\$(CFLAGS)} +CFLAGS=${CFLAGS:--O2 -std=c99 -pedantic} +CXXFLAGS=${CXXFLAGS:--O2} LDFLAGS=${LDFLAGS:-} XAPIAN_CONFIG=${XAPIAN_CONFIG:-xapian-config} -- 1.7.5.4
[RFC PATCH 2/9] xutil: #define _POSIX_C_SOURCE to get strdup()
strdup() is not standard C99. #define _POSIX_C_SOURCE 200809L to use it. This fixes -std=c99 -pedantic warning: util/xutil.c: In function ?xstrdup?: util/xutil.c:74:5: warning: implicit declaration of function ?strdup? [-Wimplicit-function-declaration] util/xutil.c:74:9: warning: assignment makes pointer from integer without a cast [enabled by default] Signed-off-by: Jani Nikula --- util/xutil.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/util/xutil.c b/util/xutil.c index ac496da..55b818b 100644 --- a/util/xutil.c +++ b/util/xutil.c @@ -18,6 +18,8 @@ * Author: Carl Worth */ +#define _POSIX_C_SOURCE 200809L /* for strdup() */ + #include #include -- 1.7.5.4
[RFC PATCH 4/9] lib: HACK: avoid warnings from talloc_steal()
talloc.h #defines talloc_steal() with macros to make it type safe, but introduces a warning when compiled using -std=c99 -pedantic: lib/tags.c: In function ?_notmuch_tags_create?: lib/tags.c:43:5: warning: ISO C forbids braced-groups within expressions [-pedantic] Call _talloc_steal_loc() directly without the macro wrapper. We aren't even interested in the return value the macro is so hard trying to provide type safety for. Signed-off-by: Jani Nikula --- lib/tags.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/lib/tags.c b/lib/tags.c index c58924f..56c43e2 100644 --- a/lib/tags.c +++ b/lib/tags.c @@ -40,7 +40,10 @@ _notmuch_tags_create (const void *ctx, notmuch_string_list_t *list) return NULL; tags->iterator = list->head; -talloc_steal (tags, list); + +/* _talloc_steal_loc() is talloc_steal() without macro wrapping to avoid + * -std=c99 -pedantic warning. __location__ is defined in talloc.h. */ +_talloc_steal_loc (tags, list, __location__); return tags; } -- 1.7.5.4
[RFC PATCH 3/9] lib: fix messages.c build warn
lib/messages.c: In function ?notmuch_messages_move_to_next?: lib/messages.c:131:2: warning: ISO C forbids ?return? with expression, in function returning void [-pedantic] Signed-off-by: Jani Nikula --- lib/messages.c |6 -- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/messages.c b/lib/messages.c index 7bcd1ab..1121864 100644 --- a/lib/messages.c +++ b/lib/messages.c @@ -127,8 +127,10 @@ notmuch_messages_get (notmuch_messages_t *messages) void notmuch_messages_move_to_next (notmuch_messages_t *messages) { -if (! messages->is_of_list_type) - return _notmuch_mset_messages_move_to_next (messages); +if (! messages->is_of_list_type) { + _notmuch_mset_messages_move_to_next (messages); + return; +} if (messages->iterator == NULL) return; -- 1.7.5.4
[RFC PATCH 5/9] cli: fix warning about variadic macros
notmuch-restore.c: In function ?notmuch_restore_command?: notmuch-restore.c:87:54: warning: ISO C99 requires rest arguments to be used [enabled by default] and elsewhere. ##__VA_ARGS__ is a GCC CPP extension. Signed-off-by: Jani Nikula --- notmuch-client.h |9 ++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/notmuch-client.h b/notmuch-client.h index 517c010..3f4751a 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -93,14 +93,17 @@ typedef struct notmuch_show_params { * * Note that __location__ comes from talloc.h. */ -#define INTERNAL_ERROR(format, ...)\ + +#define _INTERNAL_ERROR(format, ...) \ do { \ fprintf(stderr, \ - "Internal error: " format " (%s)\n",\ - ##__VA_ARGS__, __location__); \ + "Internal error: " format "%s (%s)\n", \ + __VA_ARGS__, __location__); \ exit (1); \ } while (0) +#define INTERNAL_ERROR(...) _INTERNAL_ERROR(__VA_ARGS__, "") + #define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr[0])) #define STRNCMP_LITERAL(var, literal) \ -- 1.7.5.4
[RFC PATCH 6/9] cli: fix another warning about variadic macros
notmuch-setup.c: In function ?notmuch_setup_command?: notmuch-setup.c:144:62: warning: ISO C99 requires rest arguments to be used [enabled by default] notmuch-setup.c:174:18: warning: ISO C99 requires rest arguments to be used [enabled by default] Signed-off-by: Jani Nikula --- notmuch-setup.c |7 +-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/notmuch-setup.c b/notmuch-setup.c index c3ea937..7b25680 100644 --- a/notmuch-setup.c +++ b/notmuch-setup.c @@ -102,9 +102,9 @@ notmuch_setup_command (unused (void *ctx), const char **new_tags; size_t new_tags_len; -#define prompt(format, ...)\ +#define __prompt(format, ...) \ do { \ - printf (format, ##__VA_ARGS__); \ + printf (format, __VA_ARGS__); \ fflush (stdout);\ if (getline (&response, &response_size, stdin) < 0) { \ printf ("Exiting.\n"); \ @@ -113,6 +113,9 @@ notmuch_setup_command (unused (void *ctx), chomp_newline (response); \ } while (0) +#define _prompt(format, ...) __prompt(format "%s", __VA_ARGS__) +#define prompt(...) _prompt(__VA_ARGS__, "") + config = notmuch_config_open (ctx, NULL, &is_new); if (is_new) -- 1.7.5.4
[RFC PATCH 7/9] util: fix warning about variadic macros
lib/string-list.c: In function ?_notmuch_string_list_sort?: lib/string-list.c:81:59: warning: ISO C99 requires rest arguments to be used [enabled by default] lib/message-file.c: In function ?notmuch_message_file_restrict_headersv?: lib/message-file.c:147:90: warning: ISO C99 requires rest arguments to be used [enabled by default] Signed-off-by: Jani Nikula --- util/error_util.h |8 +--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/util/error_util.h b/util/error_util.h index bb15822..75709da 100644 --- a/util/error_util.h +++ b/util/error_util.h @@ -38,8 +38,10 @@ _internal_error (const char *format, ...) PRINTF_ATTRIBUTE (1, 2); * * Note that __location__ comes from talloc.h. */ -#define INTERNAL_ERROR(format, ...)\ -_internal_error (format " (%s).\n",\ -##__VA_ARGS__, __location__) +#define _INTERNAL_ERROR(format, ...) \ +_internal_error (format "%s (%s).\n", \ +__VA_ARGS__, __location__) + +#define INTERNAL_ERROR(...) _INTERNAL_ERROR(__VA_ARGS__, "") #endif -- 1.7.5.4
[RFC PATCH 9/9] test: smtp-dummy: fixes for -std=c99 -pedantic
Signed-off-by: Jani Nikula --- test/smtp-dummy.c |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/test/smtp-dummy.c b/test/smtp-dummy.c index 3801a5e..1c29a7d 100644 --- a/test/smtp-dummy.c +++ b/test/smtp-dummy.c @@ -33,6 +33,8 @@ * have been warned. */ +#define _POSIX_C_SOURCE 200809L /* for getline() and fdopen() */ + #include #include #include @@ -162,7 +164,7 @@ main (int argc, char *argv[]) memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; addr.sin_port = htons (25025); - addr.sin_addr = *(struct in_addr *) hostinfo->h_addr; + addr.sin_addr = *(struct in_addr *) hostinfo->h_addr_list[0]; err = bind (sock, (struct sockaddr *) &addr, sizeof(addr)); if (err) { fprintf (stderr, "Error: bind() failed: %s\n", -- 1.7.5.4
[RFC PATCH 8/9] lib: use -std=c++0x -pedantic
Introduces warnings such as: In file included from /usr/include/gmime-2.4/gmime/gmime.h:39:0, from lib/database.cc:31: /usr/include/gmime-2.4/gmime/gmime-message.h:57:26: warning: comma at end of enumerator list [-pedantic] Signed-off-by: Jani Nikula --- configure |2 +- lib/database.cc |3 +-- lib/message.cc|2 +- lib/notmuch-private.h |8 +--- lib/thread.cc |2 +- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/configure b/configure index f84262d..30831f3 100755 --- a/configure +++ b/configure @@ -26,7 +26,7 @@ fi CC=${CC:-gcc} CXX=${CXX:-g++} CFLAGS=${CFLAGS:--O2 -std=c99 -pedantic} -CXXFLAGS=${CXXFLAGS:--O2} +CXXFLAGS=${CXXFLAGS:--O2 -std=c++0x -pedantic} LDFLAGS=${LDFLAGS:-} XAPIAN_CONFIG=${XAPIAN_CONFIG:-xapian-config} diff --git a/lib/database.cc b/lib/database.cc index 8103bd9..b59497b 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -1352,8 +1352,7 @@ _resolve_message_id_to_thread_id (notmuch_database_t *notmuch, return status; if (message) { - *thread_id_ret = talloc_steal (ctx, - notmuch_message_get_thread_id (message)); + *thread_id_ret = (const char *) _talloc_steal_loc (ctx, notmuch_message_get_thread_id (message), __location__); notmuch_message_destroy (message); diff --git a/lib/message.cc b/lib/message.cc index 0075425..ed7398a 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -220,7 +220,7 @@ _notmuch_message_create_for_message_id (notmuch_database_t *notmuch, message_id, &message); if (message) - return talloc_steal (notmuch, message); + return (notmuch_message_t *) _talloc_steal_loc (notmuch, message, __location__); else if (*status_ret) return NULL; diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 60a932f..7694705 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -137,15 +137,17 @@ typedef enum _notmuch_private_status { * that the caller has previously handled any expected * notmuch_private_status_t values.) */ -#define COERCE_STATUS(private_status, format, ...) \ +#define _COERCE_STATUS(private_status, format, ...)\ ((private_status >= (notmuch_private_status_t) NOTMUCH_STATUS_LAST_STATUS)\ ? \ - (notmuch_status_t) _internal_error (format " (%s).\n",\ - ##__VA_ARGS__, \ + (notmuch_status_t) _internal_error (format "%s (%s).\n", \ + __VA_ARGS__, \ __location__) \ : \ (notmuch_status_t) private_status) +#define COERCE_STATUS(private_status, ...) _COERCE_STATUS(private_status, __VA_ARGS__, "") + typedef struct _notmuch_doc_id_set notmuch_doc_id_set_t; /* database.cc */ diff --git a/lib/thread.cc b/lib/thread.cc index 0435ee6..e8f169c 100644 --- a/lib/thread.cc +++ b/lib/thread.cc @@ -224,7 +224,7 @@ _thread_add_message (notmuch_thread_t *thread, char *clean_author; _notmuch_message_list_add_message (thread->message_list, - talloc_steal (thread, message)); + (notmuch_message_t *) _talloc_steal_loc (thread, message, __location__)); thread->total_messages++; g_hash_table_insert (thread->message_hash, -- 1.7.5.4
[PATCH 0/4] Quoting HTML-only emails in replies redux
From: Adam Wolfe Gordon Hi everyone, This is a rework of my previous patch series adding support for replying to HTML email in the emacs interface (id:1322671241-23438-1-git-send-email-awg+notmuch at xvx.ca). It was suggested on IRC that a more general solution would be to add a JSON format to notmuch reply, and then have the emacs client parse the JSON to create an appropriate reply. This patchset implements that. The previous patches had an issue with emails that contained both HTML and plaintext parts, where all the parts would end up quoted. This version avoids that problem, since the emacs interface can easily check whether there are plaintext parts and avoid quoting HTML parts if there are. There should probably be some customize variables for this in emacs, to control (for example) whether to quote HTML parts and whether to prefer HTML or plaintext parts for quoting. Any suggestions for what should be customizable would be appreciated. I know Jani is currently working on some reply-related patches (the reply-all vs. reply-one set). These changes probably won't merge cleanly with those changes, so some care might be required. If his changes are pushed first, I'll happily rebase and send a new set. Thanks in advance for any reviews. Adam Wolfe Gordon (4): test: Add broken test for the new JSON reply format. reply: Add a JSON reply format. man: Update notmuch-reply man page for JSON format. emacs: Use the new JSON reply format. emacs/notmuch-mua.el | 62 +--- man/man1/notmuch-reply.1 |5 + notmuch-reply.c | 269 +++--- test/emacs |1 + test/multipart |7 ++ 5 files changed, 292 insertions(+), 52 deletions(-) -- 1.7.5.4
[PATCH 1/4] test: Add broken test for the new JSON reply format.
From: Adam Wolfe Gordon --- test/multipart |7 +++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/test/multipart b/test/multipart index f83526b..f5ebf04 100755 --- a/test/multipart +++ b/test/multipart @@ -589,6 +589,13 @@ Non-text part: text/html EOF test_expect_equal_file OUTPUT EXPECTED +test_begin_subtest "'notmuch reply' to a multipart message with json format" +notmuch reply --format=json 'id:87liy5ap00.fsf at yoom.home.cworth.org' >OUTPUT +cat", "references": " <87liy5ap00.fsf at yoom.home.cworth.org>"} }, "original": { "headers": { "from": "Carl Worth ", "to": "cworth at cworth.org", "cc": "", "subject": "Multipart message", "date": "Fri, 05 Jan 2001 15:43:57 +", "in-reply-to": "", "references": "" }, "body": [ { "content-type": "text/html", "content": "This is an embedded message, with a multipart/alternative part.\n"}, { "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}, { "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}, {} ] } }, {} ] +EOF +test_expect_equal_file OUTPUT EXPECTED + test_begin_subtest "'notmuch show --part' does not corrupt a part with CRLF pair" notmuch show --format=raw --part=3 id:base64-part-with-crlf > crlf.out echo -n -e "\xEF\x0D\x0A" > crlf.expected -- 1.7.5.4
[PATCH 3/4] man: Update notmuch-reply man page for JSON format.
From: Adam Wolfe Gordon --- man/man1/notmuch-reply.1 |5 + 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/man/man1/notmuch-reply.1 b/man/man1/notmuch-reply.1 index 099d808..240dfed 100644 --- a/man/man1/notmuch-reply.1 +++ b/man/man1/notmuch-reply.1 @@ -41,6 +41,11 @@ include .BR default Includes subject and quoted message body. .TP +.BR json +Produces JSON output containing headers for a reply message and the +headers and text parts of the original message. This output can be used +by a client to create a reply message intelligently. +.TP .BR headers\-only Only produces In\-Reply\-To, References, To, Cc, and Bcc headers. .RE -- 1.7.5.4
[PATCH 2/4] reply: Add a JSON reply format.
From: Adam Wolfe Gordon This new JSON format for replies includes headers generated for a reply message as well as the headers and all text parts of the original message. Using this data, a client can intelligently create a reply. For example, the emacs client will be able to create replies with quoted HTML parts by parsing the HTML parts using w3m. --- notmuch-reply.c | 269 +++ 1 files changed, 230 insertions(+), 39 deletions(-) diff --git a/notmuch-reply.c b/notmuch-reply.c index f8d5f64..82df396 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -30,6 +30,15 @@ reply_headers_message_part (GMimeMessage *message); static void reply_part_content (GMimeObject *part); +static void +reply_part_start_json (GMimeObject *part, int *part_count); + +static void +reply_part_content_json (GMimeObject *part); + +static void +reply_part_end_json (GMimeObject *part); + static const notmuch_show_format_t format_reply = { "", "", NULL, @@ -46,6 +55,22 @@ static const notmuch_show_format_t format_reply = { "" }; +static const notmuch_show_format_t format_json = { +"", + "", NULL, + "", NULL, NULL, "", + "", + reply_part_start_json, + NULL, + NULL, + reply_part_content_json, + reply_part_end_json, + "", + "", + "", "", +"" +}; + static void show_reply_headers (GMimeMessage *message) { @@ -147,6 +172,78 @@ reply_part_content (GMimeObject *part) } } +static void +reply_part_start_json (GMimeObject *part, unused(int *part_count)) +{ +GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part)); +GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (part); + +if (g_mime_content_type_is_type (content_type, "text", "*") && + (!disposition || +strcmp (disposition->disposition, GMIME_DISPOSITION_INLINE) == 0)) +{ + printf("{ "); +} +} + +static void +reply_part_end_json (GMimeObject *part) +{ +GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part)); +GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (part); + +if (g_mime_content_type_is_type (content_type, "text", "*") && + (!disposition || +strcmp (disposition->disposition, GMIME_DISPOSITION_INLINE) == 0)) + printf ("}, "); +} + +static void +reply_part_content_json (GMimeObject *part) +{ +GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part)); +GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (part); + +void *ctx = talloc_new (NULL); + +/* We only care about inline text parts for reply purposes */ +if (g_mime_content_type_is_type (content_type, "text", "*") && + (!disposition || +strcmp (disposition->disposition, GMIME_DISPOSITION_INLINE) == 0)) +{ + GMimeStream *stream_memory = NULL, *stream_filter = NULL; + GMimeDataWrapper *wrapper; + GByteArray *part_content; + const char *charset; + + printf("\"content-type\": %s, \"content\": ", + json_quote_str(ctx, g_mime_content_type_to_string(content_type))); + + charset = g_mime_object_get_content_type_parameter (part, "charset"); + stream_memory = g_mime_stream_mem_new (); + if (stream_memory) { + stream_filter = g_mime_stream_filter_new(stream_memory); + if (charset) { + g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter), +g_mime_filter_charset_new(charset, "UTF-8")); + } + } + wrapper = g_mime_part_get_content_object (GMIME_PART (part)); + if (wrapper && stream_filter) + g_mime_data_wrapper_write_to_stream (wrapper, stream_filter); + part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (stream_memory)); + + printf("%s", json_quote_chararray(ctx, (char *) part_content->data, part_content->len)); + + if (stream_filter) + g_object_unref(stream_filter); + if (stream_memory) + g_object_unref(stream_memory); +} + +talloc_free (ctx); +} + /* Is the given address configured as one of the user's "personal" or * "other" addresses. */ static int @@ -476,6 +573,59 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message return NULL; } +static GMimeMessage * +create_reply_message(void *ctx, +notmuch_config_t *config, +notmuch_message_t *message) +{ +const char *subject, *from_addr = NULL; +const char *in_reply_to, *orig_references, *references; + +/* The 1 means we want headers in a "pretty" order. */ +GMimeMessage *reply = g_mime_message_new (1); +if (reply == NULL) { + fprintf (stderr, "Out of
[PATCH 4/4] emacs: Use the new JSON reply format.
From: Adam Wolfe Gordon Using the new JSON reply format allows emacs to quote HTML parts nicely by first parsing them with w3m, then quoting them. This is very useful for users who regularly receive HTML-only email. The behavior for messages that contain plain text parts should be unchanged, except that an additional quoted line is added to the end of the reply message. The test has been updated to reflect this. --- emacs/notmuch-mua.el | 62 +++-- test/emacs |1 + 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index 7114e48..7f894cb 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -19,6 +19,7 @@ ;; ;; Authors: David Edmondson +(require 'json) (require 'message) (require 'notmuch-lib) @@ -71,27 +72,62 @@ list." (push header message-hidden-headers))) notmuch-mua-hidden-headers)) +(defun w3m-region (start end)) ;; From `w3m.el'. +(defun notmuch-mua-quote-part (part) + (with-temp-buffer +(insert part) +(message-mode) +(fill-region (point-min) (point-max)) +(goto-char (point-min)) +(perform-replace "^" "> " nil t nil) +(set-buffer-modified-p nil) +(buffer-substring (point-min) (point-max +(defun notmuch-mua-parse-html-part (part) + (with-temp-buffer +(insert part) +(w3m-region (point-min) (point-max)) +(set-buffer-modified-p nil) +(buffer-substring (point-min) (point-max (defun notmuch-mua-reply (query-string &optional sender) - (let (headers + (let (reply + original + headers body - (args '("reply"))) + (args '("reply" "--format=json"))) (if notmuch-show-process-crypto (setq args (append args '("--decrypt" (setq args (append args (list query-string))) -;; This make assumptions about the output of `notmuch reply', but -;; really only that the headers come first followed by a blank -;; line and then the body. +;; Get the reply object as JSON, and parse it into an elisp object. (with-temp-buffer (apply 'call-process (append (list notmuch-command nil (list t t) nil) args)) (goto-char (point-min)) - (if (re-search-forward "^$" nil t) - (save-excursion - (save-restriction - (narrow-to-region (point-min) (point)) - (goto-char (point-min)) - (setq headers (mail-header-extract) - (forward-line 1) - (setq body (buffer-substring (point) (point-max + (setq reply (aref (json-read) 0))) + +;; Get the list of headers +(setq headers (cdr (assq 'headers (assq 'reply reply +;; Construct the body of the reply. +(setq original (cdr (assq 'original reply))) + +;; Start with the prelude, based on the headers of the original message. +(let ((original-headers (cdr (assq 'headers original + (setq body (format "On %s, %s wrote:\n" +(cdr (assq 'date original-headers)) +(cdr (assq 'from original-headers) + +;; Extract the body parts and construct a reasonable quoted body. +(let* ((body-parts (cdr (assq 'body original))) + (find-parts (lambda (type) (delq nil (mapcar (lambda (part) + (if (string= (cdr (assq 'content-type part)) type) + (cdr (assq 'content part + body-parts + (plain-parts (apply find-parts '("text/plain"))) + (html-parts (apply find-parts '("text/html" + + (if (not (null plain-parts)) + (mapc (lambda (part) (setq body (concat body (notmuch-mua-quote-part part plain-parts) + (mapc (lambda (part) (setq body (concat body (notmuch-mua-quote-part (notmuch-mua-parse-html-part part) html-parts))) +(setq body (concat body "\n")) + ;; If sender is non-nil, set the From: header to its value. (when sender (mail-header-set 'from sender headers)) diff --git a/test/emacs b/test/emacs index a06c223..fe501da 100755 --- a/test/emacs +++ b/test/emacs @@ -270,6 +270,7 @@ Fcc: $(pwd)/mail/sent --text follows this line-- On 01 Jan 2000 12:00:00 -, Notmuch Test Suite wrote: > This is a test that messages are sent via SMTP +> EOF test_expect_equal_file OUTPUT EXPECTED -- 1.7.5.4
Distributed Notmuch
Hi guys, It's kind of academic for me right now because I'm mostly just using one computer, but one reason I've hesitated to switch over entirely to notmuch is that it's hard to distribute across many machines. The last time I wrote the list about this, David Bremner pointed me to gitmuch in the notmuch-scripts package, which uses git to synchronize tags. He wrote, "No one claims this is a great solution, but it works now." In brainstorming about the One True Mail Setup, my friend suggested to me that Maildir/IMAP are not really the best choices for mail storage. Among other flaws: to synchronize mail via IMAP you have to check the headers of each message, which means a lot of bandwidth; you can't compress Maildir, meaning lots of wasted space; mechanisms to synchronize arbitrary tags have to be bolted on top. My friend suggested that instead it might be better to dump mail into some kind of database, for example CouchDB, and synchronize it that way. Of course, doing full-text indexing and tagging using an arbitrary DB would be a ton of work, so instead it probably makes the most sense to keep a Xapian instance on each node and feed all the mail to that. Tagging operations still have to be replicated, probably by an oplog that's also kept in Couch, so it's still a lot of work, but keeping things in Couch automatically gets you a lot of the replication mechanisms, offline access, etc., that would have to be bolted on/hacked up using tools like nmbug/gitmuch/rsync. I also see in the wiki that someone proposes to use git as the mail store, presumably for similar reasons. Xapian itself has the idea of master/slave replication but that doesn't really get you full offline access. So my question for the wizards on this list is what their idea of the One True Mail Setup would be in a perfect, or slightly better, world, and what needs to be done to get there. I know some people use one notmuch install that they access remotely. For myself, I'm on a pretty limited Internet connection, so low bandwidth/offline access are big for me, and despite Nicolas Sebrecht and Sebastian Spaeth's heroic work on OfflineIMAP, it still uses a lot of bandwidth to sync. And obviously the whole point of this exercise is tag synchronization.. Ethan
[PATCH 1/2] clean up "compare thread ids" python test
On Mon, 2 Jan 2012 14:51:26 +, Patrick Totzke wrote: > This makes the test script open the database in READ_ONLY mode > and use the libraries own sorting methods instead of "sort". +1 I don't want to fudge the tests (I don't know a thing about them), so I can't judge the test outcome, but it is certainly good from the python side of things. So I'll push this one. -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 197 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20120108/650448f0/attachment-0001.pgp>
[PATCH 1/4] Add the option "--reply-to" to notmuch reply.
On Fri, 6 Jan 2012 13:34:14 +, Mark Walters wrote: > Possible values for this option are "sender" which replies just to > sender and "all" (the default). > > More precisely reply to sender follows these rules: > reply only to sender unless it was the user > reply only to all people on the "to" line unless they were all the user > reply to all people on the "cc" line > > Implementation details > > We continue parsing addresses beyond the ones we reply to because > we want to make sure the from address is correct. (At the very least it > is the same as it would be if we replied to all.) > > We overload the message variable in add_recipients_for_address_list so > if it is NULL we parse the address (looking for the users address) > but do not add to the message recipients list > > We add the variable reply_to_all to the function chain to keep track > of whether we should reply to everyone. > --- > notmuch-reply.c | 48 +--- > 1 files changed, 37 insertions(+), 11 deletions(-) > > diff --git a/notmuch-reply.c b/notmuch-reply.c > index f8d5f64..9a77fe6 100644 > --- a/notmuch-reply.c > +++ b/notmuch-reply.c > @@ -212,7 +212,8 @@ add_recipients_for_address_list (GMimeMessage *message, > if (ret == NULL) > ret = addr; > } else { > - g_mime_message_add_recipient (message, type, name, addr); > + if (message) > + g_mime_message_add_recipient (message, type, name, addr); > } > } > } > @@ -292,7 +293,8 @@ reply_to_header_is_redundant (notmuch_message_t *message) > static const char * > add_recipients_from_message (GMimeMessage *reply, >notmuch_config_t *config, > - notmuch_message_t *message) > + notmuch_message_t *message, > + int reply_to_all) > { > struct { > const char *header; > @@ -332,9 +334,20 @@ add_recipients_from_message (GMimeMessage *reply, > recipients = notmuch_message_get_header (message, >reply_to_map[i].fallback); > > - addr = add_recipients_for_string (reply, config, > - reply_to_map[i].recipient_type, > - recipients); > + > + /* We add the addresses if we are replying to all or we have not yet > found > + * a non-user address. We have to keep parsing to make sure we do find > the > + * correct from address for the user, but we pass a NULL message > + */ > + if ((reply_to_all) || (g_mime_message_get_all_recipients (reply) == > NULL)) Looking into this, it occurred to me g_mime_message_get_all_recipients() allocates a new InternetAddressList when the return value is non-NULL. Thus this leaks memory. OTOH allocating and deallocating for this purpose seems suboptimal. I'll think this over. BR, Jani. > + addr = add_recipients_for_string (reply, config, > + reply_to_map[i].recipient_type, > + recipients); > + else > + addr = add_recipients_for_string (NULL, config, > +reply_to_map[i].recipient_type, > +recipients); > + > if (from_addr == NULL) > from_addr = addr; > } > @@ -480,7 +493,8 @@ static int > notmuch_reply_format_default(void *ctx, >notmuch_config_t *config, >notmuch_query_t *query, > - notmuch_show_params_t *params) > + notmuch_show_params_t *params, > + int reply_to_all) > { > GMimeMessage *reply; > notmuch_messages_t *messages; > @@ -509,7 +523,7 @@ notmuch_reply_format_default(void *ctx, > g_mime_message_set_subject (reply, subject); > } > > - from_addr = add_recipients_from_message (reply, config, message); > + from_addr = add_recipients_from_message (reply, config, message, > reply_to_all); > > if (from_addr == NULL) > from_addr = guess_from_received_header (config, message); > @@ -558,7 +572,8 @@ static int > notmuch_reply_format_headers_only(void *ctx, > notmuch_config_t *config, > notmuch_query_t *query, > - unused (notmuch_show_params_t *params)) > + unused (notmuch_show_params_t *params), > + int reply_to_all) > { > GMimeMessage *reply; > notmuch_messages_t *messages; > @@ -598,7 +613,7 @@ notmuch_reply_format_headers_only(void *ctx, > g_mime_object_set_header (GMIME_OBJECT (reply), >
[PATCH 2/2] python test "compare message ids"
On Mon, 2 Jan 2012 14:51:27 +, Patrick Totzke wrote: > Introduces a second (trivial) test for the python > bindings that searches for message ids and compares > the output with that of `notmuch search`. Test passes, so it went in. -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 197 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20120108/4b63d90c/attachment.pgp>
notmuch git's disk is full! ERROR pushing.
Actually trying to push the above 2 patches, I get Writing objects: 100% (8/8), 1.25 KiB, done. Total 8 (delta 5), reused 0 (delta 0) error: unable to create temporary sha1 filename : No space left on device fatal: failed to write object error: unpack failed: unpack-objects abnormal exit To ssh://spaetz at notmuchmail.org/git/notmuch ! [remote rejected] master -> master (n/a (unpacker error)) error: failed to push some refs to 'ssh://spaetz at notmuchmail.org/git/notmuch' Sebastian -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 197 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20120108/5efd3a93/attachment.pgp>
Info about notmuch database
On Thu, 05 Jan 2012 16:04:22 +0100, Thomas Jost wrote: > There's a description of the DB "schema" in lib/database.cc in the > notmuch source code. But you may also consider just using libnotmuch > instead, if that's enough for what you want to do. > > Also: why Xapian? I'm already using something similar I wrote with > Python, storing everything in a dictionary, using Pickle to save that to > disk: 162 lines of code and 45 kb of data are enough to store my > addressbook and have completion in Emacs... Ohh, that sounds nice. Is that public somewhere? Sebastian -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 197 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20120108/0d4bfb23/attachment.pgp>
[PATCH 5/7] py3k: the basestring and unicode types are removed in python 3
Hi Tomi, Hi Sebastian :) Quoting Tomi Ollila (2012-01-04 19:07:11) >On Mon, 02 Jan 2012 16:15:58 +0100, Sebastian Spaeth >wrote: >> Happy new year. Pushed patches 1-4 of this series so far. Looking fine, nice, thanks. >> but ugh, the below seems like a rather ugly hack in a function that is >> probably called quite often. >> >> Isn't there a more pretty variant avoiding these sys.version_info checks >> all over the place? Well, I rebased and updated this patch. There are now two different implementations of _str like there are two Python3StringMixIn classes. I'll send this patch as reply to this message. >Does the Python3StringMixIn stuff in later patches already handle this >patch -- and making this obsolete ? No, that only handles the __str__ and __unicode__ stuff. Cheers, Justus
[PATCH] py3k: the basestring and unicode types are removed in python 3
--- bindings/python/notmuch/globals.py | 34 ++ 1 files changed, 22 insertions(+), 12 deletions(-) diff --git a/bindings/python/notmuch/globals.py b/bindings/python/notmuch/globals.py index 32ed9ae..4138460 100644 --- a/bindings/python/notmuch/globals.py +++ b/bindings/python/notmuch/globals.py @@ -31,12 +31,34 @@ if sys.version_info[0] == 2: class Python3StringMixIn(object): def __str__(self): return unicode(self).encode('utf-8') + + +def _str(value): +"""Ensure a nicely utf-8 encoded string to pass to libnotmuch + +C++ code expects strings to be well formatted and +unicode strings to have no null bytes.""" +if not isinstance(value, basestring): +raise TypeError("Expected str or unicode, got %s" % type(value)) +if isinstance(value, unicode): +return value.encode('UTF-8') +return value else: class Python3StringMixIn(object): def __str__(self): return self.__unicode__() +def _str(value): +"""Ensure a nicely utf-8 encoded string to pass to libnotmuch + +C++ code expects strings to be well formatted and +unicode strings to have no null bytes.""" +if not isinstance(value, str): +raise TypeError("Expected str, got %s" % type(value)) +return value.encode('UTF-8') + + class Enum(object): """Provides ENUMS as "code=Enum(['a','b','c'])" where code.a=0 etc...""" def __init__(self, names): @@ -202,18 +224,6 @@ class NotInitializedError(NotmuchError): status = STATUS.NOT_INITIALIZED -def _str(value): -"""Ensure a nicely utf-8 encoded string to pass to libnotmuch - -C++ code expects strings to be well formatted and -unicode strings to have no null bytes.""" -if not isinstance(value, basestring): -raise TypeError("Expected str or unicode, got %s" % str(type(value))) -if isinstance(value, unicode): -return value.encode('UTF-8') -return value - - class NotmuchDatabaseS(Structure): pass NotmuchDatabaseP = POINTER(NotmuchDatabaseS) -- 1.7.7.3
Info about notmuch database
On Sun, 08 Jan 2012 13:59:30 +0100, Sebastian Spaeth wrote: > On Thu, 05 Jan 2012 16:04:22 +0100, Thomas Jost > wrote: > > There's a description of the DB "schema" in lib/database.cc in the > > notmuch source code. But you may also consider just using libnotmuch > > instead, if that's enough for what you want to do. > > > > Also: why Xapian? I'm already using something similar I wrote with > > Python, storing everything in a dictionary, using Pickle to save that to > > disk: 162 lines of code and 45 kb of data are enough to store my > > addressbook and have completion in Emacs... > > Ohh, that sounds nice. Is that public somewhere? > > Sebastian https://github.com/Schnouki/dotfiles/blob/master/notmuch/addrbook.py Maybe I should add more comments in it :) Regards, -- Thomas/Schnouki -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 489 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20120108/4a45b952/attachment.pgp>
[PATCH 1/4] Add the option "--reply-to" to notmuch reply.
On Sun, 08 Jan 2012 14:47:33 +0200, Jani Nikula wrote: > > + /* We add the addresses if we are replying to all or we have not yet > > found > > +* a non-user address. We have to keep parsing to make sure we do find > > the > > +* correct from address for the user, but we pass a NULL message > > +*/ > > + if ((reply_to_all) || (g_mime_message_get_all_recipients (reply) == > > NULL)) > > Looking into this, it occurred to me g_mime_message_get_all_recipients() > allocates a new InternetAddressList when the return value is > non-NULL. Thus this leaks memory. OTOH allocating and deallocating for > this purpose seems suboptimal. I'll think this over. If we are happy with reply-to-sender stopping at the to: line (so if you reply-to-sender to an email which you sent and has no-one (apart from possibly you) on the to: line it would not give any recipients) then we only have two cases and we could do something like add_recipients_for_string for reply-to:/from: if return value is non-null then we were the sender so then add_recipients_for_string for to: and then stop regardless (well we want to carry on parsing headers to find the correct from: address to use but not adding any more recipients). It feels a bit hackish (it relies on the fact that if we found our address in the Reply-to:/From: line we didn't find anyone else's address). I think replying to an email which we sent and which does not have any other person on the to: line is sufficiently rare that it doesn't really matter what we do in this case. Best wishes Mark
[PATCH 1/4] Add the option "--reply-to" to notmuch reply.
On Sun, 08 Jan 2012 15:08:20 +, Mark Walters wrote: > I think replying to an email which we sent and which does not have any > other person on the to: line is sufficiently rare that it doesn't really > matter what we do in this case. I ended up fixing all of this properly. I'm hoping to send the patches later today so you can have a look - the code will do a better job of explaining itself than I'd do now. :) BR, Jani.
Python bindings for adoption
Hi Sebastian, hi everyone :) Quoting Sebastian Spaeth (2012-01-02 17:14:58) >Hi all, a happy new year! > >After a few weeks of notmuch abstinence I am being overwhelmed with 750 >new notmuch mails, and I really don't have the time or will (nor does my >family approve) to spend enormous amounts of time on notmuch. I am >already neglecting offlineimap, which also needs some attention. > >As I have repeatedly stated that I want to hand over the maintainership >of the notmuch python bindings, and I would like to do it asap. I feel >that people like Patrick Totzke, or Justus Winter who generally have >been working on this far more intensely than I recently did are both >very well positioned to take on that role :-). Most importantly, they >actually work with the bindings while I don't use them myself anymore. > >I will only merge bug fixes as of now, and not invest time to refactor >the code or add lots of bells and whistles. Let me know if anyone would >volunteer to take them on. I've decided to step up as a new maintainer for the libnotmuch python bindings. I assume that I'll have to mail an ssh public key to someone for repository access, right? Cheers, Justus
nmbug changes
Hey David, Quoting David Bremner (2011-12-23 22:56:31) >For those of you following/using the nmbug experiment, I made some >slightly disruptive changes, in order to support auto-updating the web >view on push. I'm having trouble with nmbug, I did follow the instructions in this mail and in the wiki, but nmbug never adds tags to my notmuch database (it is supposed to do that, right?). Consequently, nmbug status displays a long list of tags that aren't in my notmuch database. Executing nmbug merge does not help, and stracing nmbug revealed that it does only invoke notmuch with the search and dump actions. Any pointers? Thanks, Justus
[PATCH 4/4 v2] emacs: use pop-at-end functionality in archive/delete-message functions
This provides a smoother message processing flow by reducing the number of key presses needed for these common operations. --- Sorry, there were some errant extra parens at the end of these function definitions. emacs/notmuch-show.el |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 4c2b507..a706637 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -1454,7 +1454,7 @@ thread. " (interactive) (notmuch-show-remove-tag "inbox") -(notmuch-show-next-open-message))) +(notmuch-show-next-open-message t)) (defun notmuch-show-archive-thread () "Archive each message in thread, then show next thread from search. @@ -1485,7 +1485,7 @@ thread. " (interactive) (notmuch-show-add-tag "deleted") -(notmuch-show-next-open-message))) +(notmuch-show-next-open-message t)) (defun notmuch-show-delete-thread () "Delete each message in thread, then show next thread from search. -- 1.7.7.3
[PATCH 1/4 v2] emacs: add show-mode functions to archive/delete only current message
This adds two new function, notmuch-show-{archive,delete}-message, that archive/delete the current message, and then move to the next open one. --- Sorry, there were some errant extra parens at the end of these function definitions. emacs/notmuch-show.el | 24 1 files changed, 24 insertions(+), 0 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index e1d15f4..b2e7829 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -1436,6 +1436,18 @@ argument, hide all of the messages." (if show-next (notmuch-search-show-thread))) +(defun notmuch-show-archive-message () + "Archive the current message and advance. + +After the last message is reached, either the buffer will be +closed and the cursor will move to the search result if +available, or the cursor will move to the end of the current +thread. +" +(interactive) +(notmuch-show-remove-tag "inbox") +(notmuch-show-next-open-message)) + (defun notmuch-show-archive-thread () "Archive each message in thread, then show next thread from search. @@ -1455,6 +1467,18 @@ buffer." (interactive) (notmuch-show-tag-thread-internal "-" "inbox" nil)) +(defun notmuch-show-delete-message () + "Delete the current message and advance. + +After the last message is reached, either the buffer will be +closed and the cursor will move to the search result if +available, or the cursor will move to the end of the current +thread. +" +(interactive) +(notmuch-show-add-tag "deleted") +(notmuch-show-next-open-message)) + (defun notmuch-show-delete-thread () "Delete each message in thread, then show next thread from search. -- 1.7.7.3
[PATCH 4/4 v3] emacs: use pop-at-end functionality in archive/delete-message functions
This provides a smoother message processing flow by reducing the number of key presses needed for these common operations. --- Sorry sorry. I originally missed the problem in patch 1/4, so I had to modify this patch again to apply against the new version of the previous. So sorry for the noise, and thanks to amdragon for pointing all of this out. emacs/notmuch-show.el |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index b9ec584..a706637 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -1454,7 +1454,7 @@ thread. " (interactive) (notmuch-show-remove-tag "inbox") -(notmuch-show-next-open-message)) +(notmuch-show-next-open-message t)) (defun notmuch-show-archive-thread () "Archive each message in thread, then show next thread from search. @@ -1485,7 +1485,7 @@ thread. " (interactive) (notmuch-show-add-tag "deleted") -(notmuch-show-next-open-message)) +(notmuch-show-next-open-message t)) (defun notmuch-show-delete-thread () "Delete each message in thread, then show next thread from search. -- 1.7.7.3
[PATCH] man: add missing SEE ALSO header to notmuch reply man page
Signed-off-by: Jani Nikula --- man/man1/notmuch-reply.1 |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/man/man1/notmuch-reply.1 b/man/man1/notmuch-reply.1 index 099d808..db464d8 100644 --- a/man/man1/notmuch-reply.1 +++ b/man/man1/notmuch-reply.1 @@ -58,6 +58,9 @@ thread, replying to the entire thread allows for the reply to comment on issue found in multiple patches. .RE .RE + +.SH SEE ALSO + \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1), \fBnotmuch-dump\fR(5), \fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1), \fBnotmuch-part\fR(1), \fBnotmuch-restore\fR(1), -- 1.7.5.4
[PATCH v2 0/6] reply to sender
Hi all, here's v2 of the reply-to-sender series. Patches 1 & 2 are exactly the same as before. Changes since first version: - Patch 3: Settle on --reply-to=(all|sender) option for "notmuch reply". This was originally Carl Worth's suggestion, predates this patch set, and, as you'd expect, is in line with the rest of the CLI. Acked by David on IRC. - Patch 3: Handle replying to user's own messages gracefully. Credits to Mark Walters for his earlier work on this. - Patch 3: Update man page. - Patch 4: Change emacs implementation to keep old function names for old reply-to-all functionality, and add new reply-to-sender versions for new functionality, instead of vice versa. Suggested by Mark Walters. - Add patch 5 to change emacs keybindings, 'r' for reply-to-sender, 'R' for reply-to-all. I think everyone was in favour of this. - Add patch 6, written by Mark Winters, to test the cli. Comments are, as always, welcome. BR, Jani. Jani Nikula (5): cli: fix use of uninitialized variable in "notmuch reply" cli: convert "notmuch reply" to use the new argument parser cli: add support for replying just to the sender in "notmuch reply" emacs: add support for replying just to the sender emacs: bind 'r' to reply-to-sender and 'R' to reply-to-all Mark Walters (1): test: add tests for "notmuch reply" --reply-to=sender emacs/notmuch-mua.el |9 ++- emacs/notmuch-show.el| 12 ++- emacs/notmuch.el | 11 ++- man/man1/notmuch-reply.1 | 28 +- notmuch-reply.c | 155 ++ test/notmuch-test|1 + test/reply-to-sender | 209 ++ 7 files changed, 356 insertions(+), 69 deletions(-) create mode 100755 test/reply-to-sender -- 1.7.5.4
[PATCH v2 1/6] cli: fix use of uninitialized variable in "notmuch reply"
notmuch_show_params_t params is only initialized partially in notmuch_reply_command(). The only field that is used uninitialized is params.decrypt. It is usually non-zero, making "notmuch reply" on encrypted messages work by coincidence. Initialize params properly, and set params.decrypt as needed. Signed-off-by: Jani Nikula --- notmuch-reply.c | 10 +- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/notmuch-reply.c b/notmuch-reply.c index f8d5f64..1f33a86 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -621,11 +621,9 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) char *opt, *query_string; int i, ret = 0; int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params); -notmuch_show_params_t params; +notmuch_show_params_t params = { .part = -1 }; reply_format_func = notmuch_reply_format_default; -params.part = -1; -params.cryptoctx = NULL; argc--; argv++; /* skip subcommand argument */ @@ -647,10 +645,12 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) } else if ((STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) { if (params.cryptoctx == NULL) { GMimeSession* session = g_object_new(g_mime_session_get_type(), NULL); - if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg"))) + if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg"))) { fprintf (stderr, "Failed to construct gpg context.\n"); - else + } else { + params.decrypt = TRUE; g_mime_gpg_context_set_always_trust((GMimeGpgContext*)params.cryptoctx, FALSE); + } g_object_unref (session); session = NULL; } -- 1.7.5.4
[PATCH v2 2/6] cli: convert "notmuch reply" to use the new argument parser
Use the new notmuch argument parser to handle arguments in "notmuch reply". There should be no functional changes. Signed-off-by: Jani Nikula --- notmuch-reply.c | 75 +++ 1 files changed, 37 insertions(+), 38 deletions(-) diff --git a/notmuch-reply.c b/notmuch-reply.c index 1f33a86..000f6da 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -612,62 +612,61 @@ notmuch_reply_format_headers_only(void *ctx, return 0; } +enum { +FORMAT_DEFAULT, +FORMAT_HEADERS_ONLY, +}; + int notmuch_reply_command (void *ctx, int argc, char *argv[]) { notmuch_config_t *config; notmuch_database_t *notmuch; notmuch_query_t *query; -char *opt, *query_string; -int i, ret = 0; +char *query_string; +int opt_index, ret = 0; int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params); notmuch_show_params_t params = { .part = -1 }; +int format = FORMAT_DEFAULT; +notmuch_bool_t decrypt = FALSE; + +notmuch_opt_desc_t options[] = { + { NOTMUCH_OPT_KEYWORD, &format, "format", 'f', + (notmuch_keyword_t []){ { "default", FORMAT_DEFAULT }, + { "headers-only", FORMAT_HEADERS_ONLY }, + { 0, 0 } } }, + { NOTMUCH_OPT_BOOLEAN, &decrypt, "decrypt", 'd', 0 }, + { 0, 0, 0, 0, 0 } +}; -reply_format_func = notmuch_reply_format_default; - -argc--; argv++; /* skip subcommand argument */ +opt_index = parse_arguments (argc, argv, options, 1); +if (opt_index < 0) { + /* diagnostics already printed */ + return 1; +} -for (i = 0; i < argc && argv[i][0] == '-'; i++) { - if (strcmp (argv[i], "--") == 0) { - i++; - break; - } -if (STRNCMP_LITERAL (argv[i], "--format=") == 0) { - opt = argv[i] + sizeof ("--format=") - 1; - if (strcmp (opt, "default") == 0) { - reply_format_func = notmuch_reply_format_default; - } else if (strcmp (opt, "headers-only") == 0) { - reply_format_func = notmuch_reply_format_headers_only; - } else { - fprintf (stderr, "Invalid value for --format: %s\n", opt); - return 1; - } - } else if ((STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) { - if (params.cryptoctx == NULL) { - GMimeSession* session = g_object_new(g_mime_session_get_type(), NULL); - if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg"))) { - fprintf (stderr, "Failed to construct gpg context.\n"); - } else { - params.decrypt = TRUE; - g_mime_gpg_context_set_always_trust((GMimeGpgContext*)params.cryptoctx, FALSE); - } - g_object_unref (session); - session = NULL; - } +if (format == FORMAT_HEADERS_ONLY) + reply_format_func = notmuch_reply_format_headers_only; +else + reply_format_func = notmuch_reply_format_default; + +if (decrypt) { + GMimeSession* session = g_object_new (g_mime_session_get_type(), NULL); + params.cryptoctx = g_mime_gpg_context_new (session, "gpg"); + if (params.cryptoctx) { + g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) params.cryptoctx, FALSE); + params.decrypt = TRUE; } else { - fprintf (stderr, "Unrecognized option: %s\n", argv[i]); - return 1; + fprintf (stderr, "Failed to construct gpg context.\n"); } + g_object_unref (session); } -argc -= i; -argv += i; - config = notmuch_config_open (ctx, NULL, NULL); if (config == NULL) return 1; -query_string = query_string_from_args (ctx, argc, argv); +query_string = query_string_from_args (ctx, argc-opt_index, argv+opt_index); if (query_string == NULL) { fprintf (stderr, "Out of memory\n"); return 1; -- 1.7.5.4
[PATCH v2 3/6] cli: add support for replying just to the sender in "notmuch reply"
Add new option --reply-to=(all|sender) to "notmuch reply" to select whether to reply to all (sender and all recipients), or just sender. Reply to all remains the default. Credits to Mark Walters for his similar earlier work where I picked up the basic idea of handling reply-to-sender in add_recipients_from_message(). All bugs are mine, though. Signed-off-by: Jani Nikula --- Settled on --reply-to=(all|sender) per Carl's earlier suggestion (id:87pqn5cg4g.fsf at yoom.home.cworth.org) and David's approval on IRC. --- man/man1/notmuch-reply.1 | 28 +--- notmuch-reply.c | 78 -- 2 files changed, 84 insertions(+), 22 deletions(-) diff --git a/man/man1/notmuch-reply.1 b/man/man1/notmuch-reply.1 index 099d808..21afa35 100644 --- a/man/man1/notmuch-reply.1 +++ b/man/man1/notmuch-reply.1 @@ -14,11 +14,13 @@ Constructs a reply template for a set of messages. To make replying to email easier, .B notmuch reply takes an existing set of messages and constructs a suitable mail -template. The Reply-to header (if any, otherwise From:) is used for -the To: address. Vales from the To: and Cc: headers are copied, but -not including any of the current user's email addresses (as configured -in primary_mail or other_email in the .notmuch\-config file) in the -recipient list +template. The Reply-to: header (if any, otherwise From:) is used for +the To: address. Unless +.BR \-\-reply-to=sender +is specified, values from the To: and Cc: headers are copied, but not +including any of the current user's email addresses (as configured in +primary_mail or other_email in the .notmuch\-config file) in the +recipient list. It also builds a suitable new subject, including Re: at the front (if not already present), and adding the message IDs of the messages being @@ -45,6 +47,22 @@ Includes subject and quoted message body. Only produces In\-Reply\-To, References, To, Cc, and Bcc headers. .RE .RE +.RS +.TP 4 +.BR \-\-reply\-to= ( all | sender ) +.RS +.TP 4 +.BR all " (default)" +Replies to all addresses. +.TP 4 +.BR sender +Replies only to the sender. If Reply-to: header (if any, otherwise +From:) is any of the current user's configured email addresses +(replying to user's own message), try To:, Cc:, and Bcc: headers in +this order, and use the addresses in the first that contains something +other than only the user's addresses for the To: address. +.RE +.RE See \fBnotmuch-search-terms\fR(7) for details of the supported syntax for . diff --git a/notmuch-reply.c b/notmuch-reply.c index 000f6da..71946b3 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -170,7 +170,7 @@ address_is_users (const char *address, notmuch_config_t *config) /* For each address in 'list' that is not configured as one of the * user's addresses in 'config', add that address to 'message' as an - * address of 'type'. + * address of 'type', if 'add' is true. * * The first address encountered that *is* the user's address will be * returned, (otherwise NULL is returned). @@ -179,7 +179,8 @@ static const char * add_recipients_for_address_list (GMimeMessage *message, notmuch_config_t *config, GMimeRecipientType type, -InternetAddressList *list) +InternetAddressList *list, +notmuch_bool_t add) { InternetAddress *address; int i; @@ -197,7 +198,7 @@ add_recipients_for_address_list (GMimeMessage *message, continue; add_recipients_for_address_list (message, config, -type, group_list); +type, group_list, add); } else { InternetAddressMailbox *mailbox; const char *name; @@ -211,7 +212,7 @@ add_recipients_for_address_list (GMimeMessage *message, if (address_is_users (addr, config)) { if (ret == NULL) ret = addr; - } else { + } else if (add) { g_mime_message_add_recipient (message, type, name, addr); } } @@ -222,7 +223,7 @@ add_recipients_for_address_list (GMimeMessage *message, /* For each address in 'recipients' that is not configured as one of * the user's addresses in 'config', add that address to 'message' as - * an address of 'type'. + * an address of 'type', if 'add' is true. * * The first address encountered that *is* the user's address will be * returned, (otherwise NULL is returned). @@ -231,7 +232,8 @@ static const char * add_recipients_for_string (GMimeMessage *message, notmuch_config_t *config, GMimeRecipientType type, - const char *recipients) + const char *recipients, + notmuch_bool_t add) { InternetAddressList
[PATCH v2 4/6] emacs: add support for replying just to the sender
Provide reply to sender counterparts to the search and show reply functions. Add key binding 'R' to reply to sender, while keeping 'r' as reply to all, both in search and show views. Signed-off-by: Jani Nikula --- emacs/notmuch-mua.el |9 ++--- emacs/notmuch-show.el | 10 -- emacs/notmuch.el |9 - 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index 7114e48..5b15255 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -71,12 +71,15 @@ list." (push header message-hidden-headers))) notmuch-mua-hidden-headers)) -(defun notmuch-mua-reply (query-string &optional sender) +(defun notmuch-mua-reply (query-string &optional sender reply-all) (let (headers body (args '("reply"))) (if notmuch-show-process-crypto (setq args (append args '("--decrypt" +(if reply-all + (setq args (append args '("--reply-to=all"))) + (setq args (append args '("--reply-to=sender" (setq args (append args (list query-string))) ;; This make assumptions about the output of `notmuch reply', but ;; really only that the headers come first followed by a blank @@ -217,13 +220,13 @@ the From: address first." (notmuch-mua-forward-message)) (notmuch-mua-forward-message))) -(defun notmuch-mua-new-reply (query-string &optional prompt-for-sender) +(defun notmuch-mua-new-reply (query-string &optional prompt-for-sender reply-all) "Invoke the notmuch reply window." (interactive "P") (let ((sender (when prompt-for-sender (notmuch-mua-prompt-for-sender -(notmuch-mua-reply query-string sender))) +(notmuch-mua-reply query-string sender reply-all))) (defun notmuch-mua-send-and-exit (&optional arg) (interactive "P") diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 5502efd..96eea19 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -933,6 +933,7 @@ thread id. If a prefix is given, crypto processing is toggled." (define-key map "m" 'notmuch-mua-new-mail) (define-key map "f" 'notmuch-show-forward-message) (define-key map "r" 'notmuch-show-reply) + (define-key map "R" 'notmuch-show-reply-sender) (define-key map "|" 'notmuch-show-pipe-message) (define-key map "w" 'notmuch-show-save-attachments) (define-key map "V" 'notmuch-show-view-raw-message) @@ -1237,9 +1238,14 @@ any effects from previous calls to (notmuch-show-previous-message) (defun notmuch-show-reply (&optional prompt-for-sender) - "Reply to the current message." + "Reply to the sender and all recipients of the current message." (interactive "P") - (notmuch-mua-new-reply (notmuch-show-get-message-id) prompt-for-sender)) + (notmuch-mua-new-reply (notmuch-show-get-message-id) prompt-for-sender t)) + +(defun notmuch-show-reply-sender (&optional prompt-for-sender) + "Reply to the sender of the current message." + (interactive "P") + (notmuch-mua-new-reply (notmuch-show-get-message-id) prompt-for-sender nil)) (defun notmuch-show-forward-message (&optional prompt-for-sender) "Forward the current message." diff --git a/emacs/notmuch.el b/emacs/notmuch.el index fde2377..5974d6b 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -207,6 +207,7 @@ For a mouse binding, return nil." (define-key map "p" 'notmuch-search-previous-thread) (define-key map "n" 'notmuch-search-next-thread) (define-key map "r" 'notmuch-search-reply-to-thread) +(define-key map "R" 'notmuch-search-reply-to-thread-sender) (define-key map "m" 'notmuch-mua-new-mail) (define-key map "s" 'notmuch-search) (define-key map "o" 'notmuch-search-toggle-order) @@ -441,10 +442,16 @@ Complete list of currently available key bindings: (error "End of search results" (defun notmuch-search-reply-to-thread (&optional prompt-for-sender) + "Begin composing a reply-all to the entire current thread in a new buffer." + (interactive "P") + (let ((message-id (notmuch-search-find-thread-id))) +(notmuch-mua-new-reply message-id prompt-for-sender t))) + +(defun notmuch-search-reply-to-thread-sender (&optional prompt-for-sender) "Begin composing a reply to the entire current thread in a new buffer." (interactive "P") (let ((message-id (notmuch-search-find-thread-id))) -(notmuch-mua-new-reply message-id prompt-for-sender))) +(notmuch-mua-new-reply message-id prompt-for-sender nil))) (defun notmuch-call-notmuch-process (&rest args) "Synchronously invoke \"notmuch\" with the given list of arguments. -- 1.7.5.4
[PATCH v2 5/6] emacs: bind 'r' to reply-to-sender and 'R' to reply-to-all
Change the default reply key bindings, making 'r' reply-to-sender and 'R' reply-to-all. Signed-off-by: Jani Nikula --- It seemed to me that most people wanted this, and nobody spoke for keeping the old binding now that we have reply-to-sender. This as a separate patch so it's easy to drop if needed. --- emacs/notmuch-show.el |4 ++-- emacs/notmuch.el |4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 96eea19..8f8ea93 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -932,8 +932,8 @@ thread id. If a prefix is given, crypto processing is toggled." (define-key map "s" 'notmuch-search) (define-key map "m" 'notmuch-mua-new-mail) (define-key map "f" 'notmuch-show-forward-message) - (define-key map "r" 'notmuch-show-reply) - (define-key map "R" 'notmuch-show-reply-sender) + (define-key map "r" 'notmuch-show-reply-sender) + (define-key map "R" 'notmuch-show-reply) (define-key map "|" 'notmuch-show-pipe-message) (define-key map "w" 'notmuch-show-save-attachments) (define-key map "V" 'notmuch-show-view-raw-message) diff --git a/emacs/notmuch.el b/emacs/notmuch.el index 5974d6b..e158138 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -206,8 +206,8 @@ For a mouse binding, return nil." (define-key map ">" 'notmuch-search-last-thread) (define-key map "p" 'notmuch-search-previous-thread) (define-key map "n" 'notmuch-search-next-thread) -(define-key map "r" 'notmuch-search-reply-to-thread) -(define-key map "R" 'notmuch-search-reply-to-thread-sender) +(define-key map "r" 'notmuch-search-reply-to-thread-sender) +(define-key map "R" 'notmuch-search-reply-to-thread) (define-key map "m" 'notmuch-mua-new-mail) (define-key map "s" 'notmuch-search) (define-key map "o" 'notmuch-search-toggle-order) -- 1.7.5.4
[PATCH v2 6/6] test: add tests for "notmuch reply" --reply-to=sender
From: Mark Walters --- This is Mark's work; just a one line change by Jani to take into account a minor change in replying to one's own message. --- test/notmuch-test|1 + test/reply-to-sender | 209 ++ 2 files changed, 210 insertions(+), 0 deletions(-) create mode 100755 test/reply-to-sender diff --git a/test/notmuch-test b/test/notmuch-test index e40ef86..6a99ae3 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -33,6 +33,7 @@ TESTS=" thread-naming raw reply + reply-to-sender dump-restore uuencode thread-order diff --git a/test/reply-to-sender b/test/reply-to-sender new file mode 100755 index 000..caceeb2 --- /dev/null +++ b/test/reply-to-sender @@ -0,0 +1,209 @@ +#!/usr/bin/env bash +test_description="\"notmuch reply --reply-to=sender\" in several variations" +. ./test-lib.sh + +test_begin_subtest "Basic reply-to-sender" +add_message '[from]="Sender "' \ + [to]=test_suite at notmuchmail.org \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="basic reply-to-sender test"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -, Sender wrote: +> basic reply-to-sender test" + +test_begin_subtest "From Us, Basic reply to message" +add_message '[from]="Notmuch Test Suite "' \ +'[to]="Recipient "' \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="basic reply-to-from-us test"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Recipient +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -, Notmuch Test Suite wrote: +> basic reply-to-from-us test" + +test_begin_subtest "Multiple recipients" +add_message '[from]="Sender "' \ +'[to]="test_suite at notmuchmail.org, Someone Else "' \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="Multiple recipients"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -, Sender wrote: +> Multiple recipients" + +test_begin_subtest "From Us, Multiple TO recipients" +add_message '[from]="Notmuch Test Suite "' \ +'[to]="Recipient , Someone Else "' \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="From Us, Multiple TO recipients"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Recipient , Someone Else +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -, Notmuch Test Suite wrote: +> From Us, Multiple TO recipients" + +test_begin_subtest "Reply with CC" +add_message '[from]="Sender "' \ + [to]=test_suite at notmuchmail.org \ +'[cc]="Other Parties "' \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="reply with CC"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -, Sender wrote: +> reply with CC" + +test_begin_subtest "From Us, Reply with CC" +add_message '[from]="Notmuch Test Suite "' \ +'[to]="Recipient "' \ +'[cc]="Other Parties "' \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="reply with CC"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Recipient +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -, Notmuch Test Suite wrote: +> reply with CC" + +test_begin_subtest "From Us, Reply no TO but with CC" +add_message '[from]="Notmuch Test Suite "' \ +'[cc]="Other Parties "' \ + [subject]=notmuch-reply-test \ +'[date]="Tue, 05 Jan 2010 15:43:56 -"' \ +'[body]="reply with CC"' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test
[PATCH v2 5/6] emacs: bind 'r' to reply-to-sender and 'R' to reply-to-all
On Sun, Jan 8, 2012 at 14:48, Jani Nikula wrote: > It seemed to me that most people wanted this, and nobody spoke for keeping > the old binding now that we have reply-to-sender. This as a separate patch > so it's easy to drop if needed. FWIW, I generally prefer reply-all as the default. In my experience, when a message is sent to a bunch of people, it's usually treated as a "forum" discussion where everybody wants to be in on everything. Also, once you've started composing, it's much easier to delete people you don't want included than to add people who are no longer referenced in the new buffer at all.
nmbug changes
On Sun, 08 Jan 2012 16:24:06 -, Justus Winter <4winter at informatik.uni-hamburg.de> wrote: > I'm having trouble with nmbug, I did follow the instructions in this > mail and in the wiki, but nmbug never adds tags to my notmuch database > (it is supposed to do that, right?). In case you just want to load the tags in the git repo into your notmuch database, try running "nmbug checkout". It might be the instructions on "getting started" could be updated here? Perhaps someone who has gotten started more recently can chime in here. David
Python bindings for adoption
On Sun, 08 Jan 2012 16:16:06 -, Justus Winter <4winter at informatik.uni-hamburg.de> wrote: > > I've decided to step up as a new maintainer for the libnotmuch python > bindings. I assume that I'll have to mail an ssh public key to someone > for repository access, right? > That's right. Carl (in copy) handles repository access. d
[PATCH v2 3/6] cli: add support for replying just to the sender in "notmuch reply"
I like this version (of the whole series) but have two queries. (Note I haven't actually tried it out yet: I have just been reading the code.) > + /* Force recipient type in reply-to-sender mode just in case replying to > + * user's own message finds recipients in Cc/Bcc fields only. > + */ > + if (reply_all) > + recipient_type = reply_to_map[i].recipient_type; > + else > + recipient_type = GMIME_RECIPIENT_TYPE_TO; > + > + addr = add_recipients_for_string (reply, config, recipient_type, > + recipients, add_recipients); > + Why force the recipient type? I do not think notmuch should ever move bcc people onto a different header. I think that will bite someone when it leaks information. I would be happy with either empty headers or with the people staying as bcc. In the cc: case I have no preference (as those addresses are already public) but I would suggest being consistent with bcc so either empty headers or keep them in the cc line. > for (messages = notmuch_query_search_messages (query); > notmuch_messages_valid (messages); > notmuch_messages_move_to_next (messages)) > { [...] > (void)add_recipients_from_message (reply, config, message, reply_all); Since the above logic is applied to each email individually I think working out the recipients when replying to multiple emails (e.g., reply-to-sender on a thread) could be very confusing. Some of the people being replied to will have been senders, some recipients (it is very likely that the thread contains messages we sent), some could even be cc, bcc people. Personally, I would have no idea what to expect from reply-to-sender in this case. (My personal choice would be not to allow notmuch-reply-to-sender if multiple messages are specified. But I can obtain that by unbinding "r" in the notmuch-search-mode-map keymap.) Best wishes Mark
[PATCH v2 5/6] emacs: bind 'r' to reply-to-sender and 'R' to reply-to-all
On Sun, 8 Jan 2012 15:01:30 -0700, Jeremy Nickurak wrote: > FWIW, I generally prefer reply-all as the default. In my experience, > when a message is sent to a bunch of people, it's usually treated as a > "forum" discussion where everybody wants to be in on everything. Also, > once you've started composing, it's much easier to delete people you > don't want included than to add people who are no longer referenced in > the new buffer at all. That's a good point. I think that maybe people are wanting to protect against the accidental reply to all when you only mean to reply to the sender. jamie. -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 835 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20120108/5e326084/attachment.pgp>
[PATCH v2 5/6] emacs: bind 'r' to reply-to-sender and 'R' to reply-to-all
On Sun, Jan 8, 2012 at 16:32, Jameson Graef Rollins wrote: > That's a good point. ?I think that maybe people are wanting to protect > against the accidental reply to all when you only mean to reply to the > sender. Certainly a worthy cause. All I'm saying is I make the mistake in the other direction more frequently ;)
[PATCH] emacs: call "notmuch tag" only once when archiving a thread
On Thu, 05 Jan 2012 22:32:16 +0200, Jani Nikula wrote: [...] > In the show view it only modifies the messages that are currently > visible. This is to make sure you don't accidentally archive things that > have arrived after refreshing the buffer. I think this is safest. Hmm. Perhaps it would make sense to add a check in the search view that the thread being archived[1] has the same number of messages as it did when the buffer was constructed. (The information on how many messages the thread has is in the buffer; we would then compare this to the result of ?notmuch count thread:000foo? when the user requests to archive.) If the counts don?t match, the interface should show a message in the echo area and (probably) refuse to do the tagging. We could also optionally use this strategy in the search view too. The error message is simple there: ?New messages have arrived; refresh thread view before archiving.? (It doesn?t make as much sense to tell people to refresh a search view ? it could be an expensive operation and/or may not be idempotent if some thread?s tags have been changed. So it?s harder to say what the advice should be in that case.) If other people think it would be useful, I can work on a patch to implement this approach. Footnotes: [1] Or having its tags changed generally. -- Aaron Ecay
[PATCH 2/4] emacs: repurpose notmuch-show-archive-thread-internal function for general thread tagging
Jameson, Some comments below: On Sat, 7 Jan 2012 14:28:12 -0800, Jameson Graef Rollins wrote: > Instead of having a function that is only used for archiving a thread, > we instead make it useful for any tagging operation. The new > function, notmuch-show-tag-thread-internal, now takes two more > arguments, for the "sign" of the tagging operation ("-" or "+"), and > the tag to be added or removed. This will allow this function to be > used for any generic thread tagging operation. > > The higher level functions that call this function are modified > accordingly. > --- > emacs/notmuch-show.el | 34 -- > 1 files changed, 20 insertions(+), 14 deletions(-) > > diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el > index 5502efd..1e16f05 100644 > --- a/emacs/notmuch-show.el > +++ b/emacs/notmuch-show.el > @@ -1414,20 +1414,26 @@ argument, hide all of the messages." >(interactive) >(backward-button 1)) > > -(defun notmuch-show-archive-thread-internal (show-next) > +(defun notmuch-show-tag-thread-internal (sign tag show-next) A couple of comments on the arguments: - It would be good to make show-next &optional. This will enable code to call the fn with only two arguments, and not showing next will be the default behavior. - A more lispy way of specifying the sign would be to use a boolean. Perhaps you could call this ?remove?; a value of ?t? would remove the tag; ?nil? would add it. Moving this argument after ?tag? and also making it &optional woudl allow this fn to be called with one arg to add a tag. (Maybe this is too minimalist and API, however.) >;; Remove the tag from the current set of messages. >(goto-char (point-min)) > - (loop do (notmuch-show-remove-tag "inbox") > - until (not (notmuch-show-goto-message-next))) > - ;; Move to the next item in the search results, if any. > - (let ((parent-buffer notmuch-show-parent-buffer)) > -(notmuch-kill-this-buffer) > -(if parent-buffer > - (progn > - (switch-to-buffer parent-buffer) > - (forward-line) > - (if show-next > - (notmuch-search-show-thread)) > + (let ((tag-function)) No second set of parens is needed around tag-function. > +(cond > + ((string= sign "-") > + (setq tag-function 'notmuch-show-remove-tag)) > + ((string= sign "+") > + (setq tag-function 'notmuch-show-add-tag))) > +(loop do (funcall tag-function tag) > + until (not (notmuch-show-goto-message-next))) > +;; Move to the next item in the search results, if any. Does it make sense to separate the tagging and the movement? It seems plausible that some code somewhere might want to add/remove a tag from all messages in the thread w/o changing the display. > +(let ((parent-buffer notmuch-show-parent-buffer)) > + (notmuch-kill-this-buffer) > + (if parent-buffer > + (progn > + (switch-to-buffer parent-buffer) > + (forward-line) > + (if show-next > + (notmuch-search-show-thread))) -- Aaron Ecay
[PATCH 2/4] emacs: add option to notmuch-show-next-open-message to pop out to parent buffer if at end
Jameson, One small, stylistic/nitpicky comment :) On Sat, 7 Jan 2012 17:26:53 -0800, Jameson Graef Rollins wrote: > This will allow for keybindings that achieve a smoother message > processing flow by reducing the number of key presses needed for most > common operations. > --- > emacs/notmuch-show.el | 12 +--- > 1 files changed, 9 insertions(+), 3 deletions(-) > > diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el > index 8bb052e..e7bb958 100644 > --- a/emacs/notmuch-show.el > +++ b/emacs/notmuch-show.el > @@ -1264,17 +1264,23 @@ any effects from previous calls to >(notmuch-show-mark-read) >(notmuch-show-message-adjust)) > > -(defun notmuch-show-next-open-message () > +(defun notmuch-show-next-open-message (&optional pop-at-end) >"Show the next message." >(interactive) > - (let (r) > + (let ((r) > + (parent-buffer notmuch-show-parent-buffer)) No second set of parentheses is needed around r. Also, it is more idiomatic to put the initialized variable (i.e. parent-buffer) before the uninitialized one (r). > (while (and (setq r (notmuch-show-goto-message-next)) > (not (notmuch-show-message-visible-p > (if r > (progn > (notmuch-show-mark-read) > (notmuch-show-message-adjust)) > - (goto-char (point-max) > + (if (and parent-buffer pop-at-end) > + (progn > + (kill-this-buffer) > + (switch-to-buffer parent-buffer) > + (forward-line 1)) > + (goto-char (point-max)) > > (defun notmuch-show-previous-open-message () >"Show the previous message." > -- > 1.7.7.3 > > ___ > notmuch mailing list > notmuch at notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch -- Aaron Ecay
[PATCH] emacs: call "notmuch tag" only once when archiving a thread
Quoth Aaron Ecay on Jan 08 at 7:56 pm: > On Thu, 05 Jan 2012 22:32:16 +0200, Jani Nikula wrote: > > [...] > > > In the show view it only modifies the messages that are currently > > visible. This is to make sure you don't accidentally archive things that > > have arrived after refreshing the buffer. I think this is safest. > > Hmm. Perhaps it would make sense to add a check in the search view that > the thread being archived[1] has the same number of messages as it did > when the buffer was constructed. (The information on how many messages > the thread has is in the buffer; we would then compare this to the result > of ?notmuch count thread:000foo? when the user requests to archive.) If > the counts don?t match, the interface should show a message in the echo > area and (probably) refuse to do the tagging. That sounds like a clever workaround. There's been quite a bit of discussion on fixing this properly. See, for example id:"CAH-f9WsPj=1Eu=g3sOePJgCTBFs6HrLdLq18xMEnJ8aZ00yCEg at mail.gmail.com". The gist is that we need to include message IDs (or document IDs) in the search output and use these in tagging operations, rather than the unstable thread:XXX queries. Unfortunately, actually fixing this got stalled since adding this information the text format is a fool's errand (having been the fool, I can say this!), so we need to switch Emacs over to using the JSON search format first. However, once that's done, it's a relatively simple change.
[PATCH 1/4] emacs: new customization variable to exclude "deleted" messages from search
Jameson, One comment On Sat, 7 Jan 2012 14:28:11 -0800, Jameson Graef Rollins wrote: > The new customization variable, notmuch-search-exclude-deleted, when > set to t, will exclude any messages with the "deleted" tag from > searches. > > Additionally, specifying "tag:deleted" in the search directly will > override the exclusion and will included deleted messages in the > search results. > --- > emacs/notmuch.el |8 > test/emacs | 42 > > .../notmuch-search-tag-inbox-deleted-excluded | 24 +++ > 3 files changed, 74 insertions(+), 0 deletions(-) > create mode 100644 > test/emacs.expected-output/notmuch-search-tag-inbox-deleted-excluded > > diff --git a/emacs/notmuch.el b/emacs/notmuch.el > index fde2377..c519687 100644 > --- a/emacs/notmuch.el > +++ b/emacs/notmuch.el > @@ -905,6 +905,11 @@ PROMPT is the string to prompt with." >(read-from-minibuffer prompt nil keymap nil > 'notmuch-query-history nil nil > > +(defcustom notmuch-search-exclude-deleted nil > + "Exclude deleted messages (with \"deleted\" tag) from search results." > + :group 'notmuch > + :type 'boolean) > + > ;;;###autoload > (defun notmuch-search (query &optional oldest-first target-thread > target-line continuation) >"Run \"notmuch search\" with the given query string and display results. > @@ -927,6 +932,9 @@ The optional parameters are used as follows: > (set 'notmuch-search-target-thread target-thread) > (set 'notmuch-search-target-line target-line) > (set 'notmuch-search-continuation continuation) > +(when (and notmuch-search-exclude-deleted > +(not (string-match "tag:deleted[ )]*" query))) ?is:? is a synonym for ?tag:? in searches ? so this section of the code should look for it too. -- Aaron Ecay
[PATCH 4/4] emacs: Use the new JSON reply format.
Adam, One comment below. On Sun, 8 Jan 2012 00:52:42 -0700, Adam Wolfe Gordon wrote: > From: Adam Wolfe Gordon > > Using the new JSON reply format allows emacs to quote HTML parts > nicely by first parsing them with w3m, then quoting them. This is > very useful for users who regularly receive HTML-only email. > > The behavior for messages that contain plain text parts should be > unchanged, except that an additional quoted line is added to the end > of the reply message. The test has been updated to reflect this. > --- > emacs/notmuch-mua.el | 62 +++-- > test/emacs |1 + > 2 files changed, 50 insertions(+), 13 deletions(-) > > diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el > index 7114e48..7f894cb 100644 > --- a/emacs/notmuch-mua.el > +++ b/emacs/notmuch-mua.el > @@ -19,6 +19,7 @@ > ;; > ;; Authors: David Edmondson > > +(require 'json) > (require 'message) > > (require 'notmuch-lib) > @@ -71,27 +72,62 @@ list." > (push header message-hidden-headers))) > notmuch-mua-hidden-headers)) > > +(defun w3m-region (start end)) ;; From `w3m.el'. What is the purpose of the above line? If it is to make the compiler aware of the function, you should use ?declare-function? instead. Defun will erase the original definition of the w3m-region function. -- Aaron Ecay
[PATCH 0/4] Quoting HTML-only emails in replies redux
On Sun, 8 Jan 2012 00:52:38 -0700, Adam Wolfe Gordon wrote: [...] > > There should probably be some customize variables for this in emacs, to > control > (for example) whether to quote HTML parts and whether to prefer HTML or > plaintext parts for quoting. Any suggestions for what should be customizable > would be appreciated. I think two variables should suffice: one (boolean) to control whether to quote standalone text/html parts, and one to control which parts of a multipart/alternative part to quote. The latter should take possible values 'text, 'html, and 'both. This requires the emacs reply functionality to distinguish between html parts that are part of a multipart/alternative and those which are not, which (AFAICT) the current code doesn?t do. I haven?t tested the patch yet, but it looks very promising. Thanks! -- Aaron Ecay
[PATCH 1/4] emacs: new customization variable to exclude "deleted" messages from search
> > @@ -927,6 +932,9 @@ The optional parameters are used as follows: > > (set 'notmuch-search-target-thread target-thread) > > (set 'notmuch-search-target-line target-line) > > (set 'notmuch-search-continuation continuation) > > +(when (and notmuch-search-exclude-deleted > > + (not (string-match "tag:deleted[ )]*" query))) > > ?is:? is a synonym for ?tag:? in searches ? so this section of the code > should look for it too. There are several other things that could also trip up this regexp. xtag:deletedx would be falsely matched, as would a quoted phrase containing "tag:deleted", while tag:"deleted" and tag:(deleted) would incorrectly not be matched. Getting this right is hard, though I'd be happy with "\\<\\(tag\\|is\\):deleted\\>" or maybe "\\<\\(tag\\|is\\):\\(\"?\\)deleted\\>\\2" Implicit exclusions like this were actually one of my target features for the custom query parser, but I think hacking around that by inspecting the query string is a fine interim solution. (One of these months I'll dust off the query parser, really!)
[PATCH 1/4] emacs: new customization variable to exclude "deleted" messages from search
On Sun, 8 Jan 2012 20:49:38 -0500, Austin Clements wrote: > > > @@ -927,6 +932,9 @@ The optional parameters are used as follows: > > > (set 'notmuch-search-target-thread target-thread) > > > (set 'notmuch-search-target-line target-line) > > > (set 'notmuch-search-continuation continuation) > > > +(when (and notmuch-search-exclude-deleted > > > +(not (string-match "tag:deleted[ )]*" query))) > > > > ?is:? is a synonym for ?tag:? in searches ? so this section of the code > > should look for it too. > > There are several other things that could also trip up this regexp. > xtag:deletedx would be falsely matched, as would a quoted phrase > containing "tag:deleted", while tag:"deleted" and tag:(deleted) would > incorrectly not be matched. Thanks so much for the review, guys. I should have mentioned in this patch that the my regex skills are very weak, and that it was surely incomplete. I always forget about the is: prefix as well. > Getting this right is hard, though I'd be happy with > > "\\<\\(tag\\|is\\):deleted\\>" Every time I think I start to understand regex I am reminded that it's black magic and I really know nothing. For instance, I am not familiar with "<" or ">", although they appear to be a "word" boundaries (although I'm not sure how "word" is defined). Also, why is all the \\ (double?) escaping needed? I'll certainly take your word for it, though. > or maybe > > "\\<\\(tag\\|is\\):\\(\"?\\)deleted\\>\\2" After staring at this for 10 minutes I think I'm getting the extra bits here. It matches an initial \", and then a second at the end if the first matched. That's clever. Why \\>\\2 instead of \\2\\> ? I'm definitely confused by why so much apparent escaping is needed, though. > Implicit exclusions like this were actually one of my target features > for the custom query parser, but I think hacking around that by > inspecting the query string is a fine interim solution. (One of these > months I'll dust off the query parser, really!) Very much looking forward to it! jamie. -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 835 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20120108/3afe3c7f/attachment-0001.pgp>
[PATCH 1/4] emacs: new customization variable to exclude "deleted" messages from search
Quoth Jameson Graef Rollins on Jan 08 at 6:34 pm: > On Sun, 8 Jan 2012 20:49:38 -0500, Austin Clements > wrote: > > > > @@ -927,6 +932,9 @@ The optional parameters are used as follows: > > > > (set 'notmuch-search-target-thread target-thread) > > > > (set 'notmuch-search-target-line target-line) > > > > (set 'notmuch-search-continuation continuation) > > > > +(when (and notmuch-search-exclude-deleted > > > > + (not (string-match "tag:deleted[ )]*" query))) > > > > > > ?is:? is a synonym for ?tag:? in searches ? so this section of the code > > > should look for it too. > > > > There are several other things that could also trip up this regexp. > > xtag:deletedx would be falsely matched, as would a quoted phrase > > containing "tag:deleted", while tag:"deleted" and tag:(deleted) would > > incorrectly not be matched. > > Thanks so much for the review, guys. I should have mentioned in this > patch that the my regex skills are very weak, and that it was surely > incomplete. I always forget about the is: prefix as well. > > > Getting this right is hard, though I'd be happy with > > > > "\\<\\(tag\\|is\\):deleted\\>" > > Every time I think I start to understand regex I am reminded that it's > black magic and I really know nothing. For instance, I am not familiar > with "<" or ">", although they appear to be a "word" boundaries > (although I'm not sure how "word" is defined). Also, why is all the \\ > (double?) escaping needed? I'll certainly take your word for it, > though. I'm not positive, but I think \> matches on the transition from a "word-constituent" character to a non-word-constituent character, as defined by Emacs' active syntax table. The slashes are all doubled because I was writing it as an Emacs string for easy pasting (sorry, I should have been explicit about that). The regexp itself is \<\(tag\|is\):deleted\> > > or maybe > > > > "\\<\\(tag\\|is\\):\\(\"?\\)deleted\\>\\2" > > After staring at this for 10 minutes I think I'm getting the extra bits > here. It matches an initial \", and then a second at the end if the > first matched. That's clever. Why Exactly. > \\>\\2 > > instead of > > \\2\\> > > ? Okay, that can qualify as black magic. The problem is that a " will mess up the word-boundary matching because " isn't a word constituent character. So, if it is looking for a quote at the end, the \2 in \2\> would match and consume the ", but then the \> wouldn't match.