[PATCH v2 3/3] reply: Move reply citation printing to the recursive MIME walk

2012-03-27 Thread Austin Clements
This makes more logical sense, since it makes the recursive printer
responsible for the entire reply body and lets it start at the root of
the MIME tree instead of the first child.  (We could move reply header
creation in there, too, but if we ever support proper reply to
multiple messages, we'll want just one set of reply headers computed
from the entire message set and many bodies.)
---
 notmuch-reply.c |   12 ++--
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index 84a1220..0949d9f 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -47,7 +47,11 @@ format_part_reply (mime_node_t *node)
 {
 int i;

-if (GMIME_IS_MESSAGE (node->part)) {
+if (node->envelope_file) {
+   printf ("On %s, %s wrote:\n",
+   notmuch_message_get_header (node->envelope_file, "date"),
+   notmuch_message_get_header (node->envelope_file, "from"));
+} else if (GMIME_IS_MESSAGE (node->part)) {
GMimeMessage *message = GMIME_MESSAGE (node->part);
InternetAddressList *recipients;
const char *recipients_string;
@@ -540,13 +544,9 @@ notmuch_reply_format_default(void *ctx,
g_object_unref (G_OBJECT (reply));
reply = NULL;

-   printf ("On %s, %s wrote:\n",
-   notmuch_message_get_header (message, "date"),
-   notmuch_message_get_header (message, "from"));
-
if (mime_node_open (ctx, message, params->cryptoctx, params->decrypt,
) == NOTMUCH_STATUS_SUCCESS) {
-   format_part_reply (mime_node_child (root, 0));
+   format_part_reply (root);
talloc_free (root);
}

-- 
1.7.9.1



[PATCH v2 2/3] reply: Convert default reply format to self-recursive style

2012-03-27 Thread Austin Clements
This re-arranges the default reply formatter code to use the
mime_node_t abstraction.  There are no semantic changes.
---
 notmuch-reply.c |  123 +--
 1 files changed, 47 insertions(+), 76 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index 2f5ed3d..84a1220 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -24,28 +24,6 @@
 #include "gmime-filter-headers.h"

 static void
-reply_headers_message_part (GMimeMessage *message);
-
-static void
-reply_part_content (GMimeObject *part);
-
-static const notmuch_show_format_t format_reply = {
-"", NULL,
-   "", NULL,
-   "", NULL, reply_headers_message_part, ">\n",
-   "",
-   NULL,
-   NULL,
-   NULL,
-   reply_part_content,
-   NULL,
-   "",
-   "",
-   "", "",
-""
-};
-
-static void
 show_reply_headers (GMimeMessage *message)
 {
 GMimeStream *stream_stdout = NULL, *stream_filter = NULL;
@@ -65,66 +43,55 @@ show_reply_headers (GMimeMessage *message)
 }

 static void
-reply_headers_message_part (GMimeMessage *message)
+format_part_reply (mime_node_t *node)
 {
-InternetAddressList *recipients;
-const char *recipients_string;
-
-printf ("> From: %s\n", g_mime_message_get_sender (message));
-recipients = g_mime_message_get_recipients (message, 
GMIME_RECIPIENT_TYPE_TO);
-recipients_string = internet_address_list_to_string (recipients, 0);
-if (recipients_string)
-   printf ("> To: %s\n",
-   recipients_string);
-recipients = g_mime_message_get_recipients (message, 
GMIME_RECIPIENT_TYPE_CC);
-recipients_string = internet_address_list_to_string (recipients, 0);
-if (recipients_string)
-   printf ("> Cc: %s\n",
-   recipients_string);
-printf ("> Subject: %s\n", g_mime_message_get_subject (message));
-printf ("> Date: %s\n", g_mime_message_get_date_as_string (message));
-}
-
-
-static void
-reply_part_content (GMimeObject *part)
-{
-GMimeContentType *content_type = g_mime_object_get_content_type 
(GMIME_OBJECT (part));
-GMimeContentDisposition *disposition = 
g_mime_object_get_content_disposition (part);
+int i;

-if (g_mime_content_type_is_type (content_type, "multipart", "*") ||
-   g_mime_content_type_is_type (content_type, "message", "rfc822"))
-{
-   /* Output nothing, since multipart subparts will be handled 
individually. */
-}
-else if (g_mime_content_type_is_type (content_type, "application", 
"pgp-encrypted") ||
-g_mime_content_type_is_type (content_type, "application", 
"pgp-signature"))
-{
-   /* Ignore PGP/MIME cruft parts */
-}
-else if (g_mime_content_type_is_type (content_type, "text", "*") &&
-   !g_mime_content_type_is_type (content_type, "text", "html"))
-{
-   GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
-   g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
-   show_text_part_content (part, stream_stdout, 
NOTMUCH_SHOW_TEXT_PART_REPLY);
-   g_object_unref(stream_stdout);
-}
-else
-{
-   if (disposition &&
-   strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 
0)
-   {
-   const char *filename = g_mime_part_get_filename (GMIME_PART (part));
+if (GMIME_IS_MESSAGE (node->part)) {
+   GMimeMessage *message = GMIME_MESSAGE (node->part);
+   InternetAddressList *recipients;
+   const char *recipients_string;
+
+   printf ("> From: %s\n", g_mime_message_get_sender (message));
+   recipients = g_mime_message_get_recipients (message, 
GMIME_RECIPIENT_TYPE_TO);
+   recipients_string = internet_address_list_to_string (recipients, 0);
+   if (recipients_string)
+   printf ("> To: %s\n",
+   recipients_string);
+   recipients = g_mime_message_get_recipients (message, 
GMIME_RECIPIENT_TYPE_CC);
+   recipients_string = internet_address_list_to_string (recipients, 0);
+   if (recipients_string)
+   printf ("> Cc: %s\n",
+   recipients_string);
+   printf ("> Subject: %s\n", g_mime_message_get_subject (message));
+   printf ("> Date: %s\n", g_mime_message_get_date_as_string (message));
+   printf (">\n");
+} else if (GMIME_IS_PART (node->part)) {
+   GMimeContentType *content_type = g_mime_object_get_content_type 
(node->part);
+   GMimeContentDisposition *disposition = 
g_mime_object_get_content_disposition (node->part);
+
+   if (g_mime_content_type_is_type (content_type, "application", 
"pgp-encrypted") ||
+   g_mime_content_type_is_type (content_type, "application", 
"pgp-signature")) {
+   /* Ignore PGP/MIME cruft parts */
+   } else if (g_mime_content_type_is_type (content_type, "text", "*") &&
+  !g_mime_content_type_is_type (content_type, "text", "html")) 
{
+   

[PATCH v2 1/3] show/reply: Unify the code that extracts text parts

2012-03-27 Thread Austin Clements
Previously, show and reply had separate implementations of decoding
and printing text parts.  Now both use show's implementation, which
was more complete.  Show's implementation has been extended with an
option to add reply quoting to the extracted part (this is implemented
as a named flag to avoid naked booleans, even though it's the only
flag it can take).
---
 notmuch-client.h |8 
 notmuch-reply.c  |   28 
 notmuch-show.c   |   23 +++
 3 files changed, 31 insertions(+), 28 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index fa04fa2..203ac49 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -197,6 +197,14 @@ format_part_json (const void *ctx, mime_node_t *node, 
notmuch_bool_t first);
 void
 format_headers_json (const void *ctx, GMimeMessage *message, notmuch_bool_t 
reply);

+typedef enum {
+NOTMUCH_SHOW_TEXT_PART_REPLY = 1 << 0,
+} notmuch_show_text_part_flags;
+
+void
+show_text_part_content (GMimeObject *part, GMimeStream *stream_out,
+   notmuch_show_text_part_flags flags);
+
 char *
 json_quote_chararray (const void *ctx, const char *str, const size_t len);

diff --git a/notmuch-reply.c b/notmuch-reply.c
index e2b6c25..2f5ed3d 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -21,7 +21,6 @@
  */

 #include "notmuch-client.h"
-#include "gmime-filter-reply.h"
 #include "gmime-filter-headers.h"

 static void
@@ -106,29 +105,10 @@ reply_part_content (GMimeObject *part)
 else if (g_mime_content_type_is_type (content_type, "text", "*") &&
!g_mime_content_type_is_type (content_type, "text", "html"))
 {
-   GMimeStream *stream_stdout = NULL, *stream_filter = NULL;
-   GMimeDataWrapper *wrapper;
-   const char *charset;
-
-   charset = g_mime_object_get_content_type_parameter (part, "charset");
-   stream_stdout = g_mime_stream_file_new (stdout);
-   if (stream_stdout) {
-   g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), 
FALSE);
-   stream_filter = g_mime_stream_filter_new(stream_stdout);
-   if (charset) {
-   g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
-g_mime_filter_charset_new(charset, 
"UTF-8"));
-   }
-   }
-   g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
-g_mime_filter_reply_new(TRUE));
-   wrapper = g_mime_part_get_content_object (GMIME_PART (part));
-   if (wrapper && stream_filter)
-   g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
-   if (stream_filter)
-   g_object_unref(stream_filter);
-   if (stream_stdout)
-   g_object_unref(stream_stdout);
+   GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
+   g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
+   show_text_part_content (part, stream_stdout, 
NOTMUCH_SHOW_TEXT_PART_REPLY);
+   g_object_unref(stream_stdout);
 }
 else
 {
diff --git a/notmuch-show.c b/notmuch-show.c
index ff9d427..0bf5e21 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -19,6 +19,7 @@
  */

 #include "notmuch-client.h"
+#include "gmime-filter-reply.h"

 static notmuch_status_t
 format_part_text (const void *ctx, mime_node_t *node,
@@ -247,13 +248,17 @@ format_headers_json (const void *ctx, GMimeMessage 
*message, notmuch_bool_t repl

 /* Write a MIME text part out to the given stream.
  *
+ * If (flags & NOTMUCH_SHOW_TEXT_PART_REPLY), this prepends "> " to
+ * each output line.
+ *
  * Both line-ending conversion (CRLF->LF) and charset conversion ( ->
  * UTF-8) will be performed, so it is inappropriate to call this
  * function with a non-text part. Doing so will trigger an internal
  * error.
  */
-static void
-show_text_part_content (GMimeObject *part, GMimeStream *stream_out)
+void
+show_text_part_content (GMimeObject *part, GMimeStream *stream_out,
+   notmuch_show_text_part_flags flags)
 {
 GMimeContentType *content_type = g_mime_object_get_content_type 
(GMIME_OBJECT (part));
 GMimeStream *stream_filter = NULL;
@@ -286,6 +291,16 @@ show_text_part_content (GMimeObject *part, GMimeStream 
*stream_out)

 }

+if (flags & NOTMUCH_SHOW_TEXT_PART_REPLY) {
+   GMimeFilter *reply_filter;
+   reply_filter = g_mime_filter_reply_new (TRUE);
+   if (reply_filter) {
+   g_mime_stream_filter_add (GMIME_STREAM_FILTER (stream_filter),
+ reply_filter);
+   g_object_unref (reply_filter);
+   }
+}
+
 wrapper = g_mime_part_get_content_object (GMIME_PART (part));
 if (wrapper && stream_filter)
g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
@@ -532,7 +547,7 @@ format_part_text (const void *ctx, mime_node_t *node,
{
GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);

[PATCH v2 0/3] Rewrite default reply format

2012-03-27 Thread Austin Clements
This version fixes two minor formatting issues that Tomi pointed out
[1].  There are no other changes.

[1] id:"m2d382ia9d.fsf at guru.guru-group.fi"



[PATCH 0/3] Rewrite default reply format

2012-03-27 Thread Austin Clements
Thanks for the review.  New version coming shortly...

Quoth Tomi Ollila on Mar 24 at 12:06 pm:
> Austin Clements  writes:
> 
> > The default reply format is the last bastion of the old message
> > formatter style.  This series converts it to the new self-recursive
> > style.  After this, there will be one last series to rip out the
> > compatibility code and do final cleanup.
> 
> Works fine, patches look good... just 2 "spacing" questions:
> 
> in id:"1332473647-9133-2-git-send-email-amdragon at mit.edu"
> 
> + typedef enum {
> + NOTMUCH_SHOW_TEXT_PART_REPLY = 1<<0,
> + } notmuch_show_text_part_flags;
> 
> Should this be like: NOTMUCH_SHOW_TEXT_PART_REPLY = (1 << 0),

Changed to NOTMUCH_SHOW_TEXT_PART_REPLY = 1 << 0 to be consistent with
operator spacing.  I left out the parens since they aren't necessary.

> and this
> 
> + * If flags_SHOW_TEXT_PART_REPLY, this prepends "> " to each
> + * output line.
> + *
> 
> like:
> 
> + * If flags & NOTMUCH_SHOW_TEXT_PART_REPLY, this prepends "> " to each

Changed.  On this one I put in parens to better distinguish it from
the surrounding prose.

> Tomi


bug in emacs reply code?

2012-03-27 Thread Jani Nikula

Hi all, just upgraded from 0.11 to master on one machine, and emacs
reply started failing as follows. The four tests fail, all others pass.

$ emacs --version
GNU Emacs 23.2.1

$ make test
[...]
emacs: Testing emacs interface
[...]
 FAIL   Reply within emacs
--- emacs.24.expected  2012-03-27 15:02:05.894335772 +
+++ emacs.24.output2012-03-27 15:02:05.884335772 +
@@ -1,6 +1,9 @@
From: Notmuch Test Suite 
+From: Notmuch Test Suite 
+To: user at example.com
To: user at example.com
Subject: Re: Testing message sent via SMTP
+Subject: Re: Testing message sent via SMTP
In-Reply-To: 
Fcc: /home/jani/tools/notmuch/test/tmp.emacs/mail/sent
--text follows this line--
 FAIL   Reply within emacs to a multipart/mixed message
--- emacs.25.expected 2012-03-27 15:02:06.294335772 +
+++ emacs.25.output   2012-03-27 15:02:06.294335772 +
@@ -1,6 +1,9 @@
From: Notmuch Test Suite 
+From: Notmuch Test Suite 
+To: Adrian Perez de Castro ,
notmuch at notmuchmail.org
To: Adrian Perez de Castro ,
notmuch at notmuchmail.org
Subject: Re: [notmuch] Introducing myself
+Subject: Re: [notmuch] Introducing myself
In-Reply-To: <20091118002059.067214ed at hikari>
Fcc: /home/jani/tools/notmuch/test/tmp.emacs/mail/sent
--text follows this line--
 FAIL   Reply within emacs to a multipart/alternative message
--- emacs.26.expected 2012-03-27 15:02:06.914335772 +
+++ emacs.26.output   2012-03-27 15:02:06.914335772 +
@@ -1,6 +1,9 @@
From: Notmuch Test Suite 
+From: Notmuch Test Suite 
+To: Alex Botero-Lowry ,
notmuch at notmuchmail.org
To: Alex Botero-Lowry ,
notmuch at notmuchmail.org
Subject: Re: [notmuch] preliminary FreeBSD support
+Subject: Re: [notmuch] preliminary FreeBSD support
In-Reply-To:

Fcc: /home/jani/tools/notmuch/test/tmp.emacs/mail/sent
--text follows this line--
 FAIL   Quote MML tags in reply
--- emacs.27.expected 2012-03-27 15:02:07.524335772 +
+++ emacs.27.output   2012-03-27 15:02:07.524335772 +
@@ -1,6 +1,8 @@
From: Notmuch Test Suite 
+From: Notmuch Test Suite 
To: 
Subject: Re: Quote MML tags in reply
+Subject: Re: Quote MML tags in reply
In-Reply-To: 
Fcc: /home/jani/tools/notmuch/test/tmp.emacs/mail/sent
--text follows this line--
[...]


Goto command for existing search windows

2012-03-27 Thread Mark Anderson
I was looking for a function which would find a buffer based on one of
my saved searches, and perform the search if it didn't exist.

I've gotten it a bit closer, if I perform the search that matches a
saved search, then this routine will find it because of the magic in
notmuch-search-buffer-title, but perhaps someone else feels up to
searching through the saved searches directly?



(defun notmuch-goto-or-search ( query)
  "Find a notmuch-search buffer with the given query, or run 
\"notmuch search\" with the given `query' and display results.

If `query' is nil, it is read interactively from the minibuffer."
  (interactive)
  (if (null query)
  (setq query (notmuch-read-query "Notmuch goto-or-search: ")))
  (let ((buffer-name (notmuch-search-buffer-title query)))
(setq buf (get-buffer buffer-name)))

(if (not buf)
(notmuch-search query)
  (switch-to-buffer buf)
  )))

I then use it something like this:

(global-set-key [C-f1] (lambda () (interactive) (notmuch-goto-or-search 
"tag:inbox and tag:unread and not tag:deleted")))
(global-set-key [C-f2] (lambda () (interactive) (notmuch-goto-or-search 
"tag:inbox and not tag:deleted")))
(global-set-key [C-f3] 'notmuch)
(global-set-key [C-f6] (lambda () (interactive) (notmuch-goto-or-search 
"tag:todo and not tag:deleted")))

It would be better if I could use my Inbox, INBOX and todo names for the
saved searches, but how to do that without breaking generality of
searching the body of the email?  Do I have to define my own ss: (saved
search) prefix or something, as I believe some others have?

This is what I'm willing to do today, and it works for me, I could patch
notmuch.el, but I wondered about answering the other questions.

Also, some elisp master could hint about how to make the binding not so
ugly. ;)

Another appreciated elisp hint would be how to get the buf variable to
go inside the let, I keep getting complaints about buffer-name not being
defined, thus the "ugly" setq, which works.

Enjoy,

-Mark



[PATCH 1/7] Split notmuch_database_close into two functions

2012-03-27 Thread Justus Winter
Formerly notmuch_database_close closed the xapian database and
destroyed the talloc structure associated with the notmuch database
object. Split notmuch_database_close into notmuch_database_close and
notmuch_database_destroy.

This makes it possible for long running programs to close the xapian
database and thus release the lock associated with it without
destroying the data structures obtained from it.

This also makes the api more consistent since every other data
structure has a destructor function.

Signed-off-by: Justus Winter <4winter at informatik.uni-hamburg.de>
---
 lib/database.cc |   14 --
 lib/notmuch.h   |   15 +++
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 16c4354..2fefcad 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -642,7 +642,7 @@ notmuch_database_open (const char *path,
 "   read-write mode.\n",
 notmuch_path, version, NOTMUCH_DATABASE_VERSION);
notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
-   notmuch_database_close (notmuch);
+   notmuch_database_destroy (notmuch);
notmuch = NULL;
goto DONE;
}
@@ -702,7 +702,7 @@ notmuch_database_open (const char *path,
 } catch (const Xapian::Error ) {
fprintf (stderr, "A Xapian exception occurred opening database: %s\n",
 error.get_msg().c_str());
-   notmuch_database_close (notmuch);
+   notmuch_database_destroy (notmuch);
notmuch = NULL;
 }

@@ -738,9 +738,19 @@ notmuch_database_close (notmuch_database_t *notmuch)
 }

 delete notmuch->term_gen;
+notmuch->term_gen = NULL;
 delete notmuch->query_parser;
+notmuch->query_parser = NULL;
 delete notmuch->xapian_db;
+notmuch->xapian_db = NULL;
 delete notmuch->value_range_processor;
+notmuch->value_range_processor = NULL;
+}
+
+void
+notmuch_database_destroy (notmuch_database_t *notmuch)
+{
+notmuch_database_close (notmuch);
 talloc_free (notmuch);
 }

diff --git a/lib/notmuch.h b/lib/notmuch.h
index babd208..2fb4e70 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -133,7 +133,7 @@ typedef struct _notmuch_filenames notmuch_filenames_t;
  *
  * After a successful call to notmuch_database_create, the returned
  * database will be open so the caller should call
- * notmuch_database_close when finished with it.
+ * notmuch_database_destroy when finished with it.
  *
  * The database will not yet have any data in it
  * (notmuch_database_create itself is a very cheap function). Messages
@@ -165,7 +165,7 @@ typedef enum {
  * An existing notmuch database can be identified by the presence of a
  * directory named ".notmuch" below 'path'.
  *
- * The caller should call notmuch_database_close when finished with
+ * The caller should call notmuch_database_destroy when finished with
  * this database.
  *
  * In case of any failure, this function returns NULL, (after printing
@@ -175,11 +175,18 @@ notmuch_database_t *
 notmuch_database_open (const char *path,
   notmuch_database_mode_t mode);

-/* Close the given notmuch database, freeing all associated
- * resources. See notmuch_database_open. */
+/* Close the given notmuch database.
+ *
+ * This function is called by notmuch_database_destroy and can be
+ * called multiple times. */
 void
 notmuch_database_close (notmuch_database_t *database);

+/* Destroy the notmuch database freeing all associated
+ * resources */
+void
+notmuch_database_destroy (notmuch_database_t *database);
+
 /* Return the database path of the given database.
  *
  * The return value is a string owned by notmuch so should not be
-- 
1.7.9.1



[RFC] Split notmuch_database_close into two functions

2012-03-27 Thread Justus Winter
You're right of course, updated patch sent as a follow up.

Justus


[PATCH 0/2] Escape message ID queries in Emacs

2012-03-27 Thread Tomi Ollila
On Tue, Mar 27 2012, Austin Clements wrote:

> Currently, Emacs does not escape message ID queries and is
> inconsistent about quoting them.  This patch centralizes this in one
> function that always produces a properly quoted and escaped message ID
> query.
>
> With this, Emacs no longer gets confused by Tomi's crazy message,
>   id:"id:""1332281811-24710-2b-git-send-email-tomi.ollila at iki.fi"""

LGTM. Things work!


One observation, though:

In search bar the following queries return one match:

id:id:"1332281811-24710-2b-git-send-email-tomi.ollila at iki.fi"
id:"id:""1332281811-24710-2b-git-send-email-tomi.ollila at iki.fi"""

but

id:"id:"1332281811-24710-2b-git-send-email-tomi.ollila at iki.fi""

return 0 matches.

It looks like the (above) search strings goes verbatim to command line

i.e. 'notmuch' 'search' '--sort=oldest-first' 'id:...'

can be used to compare... so that would be CLI issue if there
is ever need to do do anything with it.

+1

Thanks for fixing this.

Tomi


[PATCH] emacs: Fix mis-named argument to notmuch-get-bodypart-internal

2012-03-27 Thread Tomi Ollila
On Tue, Mar 27 2012, Austin Clements  wrote:

> Previously, this function took an argument called "message-id", even
> though it was a general query, rather than a message ID.  This changes
> it to "query".
> ---

+1 

Tomi


>  emacs/notmuch-lib.el |4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
> index 2e367b5..4b17ecc 100644
> --- a/emacs/notmuch-lib.el
> +++ b/emacs/notmuch-lib.el
> @@ -219,13 +219,13 @@ the given type."
>  
>  ;; Helper for parts which are generally not included in the default
>  ;; JSON output.
> -(defun notmuch-get-bodypart-internal (message-id part-number process-crypto)
> +(defun notmuch-get-bodypart-internal (query part-number process-crypto)
>(let ((args '("show" "--format=raw"))
>   (part-arg (format "--part=%s" part-number)))
>  (setq args (append args (list part-arg)))
>  (if process-crypto
>   (setq args (append args '("--decrypt"
> -(setq args (append args (list message-id)))
> +(setq args (append args (list query)))
>  (with-temp-buffer
>(let ((coding-system-for-read 'no-conversion))
>   (progn
> -- 
> 1.7.7.2
>
> ___
> notmuch mailing list
> notmuch at notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch


Unofficial notmuch wiki concerns

2012-03-27 Thread David Bremner
On Mon, 26 Mar 2012 12:39:47 -0500, Kyle Sexton  wrote:
> 
> My goal is to make a site where the documentation is easy to update,
> and attractive.  My concern is having too many places out there for
> information.  I tried to assuage that with the disclaimer pointing to
> the canonical site.  Does the community think there is space for an
> unofficial wiki like this?

[ For those of you following along at home, notmuchuchmail.org is 
  an ikiwiki instance, writable by anonymous git push ]

First, it's great that you want to give something back to the notmuch
project.  As a project, I think we should be primarily concerned with
the quality of the official documentation that ships with the software, 
but I recognize that some things are too transient or specialized to fit
in the official docs.

Personally, I would much rather you help improve the notmuch wiki than
fork it.

If you want to have your personal site, like a blog, of course that's
fine. But if you expect other people to contribute to your wiki instead
of the official one (and the generic name kind of suggests that you do,
as compared to mocker.org), then I think it isn't helpful. The set of
contributors to the wiki (like the overall notmuch community) is
extremely small, and splitting that will decrease the quality of both
splits.

If there are technical barriers preventing contributing to the notmuch
wiki, then the folk on #notmuch would be happy to help with that.  It
might just be that you prefer some other wiki software; unfortunately
these are the sorts of compromises needed to make free software projects
(and other projects) work.  Or you can agitate to have the project
change it's wiki, if you feel that strongly about it.

David
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 315 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120327/6c524d7b/attachment.pgp>


[PATCH 0/2] Escape message ID queries in Emacs

2012-03-27 Thread Austin Clements
On Tue, 27 Mar 2012, Tomi Ollila  wrote:
> On Tue, Mar 27 2012, Austin Clements wrote:
>
>> Currently, Emacs does not escape message ID queries and is
>> inconsistent about quoting them.  This patch centralizes this in one
>> function that always produces a properly quoted and escaped message ID
>> query.
>>
>> With this, Emacs no longer gets confused by Tomi's crazy message,
>>   id:"id:""1332281811-24710-2b-git-send-email-tomi.ollila at iki.fi"""
>
> LGTM. Things work!
>
>
> One observation, though:
>
> In search bar the following queries return one match:
>
> id:id:"1332281811-24710-2b-git-send-email-tomi.ollila at iki.fi"
> id:"id:""1332281811-24710-2b-git-send-email-tomi.ollila at iki.fi"""
>
> but
>
> id:"id:"1332281811-24710-2b-git-send-email-tomi.ollila at iki.fi""
>
> return 0 matches.
>
> It looks like the (above) search strings goes verbatim to command line
>
> i.e. 'notmuch' 'search' '--sort=oldest-first' 'id:...'
>
> can be used to compare... so that would be CLI issue if there
> is ever need to do do anything with it.

I'm not sure I would consider this a CLI "issue".  It may not be
intuitive, but it is an intentional part of the Xapian query parser's
grammar.  If a boolean prefix is followed immediately by a quote, then
the term is between that quote and the next quote, modulo an escaping
rule that lets you include a literal quote in the term by doubling it in
the query string.  Together, these rules let you reliably put anything
in a boolean search term.

> +1
>
> Thanks for fixing this.
>
> Tomi


[PATCH v3 4/4] cli: refactor "notmuch restore" message tagging into a separate function

2012-03-27 Thread Jani Nikula
Refactor to make tagging code easier to reuse in the future. No
functional changes.

Signed-off-by: Jani Nikula 
---
 notmuch-restore.c |  148 -
 1 files changed, 78 insertions(+), 70 deletions(-)

diff --git a/notmuch-restore.c b/notmuch-restore.c
index 87d9772..d3b9246 100644
--- a/notmuch-restore.c
+++ b/notmuch-restore.c
@@ -20,6 +20,81 @@

 #include "notmuch-client.h"

+static int
+tag_message (notmuch_database_t *notmuch, const char *message_id,
+char *file_tags, notmuch_bool_t remove_all,
+notmuch_bool_t synchronize_flags)
+{
+notmuch_status_t status;
+notmuch_tags_t *db_tags;
+char *db_tags_str;
+notmuch_message_t *message = NULL;
+const char *tag;
+char *next;
+int ret = 0;
+
+status = notmuch_database_find_message (notmuch, message_id, );
+if (status || message == NULL) {
+   fprintf (stderr, "Warning: Cannot apply tags to %smessage: %s\n",
+message ? "" : "missing ", message_id);
+   if (status)
+   fprintf (stderr, "%s\n", notmuch_status_to_string(status));
+   return 1;
+}
+
+/* In order to detect missing messages, this check/optimization is
+ * intentionally done *after* first finding the message. */
+if (!remove_all && (file_tags == NULL || *file_tags == '\0'))
+   goto DONE;
+
+db_tags_str = NULL;
+for (db_tags = notmuch_message_get_tags (message);
+notmuch_tags_valid (db_tags);
+notmuch_tags_move_to_next (db_tags)) {
+   tag = notmuch_tags_get (db_tags);
+
+   if (db_tags_str)
+   db_tags_str = talloc_asprintf_append (db_tags_str, " %s", tag);
+   else
+   db_tags_str = talloc_strdup (message, tag);
+}
+
+if (((file_tags == NULL || *file_tags == '\0') &&
+(db_tags_str == NULL || *db_tags_str == '\0')) ||
+   (file_tags && db_tags_str && strcmp (file_tags, db_tags_str) == 0))
+   goto DONE;
+
+notmuch_message_freeze (message);
+
+if (remove_all)
+   notmuch_message_remove_all_tags (message);
+
+next = file_tags;
+while (next) {
+   tag = strsep (, " ");
+   if (*tag == '\0')
+   continue;
+   status = notmuch_message_add_tag (message, tag);
+   if (status) {
+   fprintf (stderr, "Error applying tag %s to message %s:\n",
+tag, message_id);
+   fprintf (stderr, "%s\n", notmuch_status_to_string (status));
+   ret = 1;
+   }
+}
+
+notmuch_message_thaw (message);
+
+if (synchronize_flags)
+   notmuch_message_tags_to_maildir_flags (message);
+
+DONE:
+if (message)
+   notmuch_message_destroy (message);
+
+return ret;
+}
+
 int
 notmuch_restore_command (unused (void *ctx), int argc, char *argv[])
 {
@@ -88,11 +163,7 @@ notmuch_restore_command (unused (void *ctx), int argc, char 
*argv[])

 while ((line_len = getline (, _size, input)) != -1) {
regmatch_t match[3];
-   char *message_id, *file_tags, *tag, *next;
-   notmuch_message_t *message = NULL;
-   notmuch_status_t status;
-   notmuch_tags_t *db_tags;
-   char *db_tags_str;
+   char *message_id, *file_tags;

chomp_newline (line);

@@ -109,72 +180,9 @@ notmuch_restore_command (unused (void *ctx), int argc, 
char *argv[])
file_tags = xstrndup (line + match[2].rm_so,
  match[2].rm_eo - match[2].rm_so);

-   status = notmuch_database_find_message (notmuch, message_id, );
-   if (status || message == NULL) {
-   fprintf (stderr, "Warning: Cannot apply tags to %smessage: %s\n",
-message ? "" : "missing ", message_id);
-   if (status)
-   fprintf (stderr, "%s\n",
-notmuch_status_to_string(status));
-   goto NEXT_LINE;
-   }
-
-   /* In order to detect missing messages, this check/optimization is
-* intentionally done *after* first finding the message.  */
-   if (accumulate && (file_tags == NULL || *file_tags == '\0'))
-   {
-   goto NEXT_LINE;
-   }
-
-   db_tags_str = NULL;
-   for (db_tags = notmuch_message_get_tags (message);
-notmuch_tags_valid (db_tags);
-notmuch_tags_move_to_next (db_tags))
-   {
-   const char *tag = notmuch_tags_get (db_tags);
-
-   if (db_tags_str)
-   db_tags_str = talloc_asprintf_append (db_tags_str, " %s", tag);
-   else
-   db_tags_str = talloc_strdup (message, tag);
-   }
-
-   if (((file_tags == NULL || *file_tags == '\0') &&
-(db_tags_str == NULL || *db_tags_str == '\0')) ||
-   (file_tags && db_tags_str && strcmp (file_tags, db_tags_str) == 0))
-   {
-   goto NEXT_LINE;
-   }
-
-   notmuch_message_freeze (message);
-
-   if (!accumulate)
-   notmuch_message_remove_all_tags (message);
-
-   next = file_tags;
-  

[PATCH v3 3/4] cli: refactor "notmuch tag" query tagging into a separate function

2012-03-27 Thread Jani Nikula
Refactor to make tagging code easier to reuse in the future. No
functional changes.

Signed-off-by: Jani Nikula 
---
 notmuch-tag.c |  104 +
 1 files changed, 60 insertions(+), 44 deletions(-)

diff --git a/notmuch-tag.c b/notmuch-tag.c
index 0a6b140..05feed3 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -110,6 +110,63 @@ _optimize_tag_query (void *ctx, const char 
*orig_query_string,
 return query_string;
 }

+/* Tag messages matching 'query_string' according to 'tag_ops', which
+ * must be an array of tagging operations terminated with an empty
+ * element. */
+static int
+tag_query (void *ctx, notmuch_database_t *notmuch, const char *query_string,
+  tag_operation_t *tag_ops, notmuch_bool_t synchronize_flags)
+{
+notmuch_query_t *query;
+notmuch_messages_t *messages;
+notmuch_message_t *message;
+int i;
+
+/* Optimize the query so it excludes messages that already have
+ * the specified set of tags. */
+query_string = _optimize_tag_query (ctx, query_string, tag_ops);
+if (query_string == NULL) {
+   fprintf (stderr, "Out of memory.\n");
+   return 1;
+}
+
+query = notmuch_query_create (notmuch, query_string);
+if (query == NULL) {
+   fprintf (stderr, "Out of memory.\n");
+   return 1;
+}
+
+/* tagging is not interested in any special sort order */
+notmuch_query_set_sort (query, NOTMUCH_SORT_UNSORTED);
+
+for (messages = notmuch_query_search_messages (query);
+notmuch_messages_valid (messages) && !interrupted;
+notmuch_messages_move_to_next (messages))
+{
+   message = notmuch_messages_get (messages);
+
+   notmuch_message_freeze (message);
+
+   for (i = 0; tag_ops[i].tag; i++) {
+   if (tag_ops[i].remove)
+   notmuch_message_remove_tag (message, tag_ops[i].tag);
+   else
+   notmuch_message_add_tag (message, tag_ops[i].tag);
+   }
+
+   notmuch_message_thaw (message);
+
+   if (synchronize_flags)
+   notmuch_message_tags_to_maildir_flags (message);
+
+   notmuch_message_destroy (message);
+}
+
+notmuch_query_destroy (query);
+
+return interrupted;
+}
+
 int
 notmuch_tag_command (void *ctx, int argc, char *argv[])
 {
@@ -118,12 +175,10 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
 char *query_string;
 notmuch_config_t *config;
 notmuch_database_t *notmuch;
-notmuch_query_t *query;
-notmuch_messages_t *messages;
-notmuch_message_t *message;
 struct sigaction action;
 notmuch_bool_t synchronize_flags;
 int i;
+int ret;

 /* Setup our handler for SIGINT */
 memset (, 0, sizeof (struct sigaction));
@@ -170,14 +225,6 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
return 1;
 }

-/* Optimize the query so it excludes messages that already have
- * the specified set of tags. */
-query_string = _optimize_tag_query (ctx, query_string, tag_ops);
-if (query_string == NULL) {
-   fprintf (stderr, "Out of memory.\n");
-   return 1;
-}
-
 config = notmuch_config_open (ctx, NULL, NULL);
 if (config == NULL)
return 1;
@@ -189,40 +236,9 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])

 synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config);

-query = notmuch_query_create (notmuch, query_string);
-if (query == NULL) {
-   fprintf (stderr, "Out of memory.\n");
-   return 1;
-}
-
-/* tagging is not interested in any special sort order */
-notmuch_query_set_sort (query, NOTMUCH_SORT_UNSORTED);
+ret = tag_query (ctx, notmuch, query_string, tag_ops, synchronize_flags);

-for (messages = notmuch_query_search_messages (query);
-notmuch_messages_valid (messages) && !interrupted;
-notmuch_messages_move_to_next (messages))
-{
-   message = notmuch_messages_get (messages);
-
-   notmuch_message_freeze (message);
-
-   for (i = 0; tag_ops[i].tag; i++) {
-   if (tag_ops[i].remove)
-   notmuch_message_remove_tag (message, tag_ops[i].tag);
-   else
-   notmuch_message_add_tag (message, tag_ops[i].tag);
-   }
-
-   notmuch_message_thaw (message);
-
-   if (synchronize_flags)
-   notmuch_message_tags_to_maildir_flags (message);
-
-   notmuch_message_destroy (message);
-}
-
-notmuch_query_destroy (query);
 notmuch_database_close (notmuch);

-return interrupted;
+return ret;
 }
-- 
1.7.5.4



[PATCH v3 2/4] cli: refactor "notmuch tag" data structures for tagging operations

2012-03-27 Thread Jani Nikula
To simplify code, keep all tagging operations in a single array
instead of separate add and remove arrays. Apply tag changes in the
order specified on the command line, instead of first removing and
then adding the tags.

This results in a minor functional change: If a tag is both added and
removed, the last specified operation is now used. Previously the tag
was always added. Change the relevant test to reflect the new
behaviour.

Signed-off-by: Jani Nikula 
---
 notmuch-tag.c |   83 ++--
 test/tagging  |2 +-
 2 files changed, 40 insertions(+), 45 deletions(-)

diff --git a/notmuch-tag.c b/notmuch-tag.c
index 36b9b09..0a6b140 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -53,10 +53,14 @@ _escape_tag (char *buf, const char *tag)
 return buf;
 }

+typedef struct {
+const char *tag;
+notmuch_bool_t remove;
+} tag_operation_t;
+
 static char *
-_optimize_tag_query (void *ctx, const char *orig_query_string, char *argv[],
-int *add_tags, int add_tags_count,
-int *remove_tags, int remove_tags_count)
+_optimize_tag_query (void *ctx, const char *orig_query_string,
+const tag_operation_t *tag_ops)
 {
 /* This is subtler than it looks.  Xapian ignores the '-' operator
  * at the beginning both queries and parenthesized groups and,
@@ -71,15 +75,16 @@ _optimize_tag_query (void *ctx, const char 
*orig_query_string, char *argv[],
 int i;
 unsigned int max_tag_len = 0;

+/* Don't optimize if there are no tag changes. */
+if (tag_ops[0].tag == NULL)
+   return talloc_strdup (ctx, orig_query_string);
+
 /* Allocate a buffer for escaping tags.  This is large enough to
  * hold a fully escaped tag with every character doubled plus
  * enclosing quotes and a NUL. */
-for (i = 0; i < add_tags_count; i++)
-   if (strlen (argv[add_tags[i]] + 1) > max_tag_len)
-   max_tag_len = strlen (argv[add_tags[i]] + 1);
-for (i = 0; i < remove_tags_count; i++)
-   if (strlen (argv[remove_tags[i]] + 1) > max_tag_len)
-   max_tag_len = strlen (argv[remove_tags[i]] + 1);
+for (i = 0; tag_ops[i].tag; i++)
+   if (strlen (tag_ops[i].tag) > max_tag_len)
+   max_tag_len = strlen (tag_ops[i].tag);
 escaped = talloc_array(ctx, char, max_tag_len * 2 + 3);
 if (!escaped)
return NULL;
@@ -90,16 +95,11 @@ _optimize_tag_query (void *ctx, const char 
*orig_query_string, char *argv[],
 else
query_string = talloc_asprintf (ctx, "( %s ) and (", orig_query_string);

-for (i = 0; i < add_tags_count && query_string; i++) {
+for (i = 0; tag_ops[i].tag && query_string; i++) {
query_string = talloc_asprintf_append_buffer (
-   query_string, "%snot tag:%s", join,
-   _escape_tag (escaped, argv[add_tags[i]] + 1));
-   join = " or ";
-}
-for (i = 0; i < remove_tags_count && query_string; i++) {
-   query_string = talloc_asprintf_append_buffer (
-   query_string, "%stag:%s", join,
-   _escape_tag (escaped, argv[remove_tags[i]] + 1));
+   query_string, "%s%stag:%s", join,
+   tag_ops[i].remove ? "" : "not ",
+   _escape_tag (escaped, tag_ops[i].tag));
join = " or ";
 }

@@ -113,9 +113,8 @@ _optimize_tag_query (void *ctx, const char 
*orig_query_string, char *argv[],
 int
 notmuch_tag_command (void *ctx, int argc, char *argv[])
 {
-int *add_tags, *remove_tags;
-int add_tags_count = 0;
-int remove_tags_count = 0;
+tag_operation_t *tag_ops;
+int tag_ops_count = 0;
 char *query_string;
 notmuch_config_t *config;
 notmuch_database_t *notmuch;
@@ -133,35 +132,33 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
 action.sa_flags = SA_RESTART;
 sigaction (SIGINT, , NULL);

-add_tags = talloc_size (ctx, argc * sizeof (int));
-if (add_tags == NULL) {
-   fprintf (stderr, "Out of memory.\n");
-   return 1;
-}
+argc--; argv++; /* skip subcommand argument */

-remove_tags = talloc_size (ctx, argc * sizeof (int));
-if (remove_tags == NULL) {
+/* Array of tagging operations (add or remove), terminated with an
+ * empty element. */
+tag_ops = talloc_array (ctx, tag_operation_t, argc + 1);
+if (tag_ops == NULL) {
fprintf (stderr, "Out of memory.\n");
return 1;
 }

-argc--; argv++; /* skip subcommand argument */
-
 for (i = 0; i < argc; i++) {
if (strcmp (argv[i], "--") == 0) {
i++;
break;
}
-   if (argv[i][0] == '+') {
-   add_tags[add_tags_count++] = i;
-   } else if (argv[i][0] == '-') {
-   remove_tags[remove_tags_count++] = i;
+   if (argv[i][0] == '+' || argv[i][0] == '-') {
+   tag_ops[tag_ops_count].tag = argv[i] + 1;
+   tag_ops[tag_ops_count].remove = (argv[i][0] == '-');
+   tag_ops_count++;
} else {

[PATCH v3 1/4] test: add test for both adding and removing a tag at the same time

2012-03-27 Thread Jani Nikula
The current behaviour is that regardless of the order in which the
addition and removal of a tag are specified, the tag is added.

Signed-off-by: Jani Nikula 
---
 test/tagging |8 
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/test/tagging b/test/tagging
index 77202bf..3acf1bc 100755
--- a/test/tagging
+++ b/test/tagging
@@ -38,4 +38,12 @@ test_expect_equal "$output" "\
 thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; One (:\"  inbox tag1 unread)
 thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 unread)"

+test_begin_subtest "Tagging order"
+notmuch tag +tag4 -tag4 One
+notmuch tag -tag4 +tag4 Two
+output=$(notmuch search \* | notmuch_search_sanitize)
+test_expect_equal "$output" "\
+thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; One (:\"  inbox tag1 tag4 
unread)
+thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag4 unread)"
+
 test_done
-- 
1.7.5.4



[PATCH v3 0/4] cli: notmuch tag/restore refactoring

2012-03-27 Thread Jani Nikula
v3 of id:"cover.1332702915.git.jani at nikula.org" with the following
mostly non-functional changes:

 - add test for the current tagging behaviour in patch 1, and change the
   test in patch 2 when the behaviour is changed
 - handle the no tag changes case in _optimize_tag_query() in patch 2
 - add braces around the "tag_ops[tag_ops_count].remove = (argv[i][0] == '-');"
   assignment
 - document the tag_query() function a bit in patch 3
 - make tag_message() static in patch 4

BR,
Jani.


Jani Nikula (4):
  test: add test for both adding and removing a tag at the same time
  cli: refactor "notmuch tag" data structures for tagging operations
  cli: refactor "notmuch tag" query tagging into a separate function
  cli: refactor "notmuch restore" message tagging into a separate
function

 notmuch-restore.c |  148 -
 notmuch-tag.c |  173 -
 test/tagging  |8 +++
 3 files changed, 178 insertions(+), 151 deletions(-)

-- 
1.7.5.4



Bug#628018: [PATCH] notmuch-mutt utility for notmuch/contrib/

2012-03-27 Thread Stefano Zacchiroli
On Mon, Mar 26, 2012 at 01:03:32PM -0600, Scott Barker wrote:
> FYI, I use the following in my .muttrc, which includes an expansion of $HOME
> in , and it works fine:
> 
>   macro index / "mutt-notmuch --prompt 
> search$HOME/.cache/mutt_results" 
> "notmuch search"

Right, but I need support for variable expansions with defaults, because
there's no guarantee that $XDG_CACHE_HOME is defined in user
environment. I.e., I need the equivalent of shell ${name:-default}
idiom.

AFAICT that is not supported by Mutt natively. Hence the need of
resorting to shell escaping.

Hope this explains,
-- 
Stefano Zacchiroli zack@{upsilon.cc,pps.jussieu.fr,debian.org} . o .
Ma?tre de conf?rences   ..   http://upsilon.cc/zack   ..   . . o
Debian Project Leader...   @zack on identi.ca   ...o o o
? the first rule of tautology club is the first rule of tautology club ?


Re: [PATCH] emacs: Fix mis-named argument to notmuch-get-bodypart-internal

2012-03-27 Thread Tomi Ollila
On Tue, Mar 27 2012, Austin Clements amdra...@mit.edu wrote:

 Previously, this function took an argument called message-id, even
 though it was a general query, rather than a message ID.  This changes
 it to query.
 ---

+1 

Tomi


  emacs/notmuch-lib.el |4 ++--
  1 files changed, 2 insertions(+), 2 deletions(-)

 diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
 index 2e367b5..4b17ecc 100644
 --- a/emacs/notmuch-lib.el
 +++ b/emacs/notmuch-lib.el
 @@ -219,13 +219,13 @@ the given type.
  
  ;; Helper for parts which are generally not included in the default
  ;; JSON output.
 -(defun notmuch-get-bodypart-internal (message-id part-number process-crypto)
 +(defun notmuch-get-bodypart-internal (query part-number process-crypto)
(let ((args '(show --format=raw))
   (part-arg (format --part=%s part-number)))
  (setq args (append args (list part-arg)))
  (if process-crypto
   (setq args (append args '(--decrypt
 -(setq args (append args (list message-id)))
 +(setq args (append args (list query)))
  (with-temp-buffer
(let ((coding-system-for-read 'no-conversion))
   (progn
 -- 
 1.7.7.2

 ___
 notmuch mailing list
 notmuch@notmuchmail.org
 http://notmuchmail.org/mailman/listinfo/notmuch
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 0/2] Escape message ID queries in Emacs

2012-03-27 Thread Tomi Ollila
On Tue, Mar 27 2012, Austin Clements wrote:

 Currently, Emacs does not escape message ID queries and is
 inconsistent about quoting them.  This patch centralizes this in one
 function that always produces a properly quoted and escaped message ID
 query.

 With this, Emacs no longer gets confused by Tomi's crazy message,
   id:id:1332281811-24710-2b-git-send-email-tomi.oll...@iki.fi

LGTM. Things work!


One observation, though:

In search bar the following queries return one match:

id:id:1332281811-24710-2b-git-send-email-tomi.oll...@iki.fi
id:id:1332281811-24710-2b-git-send-email-tomi.oll...@iki.fi

but

id:id:1332281811-24710-2b-git-send-email-tomi.oll...@iki.fi

return 0 matches.

It looks like the (above) search strings goes verbatim to command line

i.e. 'notmuch' 'search' '--sort=oldest-first' 'id:...'

can be used to compare... so that would be CLI issue if there
is ever need to do do anything with it.

+1

Thanks for fixing this.

Tomi
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 0/2] Escape message ID queries in Emacs

2012-03-27 Thread Austin Clements
On Tue, 27 Mar 2012, Tomi Ollila tomi.oll...@iki.fi wrote:
 On Tue, Mar 27 2012, Austin Clements wrote:

 Currently, Emacs does not escape message ID queries and is
 inconsistent about quoting them.  This patch centralizes this in one
 function that always produces a properly quoted and escaped message ID
 query.

 With this, Emacs no longer gets confused by Tomi's crazy message,
   id:id:1332281811-24710-2b-git-send-email-tomi.oll...@iki.fi

 LGTM. Things work!


 One observation, though:

 In search bar the following queries return one match:

 id:id:1332281811-24710-2b-git-send-email-tomi.oll...@iki.fi
 id:id:1332281811-24710-2b-git-send-email-tomi.oll...@iki.fi

 but

 id:id:1332281811-24710-2b-git-send-email-tomi.oll...@iki.fi

 return 0 matches.

 It looks like the (above) search strings goes verbatim to command line

 i.e. 'notmuch' 'search' '--sort=oldest-first' 'id:...'

 can be used to compare... so that would be CLI issue if there
 is ever need to do do anything with it.

I'm not sure I would consider this a CLI issue.  It may not be
intuitive, but it is an intentional part of the Xapian query parser's
grammar.  If a boolean prefix is followed immediately by a quote, then
the term is between that quote and the next quote, modulo an escaping
rule that lets you include a literal quote in the term by doubling it in
the query string.  Together, these rules let you reliably put anything
in a boolean search term.

 +1

 Thanks for fixing this.

 Tomi
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [RFC] Split notmuch_database_close into two functions

2012-03-27 Thread Justus Winter
You're right of course, updated patch sent as a follow up.

Justus
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 1/7] Split notmuch_database_close into two functions

2012-03-27 Thread Justus Winter
Formerly notmuch_database_close closed the xapian database and
destroyed the talloc structure associated with the notmuch database
object. Split notmuch_database_close into notmuch_database_close and
notmuch_database_destroy.

This makes it possible for long running programs to close the xapian
database and thus release the lock associated with it without
destroying the data structures obtained from it.

This also makes the api more consistent since every other data
structure has a destructor function.

Signed-off-by: Justus Winter 4win...@informatik.uni-hamburg.de
---
 lib/database.cc |   14 --
 lib/notmuch.h   |   15 +++
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 16c4354..2fefcad 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -642,7 +642,7 @@ notmuch_database_open (const char *path,
read-write mode.\n,
 notmuch_path, version, NOTMUCH_DATABASE_VERSION);
notmuch-mode = NOTMUCH_DATABASE_MODE_READ_ONLY;
-   notmuch_database_close (notmuch);
+   notmuch_database_destroy (notmuch);
notmuch = NULL;
goto DONE;
}
@@ -702,7 +702,7 @@ notmuch_database_open (const char *path,
 } catch (const Xapian::Error error) {
fprintf (stderr, A Xapian exception occurred opening database: %s\n,
 error.get_msg().c_str());
-   notmuch_database_close (notmuch);
+   notmuch_database_destroy (notmuch);
notmuch = NULL;
 }
 
@@ -738,9 +738,19 @@ notmuch_database_close (notmuch_database_t *notmuch)
 }
 
 delete notmuch-term_gen;
+notmuch-term_gen = NULL;
 delete notmuch-query_parser;
+notmuch-query_parser = NULL;
 delete notmuch-xapian_db;
+notmuch-xapian_db = NULL;
 delete notmuch-value_range_processor;
+notmuch-value_range_processor = NULL;
+}
+
+void
+notmuch_database_destroy (notmuch_database_t *notmuch)
+{
+notmuch_database_close (notmuch);
 talloc_free (notmuch);
 }
 
diff --git a/lib/notmuch.h b/lib/notmuch.h
index babd208..2fb4e70 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -133,7 +133,7 @@ typedef struct _notmuch_filenames notmuch_filenames_t;
  *
  * After a successful call to notmuch_database_create, the returned
  * database will be open so the caller should call
- * notmuch_database_close when finished with it.
+ * notmuch_database_destroy when finished with it.
  *
  * The database will not yet have any data in it
  * (notmuch_database_create itself is a very cheap function). Messages
@@ -165,7 +165,7 @@ typedef enum {
  * An existing notmuch database can be identified by the presence of a
  * directory named .notmuch below 'path'.
  *
- * The caller should call notmuch_database_close when finished with
+ * The caller should call notmuch_database_destroy when finished with
  * this database.
  *
  * In case of any failure, this function returns NULL, (after printing
@@ -175,11 +175,18 @@ notmuch_database_t *
 notmuch_database_open (const char *path,
   notmuch_database_mode_t mode);
 
-/* Close the given notmuch database, freeing all associated
- * resources. See notmuch_database_open. */
+/* Close the given notmuch database.
+ *
+ * This function is called by notmuch_database_destroy and can be
+ * called multiple times. */
 void
 notmuch_database_close (notmuch_database_t *database);
 
+/* Destroy the notmuch database freeing all associated
+ * resources */
+void
+notmuch_database_destroy (notmuch_database_t *database);
+
 /* Return the database path of the given database.
  *
  * The return value is a string owned by notmuch so should not be
-- 
1.7.9.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: Unofficial notmuch wiki concerns

2012-03-27 Thread David Bremner
On Mon, 26 Mar 2012 12:39:47 -0500, Kyle Sexton k...@mocker.org wrote:
 
 My goal is to make a site where the documentation is easy to update,
 and attractive.  My concern is having too many places out there for
 information.  I tried to assuage that with the disclaimer pointing to
 the canonical site.  Does the community think there is space for an
 unofficial wiki like this?

[ For those of you following along at home, notmuchuchmail.org is 
  an ikiwiki instance, writable by anonymous git push ]

First, it's great that you want to give something back to the notmuch
project.  As a project, I think we should be primarily concerned with
the quality of the official documentation that ships with the software, 
but I recognize that some things are too transient or specialized to fit
in the official docs.

Personally, I would much rather you help improve the notmuch wiki than
fork it.

If you want to have your personal site, like a blog, of course that's
fine. But if you expect other people to contribute to your wiki instead
of the official one (and the generic name kind of suggests that you do,
as compared to mocker.org), then I think it isn't helpful. The set of
contributors to the wiki (like the overall notmuch community) is
extremely small, and splitting that will decrease the quality of both
splits.

If there are technical barriers preventing contributing to the notmuch
wiki, then the folk on #notmuch would be happy to help with that.  It
might just be that you prefer some other wiki software; unfortunately
these are the sorts of compromises needed to make free software projects
(and other projects) work.  Or you can agitate to have the project
change it's wiki, if you feel that strongly about it.

David


pgpgMUj3oOA36.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


bug in emacs reply code?

2012-03-27 Thread Jani Nikula

Hi all, just upgraded from 0.11 to master on one machine, and emacs
reply started failing as follows. The four tests fail, all others pass.

$ emacs --version
GNU Emacs 23.2.1

$ make test
[...]
emacs: Testing emacs interface
[...]
 FAIL   Reply within emacs
--- emacs.24.expected  2012-03-27 15:02:05.894335772 +
+++ emacs.24.output2012-03-27 15:02:05.884335772 +
@@ -1,6 +1,9 @@
From: Notmuch Test Suite test_su...@notmuchmail.org
+From: Notmuch Test Suite test_su...@notmuchmail.org
+To: u...@example.com
To: u...@example.com
Subject: Re: Testing message sent via SMTP
+Subject: Re: Testing message sent via SMTP
In-Reply-To: XXX
Fcc: /home/jani/tools/notmuch/test/tmp.emacs/mail/sent
--text follows this line--
 FAIL   Reply within emacs to a multipart/mixed message
--- emacs.25.expected 2012-03-27 15:02:06.294335772 +
+++ emacs.25.output   2012-03-27 15:02:06.294335772 +
@@ -1,6 +1,9 @@
From: Notmuch Test Suite test_su...@notmuchmail.org
+From: Notmuch Test Suite test_su...@notmuchmail.org
+To: Adrian Perez de Castro ape...@igalia.com,
notmuch@notmuchmail.org
To: Adrian Perez de Castro ape...@igalia.com,
notmuch@notmuchmail.org
Subject: Re: [notmuch] Introducing myself
+Subject: Re: [notmuch] Introducing myself
In-Reply-To: 20091118002059.067214ed@hikari
Fcc: /home/jani/tools/notmuch/test/tmp.emacs/mail/sent
--text follows this line--
 FAIL   Reply within emacs to a multipart/alternative message
--- emacs.26.expected 2012-03-27 15:02:06.914335772 +
+++ emacs.26.output   2012-03-27 15:02:06.914335772 +
@@ -1,6 +1,9 @@
From: Notmuch Test Suite test_su...@notmuchmail.org
+From: Notmuch Test Suite test_su...@notmuchmail.org
+To: Alex Botero-Lowry alex.boterolo...@gmail.com,
notmuch@notmuchmail.org
To: Alex Botero-Lowry alex.boterolo...@gmail.com,
notmuch@notmuchmail.org
Subject: Re: [notmuch] preliminary FreeBSD support
+Subject: Re: [notmuch] preliminary FreeBSD support
In-Reply-To:
cf0c4d610911171136h1713aa59w9cf9aa31f052a...@mail.gmail.com
Fcc: /home/jani/tools/notmuch/test/tmp.emacs/mail/sent
--text follows this line--
 FAIL   Quote MML tags in reply
--- emacs.27.expected 2012-03-27 15:02:07.524335772 +
+++ emacs.27.output   2012-03-27 15:02:07.524335772 +
@@ -1,6 +1,8 @@
From: Notmuch Test Suite test_su...@notmuchmail.org
+From: Notmuch Test Suite test_su...@notmuchmail.org
To: 
Subject: Re: Quote MML tags in reply
+Subject: Re: Quote MML tags in reply
In-Reply-To: test-emacs-mml-quot...@message.id
Fcc: /home/jani/tools/notmuch/test/tmp.emacs/mail/sent
--text follows this line--
[...]
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v3 0/4] cli: notmuch tag/restore refactoring

2012-03-27 Thread Tomi Ollila
On Tue, Mar 27 2012, Jani Nikula j...@nikula.org wrote:

 v3 of id:cover.1332702915.git.j...@nikula.org with the following
 mostly non-functional changes:

  - add test for the current tagging behaviour in patch 1, and change the
test in patch 2 when the behaviour is changed
  - handle the no tag changes case in _optimize_tag_query() in patch 2
  - add braces around the tag_ops[tag_ops_count].remove = (argv[i][0] == 
 '-');
assignment
  - document the tag_query() function a bit in patch 3
  - make tag_message() static in patch 4

LGTM.


 BR,
 Jani.

Tomi



 Jani Nikula (4):
   test: add test for both adding and removing a tag at the same time
   cli: refactor notmuch tag data structures for tagging operations
   cli: refactor notmuch tag query tagging into a separate function
   cli: refactor notmuch restore message tagging into a separate
 function

  notmuch-restore.c |  148 -
  notmuch-tag.c |  173 
 -
  test/tagging  |8 +++
  3 files changed, 178 insertions(+), 151 deletions(-)

 -- 
 1.7.5.4

 ___
 notmuch mailing list
 notmuch@notmuchmail.org
 http://notmuchmail.org/mailman/listinfo/notmuch
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Goto command for existing search windows

2012-03-27 Thread Mark Anderson
I was looking for a function which would find a buffer based on one of
my saved searches, and perform the search if it didn't exist.

I've gotten it a bit closer, if I perform the search that matches a
saved search, then this routine will find it because of the magic in
notmuch-search-buffer-title, but perhaps someone else feels up to
searching through the saved searches directly?



(defun notmuch-goto-or-search (optional query)
  Find a notmuch-search buffer with the given query, or run 
\notmuch search\ with the given `query' and display results.

If `query' is nil, it is read interactively from the minibuffer.
  (interactive)
  (if (null query)
  (setq query (notmuch-read-query Notmuch goto-or-search: )))
  (let ((buffer-name (notmuch-search-buffer-title query)))
(setq buf (get-buffer buffer-name)))
  
(if (not buf)
(notmuch-search query)
  (switch-to-buffer buf)
  )))

I then use it something like this:

(global-set-key [C-f1] (lambda () (interactive) (notmuch-goto-or-search 
tag:inbox and tag:unread and not tag:deleted)))
(global-set-key [C-f2] (lambda () (interactive) (notmuch-goto-or-search 
tag:inbox and not tag:deleted)))
(global-set-key [C-f3] 'notmuch)
(global-set-key [C-f6] (lambda () (interactive) (notmuch-goto-or-search 
tag:todo and not tag:deleted)))

It would be better if I could use my Inbox, INBOX and todo names for the
saved searches, but how to do that without breaking generality of
searching the body of the email?  Do I have to define my own ss: (saved
search) prefix or something, as I believe some others have?

This is what I'm willing to do today, and it works for me, I could patch
notmuch.el, but I wondered about answering the other questions.

Also, some elisp master could hint about how to make the binding not so
ugly. ;)

Another appreciated elisp hint would be how to get the buf variable to
go inside the let, I keep getting complaints about buffer-name not being
defined, thus the ugly setq, which works.

Enjoy,

-Mark

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 0/3] Rewrite default reply format

2012-03-27 Thread Austin Clements
Thanks for the review.  New version coming shortly...

Quoth Tomi Ollila on Mar 24 at 12:06 pm:
 Austin Clements amdra...@mit.edu writes:
 
  The default reply format is the last bastion of the old message
  formatter style.  This series converts it to the new self-recursive
  style.  After this, there will be one last series to rip out the
  compatibility code and do final cleanup.
 
 Works fine, patches look good... just 2 spacing questions:
 
 in id:1332473647-9133-2-git-send-email-amdra...@mit.edu
 
 + typedef enum {
 + NOTMUCH_SHOW_TEXT_PART_REPLY = 10,
 + } notmuch_show_text_part_flags;
 
 Should this be like: NOTMUCH_SHOW_TEXT_PART_REPLY = (1  0),

Changed to NOTMUCH_SHOW_TEXT_PART_REPLY = 1  0 to be consistent with
operator spacing.  I left out the parens since they aren't necessary.

 and this
 
 + * If flagsNOTMUCH_SHOW_TEXT_PART_REPLY, this prepends   to each
 + * output line.
 + *
 
 like:
 
 + * If flags  NOTMUCH_SHOW_TEXT_PART_REPLY, this prepends   to each

Changed.  On this one I put in parens to better distinguish it from
the surrounding prose.

 Tomi
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v2 0/3] Rewrite default reply format

2012-03-27 Thread Austin Clements
This version fixes two minor formatting issues that Tomi pointed out
[1].  There are no other changes.

[1] id:m2d382ia9d@guru.guru-group.fi

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v2 3/3] reply: Move reply citation printing to the recursive MIME walk

2012-03-27 Thread Austin Clements
This makes more logical sense, since it makes the recursive printer
responsible for the entire reply body and lets it start at the root of
the MIME tree instead of the first child.  (We could move reply header
creation in there, too, but if we ever support proper reply to
multiple messages, we'll want just one set of reply headers computed
from the entire message set and many bodies.)
---
 notmuch-reply.c |   12 ++--
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index 84a1220..0949d9f 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -47,7 +47,11 @@ format_part_reply (mime_node_t *node)
 {
 int i;
 
-if (GMIME_IS_MESSAGE (node-part)) {
+if (node-envelope_file) {
+   printf (On %s, %s wrote:\n,
+   notmuch_message_get_header (node-envelope_file, date),
+   notmuch_message_get_header (node-envelope_file, from));
+} else if (GMIME_IS_MESSAGE (node-part)) {
GMimeMessage *message = GMIME_MESSAGE (node-part);
InternetAddressList *recipients;
const char *recipients_string;
@@ -540,13 +544,9 @@ notmuch_reply_format_default(void *ctx,
g_object_unref (G_OBJECT (reply));
reply = NULL;
 
-   printf (On %s, %s wrote:\n,
-   notmuch_message_get_header (message, date),
-   notmuch_message_get_header (message, from));
-
if (mime_node_open (ctx, message, params-cryptoctx, params-decrypt,
root) == NOTMUCH_STATUS_SUCCESS) {
-   format_part_reply (mime_node_child (root, 0));
+   format_part_reply (root);
talloc_free (root);
}
 
-- 
1.7.9.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v2 2/3] reply: Convert default reply format to self-recursive style

2012-03-27 Thread Austin Clements
This re-arranges the default reply formatter code to use the
mime_node_t abstraction.  There are no semantic changes.
---
 notmuch-reply.c |  123 +--
 1 files changed, 47 insertions(+), 76 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index 2f5ed3d..84a1220 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -24,28 +24,6 @@
 #include gmime-filter-headers.h
 
 static void
-reply_headers_message_part (GMimeMessage *message);
-
-static void
-reply_part_content (GMimeObject *part);
-
-static const notmuch_show_format_t format_reply = {
-, NULL,
-   , NULL,
-   , NULL, reply_headers_message_part, \n,
-   ,
-   NULL,
-   NULL,
-   NULL,
-   reply_part_content,
-   NULL,
-   ,
-   ,
-   , ,
-
-};
-
-static void
 show_reply_headers (GMimeMessage *message)
 {
 GMimeStream *stream_stdout = NULL, *stream_filter = NULL;
@@ -65,66 +43,55 @@ show_reply_headers (GMimeMessage *message)
 }
 
 static void
-reply_headers_message_part (GMimeMessage *message)
+format_part_reply (mime_node_t *node)
 {
-InternetAddressList *recipients;
-const char *recipients_string;
-
-printf ( From: %s\n, g_mime_message_get_sender (message));
-recipients = g_mime_message_get_recipients (message, 
GMIME_RECIPIENT_TYPE_TO);
-recipients_string = internet_address_list_to_string (recipients, 0);
-if (recipients_string)
-   printf ( To: %s\n,
-   recipients_string);
-recipients = g_mime_message_get_recipients (message, 
GMIME_RECIPIENT_TYPE_CC);
-recipients_string = internet_address_list_to_string (recipients, 0);
-if (recipients_string)
-   printf ( Cc: %s\n,
-   recipients_string);
-printf ( Subject: %s\n, g_mime_message_get_subject (message));
-printf ( Date: %s\n, g_mime_message_get_date_as_string (message));
-}
-
-
-static void
-reply_part_content (GMimeObject *part)
-{
-GMimeContentType *content_type = g_mime_object_get_content_type 
(GMIME_OBJECT (part));
-GMimeContentDisposition *disposition = 
g_mime_object_get_content_disposition (part);
+int i;
 
-if (g_mime_content_type_is_type (content_type, multipart, *) ||
-   g_mime_content_type_is_type (content_type, message, rfc822))
-{
-   /* Output nothing, since multipart subparts will be handled 
individually. */
-}
-else if (g_mime_content_type_is_type (content_type, application, 
pgp-encrypted) ||
-g_mime_content_type_is_type (content_type, application, 
pgp-signature))
-{
-   /* Ignore PGP/MIME cruft parts */
-}
-else if (g_mime_content_type_is_type (content_type, text, *) 
-   !g_mime_content_type_is_type (content_type, text, html))
-{
-   GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
-   g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
-   show_text_part_content (part, stream_stdout, 
NOTMUCH_SHOW_TEXT_PART_REPLY);
-   g_object_unref(stream_stdout);
-}
-else
-{
-   if (disposition 
-   strcmp (disposition-disposition, GMIME_DISPOSITION_ATTACHMENT) == 
0)
-   {
-   const char *filename = g_mime_part_get_filename (GMIME_PART (part));
+if (GMIME_IS_MESSAGE (node-part)) {
+   GMimeMessage *message = GMIME_MESSAGE (node-part);
+   InternetAddressList *recipients;
+   const char *recipients_string;
+
+   printf ( From: %s\n, g_mime_message_get_sender (message));
+   recipients = g_mime_message_get_recipients (message, 
GMIME_RECIPIENT_TYPE_TO);
+   recipients_string = internet_address_list_to_string (recipients, 0);
+   if (recipients_string)
+   printf ( To: %s\n,
+   recipients_string);
+   recipients = g_mime_message_get_recipients (message, 
GMIME_RECIPIENT_TYPE_CC);
+   recipients_string = internet_address_list_to_string (recipients, 0);
+   if (recipients_string)
+   printf ( Cc: %s\n,
+   recipients_string);
+   printf ( Subject: %s\n, g_mime_message_get_subject (message));
+   printf ( Date: %s\n, g_mime_message_get_date_as_string (message));
+   printf (\n);
+} else if (GMIME_IS_PART (node-part)) {
+   GMimeContentType *content_type = g_mime_object_get_content_type 
(node-part);
+   GMimeContentDisposition *disposition = 
g_mime_object_get_content_disposition (node-part);
+
+   if (g_mime_content_type_is_type (content_type, application, 
pgp-encrypted) ||
+   g_mime_content_type_is_type (content_type, application, 
pgp-signature)) {
+   /* Ignore PGP/MIME cruft parts */
+   } else if (g_mime_content_type_is_type (content_type, text, *) 
+  !g_mime_content_type_is_type (content_type, text, html)) 
{
+   GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
+   g_mime_stream_file_set_owner 

[PATCH v2 1/3] show/reply: Unify the code that extracts text parts

2012-03-27 Thread Austin Clements
Previously, show and reply had separate implementations of decoding
and printing text parts.  Now both use show's implementation, which
was more complete.  Show's implementation has been extended with an
option to add reply quoting to the extracted part (this is implemented
as a named flag to avoid naked booleans, even though it's the only
flag it can take).
---
 notmuch-client.h |8 
 notmuch-reply.c  |   28 
 notmuch-show.c   |   23 +++
 3 files changed, 31 insertions(+), 28 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index fa04fa2..203ac49 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -197,6 +197,14 @@ format_part_json (const void *ctx, mime_node_t *node, 
notmuch_bool_t first);
 void
 format_headers_json (const void *ctx, GMimeMessage *message, notmuch_bool_t 
reply);
 
+typedef enum {
+NOTMUCH_SHOW_TEXT_PART_REPLY = 1  0,
+} notmuch_show_text_part_flags;
+
+void
+show_text_part_content (GMimeObject *part, GMimeStream *stream_out,
+   notmuch_show_text_part_flags flags);
+
 char *
 json_quote_chararray (const void *ctx, const char *str, const size_t len);
 
diff --git a/notmuch-reply.c b/notmuch-reply.c
index e2b6c25..2f5ed3d 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -21,7 +21,6 @@
  */
 
 #include notmuch-client.h
-#include gmime-filter-reply.h
 #include gmime-filter-headers.h
 
 static void
@@ -106,29 +105,10 @@ reply_part_content (GMimeObject *part)
 else if (g_mime_content_type_is_type (content_type, text, *) 
!g_mime_content_type_is_type (content_type, text, html))
 {
-   GMimeStream *stream_stdout = NULL, *stream_filter = NULL;
-   GMimeDataWrapper *wrapper;
-   const char *charset;
-
-   charset = g_mime_object_get_content_type_parameter (part, charset);
-   stream_stdout = g_mime_stream_file_new (stdout);
-   if (stream_stdout) {
-   g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), 
FALSE);
-   stream_filter = g_mime_stream_filter_new(stream_stdout);
-   if (charset) {
-   g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
-g_mime_filter_charset_new(charset, 
UTF-8));
-   }
-   }
-   g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
-g_mime_filter_reply_new(TRUE));
-   wrapper = g_mime_part_get_content_object (GMIME_PART (part));
-   if (wrapper  stream_filter)
-   g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
-   if (stream_filter)
-   g_object_unref(stream_filter);
-   if (stream_stdout)
-   g_object_unref(stream_stdout);
+   GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
+   g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
+   show_text_part_content (part, stream_stdout, 
NOTMUCH_SHOW_TEXT_PART_REPLY);
+   g_object_unref(stream_stdout);
 }
 else
 {
diff --git a/notmuch-show.c b/notmuch-show.c
index ff9d427..0bf5e21 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -19,6 +19,7 @@
  */
 
 #include notmuch-client.h
+#include gmime-filter-reply.h
 
 static notmuch_status_t
 format_part_text (const void *ctx, mime_node_t *node,
@@ -247,13 +248,17 @@ format_headers_json (const void *ctx, GMimeMessage 
*message, notmuch_bool_t repl
 
 /* Write a MIME text part out to the given stream.
  *
+ * If (flags  NOTMUCH_SHOW_TEXT_PART_REPLY), this prepends   to
+ * each output line.
+ *
  * Both line-ending conversion (CRLF-LF) and charset conversion ( -
  * UTF-8) will be performed, so it is inappropriate to call this
  * function with a non-text part. Doing so will trigger an internal
  * error.
  */
-static void
-show_text_part_content (GMimeObject *part, GMimeStream *stream_out)
+void
+show_text_part_content (GMimeObject *part, GMimeStream *stream_out,
+   notmuch_show_text_part_flags flags)
 {
 GMimeContentType *content_type = g_mime_object_get_content_type 
(GMIME_OBJECT (part));
 GMimeStream *stream_filter = NULL;
@@ -286,6 +291,16 @@ show_text_part_content (GMimeObject *part, GMimeStream 
*stream_out)
 
 }
 
+if (flags  NOTMUCH_SHOW_TEXT_PART_REPLY) {
+   GMimeFilter *reply_filter;
+   reply_filter = g_mime_filter_reply_new (TRUE);
+   if (reply_filter) {
+   g_mime_stream_filter_add (GMIME_STREAM_FILTER (stream_filter),
+ reply_filter);
+   g_object_unref (reply_filter);
+   }
+}
+
 wrapper = g_mime_part_get_content_object (GMIME_PART (part));
 if (wrapper  stream_filter)
g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
@@ -532,7 +547,7 @@ format_part_text (const void *ctx, mime_node_t *node,
{
GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
g_mime_stream_file_set_owner 

[Joerg Jaspert] Bug#666027: notmuch: get a quiet option

2012-03-27 Thread David Bremner
---BeginMessage---
Package: notmuch
Version: 0.12-1
Severity: wishlist

Dear Maintainer,

a feature wish to get to upstream:

as the subject says, it would be nice if notmuch gets a quiet
option. Especially for notmuch new that is. Its printing out lots of
Note: Ignoring blah and Processed blubb in almost no time and
similar useless stuff.

Fine if it likes itself, and heck i dont care if it ignores files, its
not the only one playing in this maildir, so a possibility to
make it shutup would be nice.

-- 
bye, Joerg
Maulkin db.oftc.net?
* Maulkin thinks Ganneff is doing evil ldap stuff again
Maulkin It's called the Ganneff fingerprint
Maulkin If somethign has 'db.foo.blah' it's had Ganneff involved



---End Message---
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch