[PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Daniel Schoepe

I accidentally used `filter' in the previous patch which isn't defined
by default during runtime, updated version in the attachment.
-- next part --
A non-text attachment was scrubbed...
Name: 0001-emacs-Make-queries-used-in-the-all-tags-section-conf.patch
Type: text/x-diff
Size: 4469 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20110525/214862c2/attachment.patch>
-- 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/20110525/214862c2/attachment.pgp>


[PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Daniel Schoepe
On Wed, 25 May 2011 10:44:51 -0400, Austin Clements  wrote:
> May I suggest a slightly different way of looking at this that will
> quell my inner parser?  Instead of configuring a weird "query
> fragment" like "and tag:unread" to be string-concatenated with the tag
> query, configure a *filter* query like merely "tag:unread" that
> narrows down what you'd like to be counted within the scope of a tag.
> The implementations are hardly different---simply generate the query
> "tag: and (  )"---but a filter is a well-formed query,
> not some string fragment.  Furthermore, the user can't get bitten by
> precedence and wind up with a query that counts messages that don't
> even have that tag.

Good point, I attached an updated patch that implements this.
-- next part --
A non-text attachment was scrubbed...
Name: 0001-emacs-Make-queries-used-in-the-all-tags-section-conf.patch
Type: text/x-diff
Size: 3312 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20110525/f02b5621/attachment.patch>
-- 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/20110525/f02b5621/attachment.pgp>


[PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Austin Clements
On Wed, May 25, 2011 at 5:21 PM, Daniel Schoepe
 wrote:
> On Wed, 25 May 2011 15:11:16 -0400, Austin Clements  
> wrote:
>> So, perhaps something like
>>
>> (defcustom notmuch-hello-tag-list-counts nil
>> ? "Method for generating counts displayed in the all tags list.
>>
>> This variable controls the query used to generate counts for each
>> tag in the \"all tags\" list. ?If nil, the tag list will count
>> all messages with each tag. ?This can be a query string that will
>> filter the messages counted for each tag. ?Finally, this can be a
>> function that will be called for each tag and should return a
>> filter query for that tag, or nil to hide the tag."
>> ? :type '(choice (const :tag "Count all messages" nil)
>> ? ? ? ? ? ? ? ? ?(const :tag "Count unread messages" "tag:unread")
>> ? ? ? ? ? ? ? ? ?(const :tag "Custom filter" string)
>> ? ? ? ? ? ? ? ? ?(const :tag "Custom filter function" function))
>> ? :group 'notmuch)
>
> That is slightly less accurate though, since the query is not only used
> to generate the counts, but also the searches that are performed when
> one presses return on a tag in the list.

'Doh.  That's what I get for not reading the surrounding code.  I
misunderstood what your patch was going for and assumed it was what
*I* wanted notmuch to do, which is to show me useful counts (e.g.,
unread count), but not to change the underlying query.  ]:--8)

So, to me, it seems like this turns the all tags section into another
saved searches section, just with a slight twist, and makes me wonder
if there's a better way to reconcile these.

> Ah, thanks. I guess too much exposure to Haskell (and how smart GHC is)
> makes me write things in a functional style without thinking about
> performance.

Hah, been there.  I have to constantly remind myself that Elisp is
*not* a self-respecting functional programming language, despite how
much it may look like Scheme.


[PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Carl Worth
On Thu, 26 May 2011 01:21:17 +0200, Daniel Schoepe  wrote:
> Since the main difference between those sections is the clear visual
> distinction, it might be an option to provide the user with functions to
> easily declare new sections for the hello screen, where this sort of
> thing is configurable. 

Yes!

This sounds very much like what I want myself. (I'm planning to write a
new "How I process mail" post summarizing some things I've learned about
notmuch and my personal habits over the past two months.)

I definitely have two very distinct groups of saved searches based on
how I use them. And it would be nice to have them visually separated in
the interface.

-Carl

-- 
carl.d.worth at intel.com
-- 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/20110525/0ac6b12a/attachment.pgp>


[PATCH 3/5] Fix hiding a message while some citations are shown in notmuch-show view.

2011-05-25 Thread Carl Worth
On Thu, 26 May 2011 03:10:11 +0400, Dmitry Kurochkin  wrote:
> On Wed, 25 May 2011 15:46:40 -0700, Carl Worth  wrote:
> Well, emacs trunk is not broken :)  The bug is in lisp code, so you can
> fix it in .emacs by redefining `isearch-range-invisible' function.  I do
> that now.

Oh, in that case we can fix this is notmuch emacs lisp by just defining
and using a fixed function. Is the broken function something we're
calling directly? Or is it being called indirectly? (being called by
other emacs lisp code that we are calling)?

If we can incorporate the fix, that would be great.

> Please consider pushing other patches from the series.  They do not fix
> any bug, but do simplify the code.  The last patch uses list for
> invisible overlay property as well.  But it does not break isearch
> because we do not search in hidden messages.

Hmmm... we should probably do that. I'd like isearch in notmuch to
search anything that is hidden.

> BTW would be nice to have a set of known-to-fail tests, i.e. bugs that
> are not fixed yet.  If we had it, the above test could be implemented
> and committed before we have the fix pushed.

We do! Use test_expect_equal_failure (yes, the name is horrible!)
instead of test_expect_equal and you should get what you want.

-Carl

-- 
carl.d.worth at intel.com
-- 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/20110525/864c9e60/attachment.pgp>


[PATCH 11/11] tag signed/encrypted during notmuch new

2011-05-25 Thread Jameson Graef Rollins
This patch adds the tag "signed" to messages with any multipart/signed
parts, and the tag "encrypted" to messages with any
multipart/encrypted parts.  This only occurs when messages are indexed
during notmuch new, so a database rebuild is required to have old
messages tagged.
---
 lib/index.cc   |6 ++
 test/crypto|   16 
 .../emacs.expected-output/notmuch-hello-view-inbox |6 +++---
 .../emacs.expected-output/notmuch-search-tag-inbox |6 +++---
 .../notmuch-show-thread-maildir-storage|8 
 test/multipart |4 ++--
 test/search|6 +++---
 test/search-output |2 ++
 8 files changed, 31 insertions(+), 23 deletions(-)

diff --git a/lib/index.cc b/lib/index.cc
index bdfb8ed..e8e9922 100644
--- a/lib/index.cc
+++ b/lib/index.cc
@@ -325,6 +325,12 @@ _index_mime_part (notmuch_message_t *message,
GMimeMultipart *multipart = GMIME_MULTIPART (part);
int i;

+   if (GMIME_IS_MULTIPART_SIGNED (multipart))
+ _notmuch_message_add_term (message, "tag", "signed");
+
+   if (GMIME_IS_MULTIPART_ENCRYPTED (multipart))
+ _notmuch_message_add_term (message, "tag", "encrypted");
+
for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {
if (GMIME_IS_MULTIPART_SIGNED (multipart)) {
/* Don't index the signature. */
diff --git a/test/crypto b/test/crypto
index 3b0f381..c5abcc3 100755
--- a/test/crypto
+++ b/test/crypto
@@ -46,7 +46,7 @@ expected='[[[{"id": "X",
  "filename": "Y",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["inbox","signed"],
  "headers": {"Subject": "test signed message 001",
  "From": "Notmuch Test Suite ",
  "To": "test_suite at notmuchmail.org",
@@ -76,7 +76,7 @@ expected='[[[{"id": "X",
  "filename": "Y",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["inbox","signed"],
  "headers": {"Subject": "test signed message 001",
  "From": "Notmuch Test Suite ",
  "To": "test_suite at notmuchmail.org",
@@ -106,7 +106,7 @@ expected='[[[{"id": "X",
  "filename": "Y",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["inbox","signed"],
  "headers": {"Subject": "test signed message 001",
  "From": "Notmuch Test Suite ",
  "To": "test_suite at notmuchmail.org",
@@ -141,7 +141,7 @@ output=$(notmuch show --format=text --decrypt subject:"test 
encrypted message 00
 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
 expected='message{ id:X depth:0 match:1 filename:X
 header{
-Notmuch Test Suite  (2000-01-01) (inbox)
+Notmuch Test Suite  (2000-01-01) (encrypted 
inbox)
 Subject: test encrypted message 001
 From: Notmuch Test Suite 
 To: test_suite at notmuchmail.org
@@ -172,7 +172,7 @@ expected='[[[{"id": "X",
  "filename": "Y",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["encrypted","inbox"],
  "headers": {"Subject": "test encrypted message 001",
  "From": "Notmuch Test Suite ",
  "To": "test_suite at notmuchmail.org",
@@ -223,7 +223,7 @@ expected='[[[{"id": "X",
  "filename": "Y",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["encrypted","inbox"],
  "headers": {"Subject": "test encrypted message 001",
  "From": "Notmuch Test Suite ",
  "To": "test_suite at notmuchmail.org",
@@ -258,7 +258,7 @@ expected='[[[{"id": "X",
  "filename": "Y",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["encrypted","inbox"],
  "headers": {"Subject": "test encrypted message 002",
  "From": "Notmuch Test Suite ",
  "To": "test_suite at notmuchmail.org",
@@ -309,7 +309,7 @@ expected='[[[{"id": "X",
  "filename": "Y",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["inbox","signed"],
  "headers": {"Subject": "test signed message 001",
  "From": "Notmuch Test Suite ",
  "To": "test_suite at notmuchmail.org",
diff --git a/test/emacs.expected-output/notmuch-hello-view-inbox 
b/test/emacs.expected-output/notmuch-hello-view-inbox
index 6472c46..894ae5f 100644
--- a/test/emacs.expected-output/notmuch-hello-view-inbox
+++ b/test/emacs.expected-output/notmuch-hello-view-inbox
@@ -1,16 +1,16 @@
   2009-11-17 [5/5]   Mikhail Gusarov, Carl Worth, Keith Packard  [notmuch] 
[PATCH 1/2] Close message file after parsing message headers (inbox unread)
-  2009-11-17 [7/7]   Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, 
Carl Worth  [notmuch] Working with Maildir storage? (inbox unread)
+  2009-11-17 [7/7]   Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, 
Carl Worth  [notmuch] Working with Maildir storage? (inbox signed unread)
   2009-11-17 [2/2]   

[PATCH 10/11] emacs: Add support for PGP/MIME verification/decryption

2011-05-25 Thread Jameson Graef Rollins
A new emacs configuration variable "notmuch-crypto-process-mime"
controls the processing of PGP/MIME signatures and encrypted parts.
When this is set true, notmuch-query will use the notmuch show
--decrypt flag to decrypt encrypted messages and/or calculate the
sigstatus of signed messages.  If sigstatus is available, notmuch-show
will place a specially color-coded header at the begining of the
signed message.

Also included is the ability to switch decryption/verification on/off
on the fly, which is bound to M-RET in notmuch-search-mode.
---
 emacs/Makefile.local|1 +
 emacs/notmuch-crypto.el |  104 +++
 emacs/notmuch-lib.el|5 ++
 emacs/notmuch-mua.el|9 +++-
 emacs/notmuch-query.el  |7 ++-
 emacs/notmuch-show.el   |   65 -
 emacs/notmuch.el|   10 -
 7 files changed, 175 insertions(+), 26 deletions(-)
 create mode 100644 emacs/notmuch-crypto.el

diff --git a/emacs/Makefile.local b/emacs/Makefile.local
index 1c09d87..1022777 100644
--- a/emacs/Makefile.local
+++ b/emacs/Makefile.local
@@ -12,6 +12,7 @@ emacs_sources := \
$(dir)/notmuch-address.el \
$(dir)/notmuch-maildir-fcc.el \
$(dir)/notmuch-message.el \
+   $(dir)/notmuch-crypto.el \
$(dir)/coolj.el

 emacs_images := \
diff --git a/emacs/notmuch-crypto.el b/emacs/notmuch-crypto.el
new file mode 100644
index 000..944452b
--- /dev/null
+++ b/emacs/notmuch-crypto.el
@@ -0,0 +1,104 @@
+;; notmuch-crypto.el --- functions for handling display of cryptographic 
metadata.
+;;
+;; Copyright ? Jameson Rollins
+;;
+;; This file is part of Notmuch.
+;;
+;; Notmuch is free software: you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Notmuch is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Notmuch.  If not, see .
+;;
+;; Authors: Jameson Rollins 
+
+(defcustom notmuch-crypto-process-mime nil
+  "Should cryptographic MIME parts be processed?
+
+If this variable is non-nil signatures in multipart/signed
+messages will be verified and multipart/encrypted parts will be
+decrypted.  The result of the crypto operation will be displayed
+in a specially colored header button at the top of the processed
+part.  Signed parts will have variously colored headers depending
+on the success or failure of the verification process and on the
+validity of user ID of the signer.
+
+The effect of setting this variable can be seen temporarily by
+viewing a signed or encrypted message with M-RET in notmuch
+search."
+  :group 'notmuch
+  :type 'boolean)
+
+(define-button-type 'notmuch-crypto-status-button-type
+  'action '(lambda (button) (message (button-get button 'help-echo)))
+  'follow-link t
+  'help-echo "Set notmuch-crypto-process-mime to process cryptographic mime 
parts."
+  'face '(:foreground "blue")
+  'mouse-face '(:foreground "blue"))
+
+(defun notmuch-crypto-insert-sigstatus-button (sigstatus from)
+  (let* ((status (plist-get sigstatus :status))
+(help-msg nil)
+(label "multipart/signed: signature not processed")
+(face '(:background "red" :foreground "black")))
+(cond
+ ((string= status "good")
+  ; if userid present, userid has full or greater validity
+  (if (plist-member sigstatus :userid)
+ (let ((userid (plist-get sigstatus :userid)))
+   (setq label (concat "Good signature by: " userid))
+   (setq face '(:background "green" :foreground "black")))
+   (let ((fingerprint (concat "0x" (plist-get sigstatus :fingerprint
+ (setq label (concat "Good signature by key: " fingerprint))
+ (setq face '(:background "orange" :foreground "black")
+ ((string= status "error")
+  (let ((keyid (concat "0x" (plist-get sigstatus :keyid
+   (setq label (concat "Unknown key ID " keyid " or unsupported 
algorithm"))
+   (setq face '(:background "red" :foreground "black"
+ ((string= status "bad")
+  (let ((keyid (concat "0x" (plist-get sigstatus :keyid
+   (setq label (concat "Bad signature (claimed key ID " keyid ")"))
+   (setq face '(:background "red" :foreground "black"
+ (t
+  (setq label "Unknown signature status")
+  (if status (setq label (concat label " \"" status "\"")
+(insert-button
+ (concat "[ " label " ]")
+ :type 'notmuch-crypto-status-button-type
+ 'help-echo help-msg
+ 'face face
+ 'mouse-face face
+ :notmuch-sigstatus sigstatus
+ :notmuch-from from)
+(insert 

[PATCH 09/11] Add decryption of PGP/MIME-encrypted parts with --decrypt.

2011-05-25 Thread Jameson Graef Rollins
This adds support for decrypting PGP/MIME-encrypted parts to
notmuch-show and notmuch-reply.  The --decrypt option implies
--verify.  Once decryption (and possibly signature verification) is
done, a new part_encstatus formatter is emitted, the part_sigstatus
formatter is emitted, and the entire multipart/encrypted part is
replaced by the contents of the encrypted part.

At the moment only a json part_encstatus formatting function is
available, even though decryption is done for all formats.  Emacs
support to follow.
---
 notmuch-client.h |2 ++
 notmuch-reply.c  |   36 
 notmuch-show.c   |   25 -
 notmuch.1|   11 +++
 notmuch.c|8 
 show-message.c   |   29 -
 6 files changed, 101 insertions(+), 10 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index dc4ed7a..8a27260 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -67,6 +67,7 @@ typedef struct notmuch_show_format {
 const char *body_start;
 void (*part_start) (GMimeObject *part,
int *part_count);
+void (*part_encstatus) (int status);
 void (*part_sigstatus) (const GMimeSignatureValidity* validity);
 void (*part_content) (GMimeObject *part);
 void (*part_end) (GMimeObject *part);
@@ -82,6 +83,7 @@ typedef struct notmuch_show_params {
 int raw;
 int part;
 GMimeCipherContext* cryptoctx;
+int decrypt;
 } notmuch_show_params_t;

 /* There's no point in continuing when we've detected that we've done
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 99bb15f..5265af6 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -34,6 +34,7 @@ static const notmuch_show_format_t format_reply = {
"",
NULL,
NULL,
+   NULL,
reply_part_content,
NULL,
"",
@@ -438,7 +439,10 @@ guess_from_received_header (notmuch_config_t *config, 
notmuch_message_t *message
 }

 static int
-notmuch_reply_format_default(void *ctx, notmuch_config_t *config, 
notmuch_query_t *query)
+notmuch_reply_format_default(void *ctx,
+notmuch_config_t *config,
+notmuch_query_t *query,
+notmuch_show_params_t *params)
 {
 GMimeMessage *reply;
 notmuch_messages_t *messages;
@@ -446,9 +450,6 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t 
*config, notmuch_query_
 const char *subject, *from_addr = NULL;
 const char *in_reply_to, *orig_references, *references;
 const notmuch_show_format_t *format = _reply;
-notmuch_show_params_t params;
-params.part = -1;
-params.cryptoctx = NULL;

 for (messages = notmuch_query_search_messages (query);
 notmuch_messages_valid (messages);
@@ -508,7 +509,7 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t 
*config, notmuch_query_
notmuch_message_get_header (message, "from"));

show_message_body (notmuch_message_get_filename (message),
-  format, );
+  format, params);

notmuch_message_destroy (message);
 }
@@ -517,7 +518,10 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t 
*config, notmuch_query_

 /* This format is currently tuned for a git send-email --notmuch hook */
 static int
-notmuch_reply_format_headers_only(void *ctx, notmuch_config_t *config, 
notmuch_query_t *query)
+notmuch_reply_format_headers_only(void *ctx,
+ notmuch_config_t *config,
+ notmuch_query_t *query,
+ unused (notmuch_show_params_t *params))
 {
 GMimeMessage *reply;
 notmuch_messages_t *messages;
@@ -579,9 +583,12 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
 notmuch_query_t *query;
 char *opt, *query_string;
 int i, ret = 0;
-int (*reply_format_func)(void *ctx, notmuch_config_t *config, 
notmuch_query_t *query);
+int (*reply_format_func)(void *ctx, notmuch_config_t *config, 
notmuch_query_t *query, notmuch_show_params_t *params);
+notmuch_show_params_t params;

 reply_format_func = notmuch_reply_format_default;
+params.part = -1;
+params.cryptoctx = NULL;

 for (i = 0; i < argc && argv[i][0] == '-'; i++) {
if (strcmp (argv[i], "--") == 0) {
@@ -598,6 +605,16 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
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(notmuch_gmime_session_get_type(), NULL);
+   if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, 
"gpg")))
+   fprintf (stderr, "Failed to construct gpg 

[PATCH 08/11] Add signature verification of PGP/MIME-signed parts with --verify.

2011-05-25 Thread Jameson Graef Rollins
This is primarily for notmuch-show, although the functionality is
added to show-message.  Once signatures are processed a new
part_sigstatus formatter is emitted, and the entire multipart/signed
part is replaced with the contents of the signed part.

At the moment only a json part_sigstatus formatting function is
available.  Emacs support to follow.

The original work for this patch was done by

  Daniel Kahn Gillmor 

whose help with this functionality I greatly appreciate.
---
 Makefile.local  |1 +
 notmuch-client.h|5 ++
 notmuch-gmime-session.c |   49 
 notmuch-reply.c |2 +
 notmuch-show.c  |   96 +++
 notmuch.1   |   11 +
 notmuch.c   |8 
 show-message.c  |   41 +++-
 8 files changed, 212 insertions(+), 1 deletions(-)
 create mode 100644 notmuch-gmime-session.c

diff --git a/Makefile.local b/Makefile.local
index 8a8832d..f726f1f 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -246,6 +246,7 @@ notmuch_client_srcs =   \
notmuch-show.c  \
notmuch-tag.c   \
notmuch-time.c  \
+   notmuch-gmime-session.c \
query-string.c  \
show-message.c  \
json.c  \
diff --git a/notmuch-client.h b/notmuch-client.h
index b278bc7..dc4ed7a 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -67,6 +67,7 @@ typedef struct notmuch_show_format {
 const char *body_start;
 void (*part_start) (GMimeObject *part,
int *part_count);
+void (*part_sigstatus) (const GMimeSignatureValidity* validity);
 void (*part_content) (GMimeObject *part);
 void (*part_end) (GMimeObject *part);
 const char *part_sep;
@@ -80,6 +81,7 @@ typedef struct notmuch_show_params {
 int entire_thread;
 int raw;
 int part;
+GMimeCipherContext* cryptoctx;
 } notmuch_show_params_t;

 /* There's no point in continuing when we've detected that we've done
@@ -233,4 +235,7 @@ notmuch_config_set_maildir_synchronize_flags 
(notmuch_config_t *config,
 notmuch_bool_t
 debugger_is_active (void);

+GType
+notmuch_gmime_session_get_type (void);
+
 #endif
diff --git a/notmuch-gmime-session.c b/notmuch-gmime-session.c
new file mode 100644
index 000..d83d9b3
--- /dev/null
+++ b/notmuch-gmime-session.c
@@ -0,0 +1,49 @@
+#include "notmuch-client.h"
+
+/* CRUFTY BOILERPLATE for GMimeSession (dkg thinks this will go away once 
GMime 2.6 comes out) */
+typedef struct _NotmuchGmimeSession NotmuchGmimeSession;
+typedef struct _NotmuchGmimeSessionClass NotmuchGmimeSessionClass;
+
+struct _NotmuchGmimeSession {
+GMimeSession parent_object;
+};
+
+struct _NotmuchGmimeSessionClass {
+GMimeSessionClass parent_class;
+};
+
+static void notmuch_gmime_session_class_init (NotmuchGmimeSessionClass *klass);
+
+static GMimeSessionClass *parent_class = NULL;
+
+GType
+notmuch_gmime_session_get_type (void)
+{
+static GType type = 0;
+
+if (!type) {
+   static const GTypeInfo info = {
+   sizeof (NotmuchGmimeSessionClass),
+   NULL, /* base_class_init */
+   NULL, /* base_class_finalize */
+   (GClassInitFunc) notmuch_gmime_session_class_init,
+   NULL, /* class_finalize */
+   NULL, /* class_data */
+   sizeof (NotmuchGmimeSession),
+   0,/* n_preallocs */
+   NULL, /* object_init */
+   NULL, /* value_table */
+   };
+   type = g_type_register_static (GMIME_TYPE_SESSION, 
"NotmuchGmimeSession", , 0);
+}
+return type;
+}
+
+static void
+notmuch_gmime_session_class_init (NotmuchGmimeSessionClass *klass)
+{
+GMimeSessionClass *session_class = GMIME_SESSION_CLASS (klass);
+parent_class = g_type_class_ref (GMIME_TYPE_SESSION);
+session_class->request_passwd = NULL;
+}
+/* END CRUFTY BOILERPLATE */
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 9c35475..99bb15f 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -33,6 +33,7 @@ static const notmuch_show_format_t format_reply = {
"", NULL, "",
"",
NULL,
+   NULL,
reply_part_content,
NULL,
"",
@@ -447,6 +448,7 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t 
*config, notmuch_query_
 const notmuch_show_format_t *format = _reply;
 notmuch_show_params_t params;
 params.part = -1;
+params.cryptoctx = NULL;

 for (messages = notmuch_query_search_messages (query);
 notmuch_messages_valid (messages);
diff --git a/notmuch-show.c b/notmuch-show.c
index 363cdbf..bb54e56 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -44,6 +44,7 @@ static const notmuch_show_format_t format_text = {
"\fheader{\n", format_headers_text, "\fheader}\n",
"\fbody{\n",
format_part_start_text,
+   

[PATCH 07/11] test: add crypto tests for signature verification and decryption

2011-05-25 Thread Jameson Graef Rollins
This adds a new "crypto" test script to the test suite to test
PGP/MIME signature verification and message decryption.  Included here
is a test GNUPGHOME with a test secret key (passwordless), and test
for:

  * signing/verification
  * signing/verification with full owner trust
  * verification with signer key unavailable
  * encryption/decryption
  * decryption failure with missing key
  * encryption/decryption + signing/verfifying
  * reply to encrypted message
  * verification of signature from revoked key

These tests are not expected to pass now, but will as crypto
functionality is included.
---
 test/basic |5 +-
 test/crypto|  330 
 test/gnupg-secret-key.NOTE |9 ++
 test/gnupg-secret-key.asc  |   34 +
 test/notmuch-test  |1 +
 test/test-lib.sh   |   29 
 6 files changed, 407 insertions(+), 1 deletions(-)
 create mode 100755 test/crypto
 create mode 100644 test/gnupg-secret-key.NOTE
 create mode 100644 test/gnupg-secret-key.asc

diff --git a/test/basic b/test/basic
index 3b43ad9..d6c0d00 100755
--- a/test/basic
+++ b/test/basic
@@ -57,7 +57,10 @@ available=$(ls -1 ../ | \
 sed -r -e 
"/^(aggregate-results.sh|Makefile|Makefile.local|notmuch-test)/d" \
   -e "/^(README|test-lib.sh|test-results|tmp.*|valgrind|corpus*)/d" \
   -e 
"/^(emacs.expected-output|smtp-dummy|smtp-dummy.c|test-verbose)/d" \
-  -e "/^(test.expected-output|.*~)/d" | sort)
+  -e "/^(test.expected-output|.*~)/d" \
+  -e "/^(gnupg-secret-key.asc)/d" \
+  -e "/^(gnupg-secret-key.NOTE)/d" \
+  | sort)
 test_expect_equal "$tests_in_suite" "$available"

 EXPECTED=../test.expected-output
diff --git a/test/crypto b/test/crypto
new file mode 100755
index 000..3b0f381
--- /dev/null
+++ b/test/crypto
@@ -0,0 +1,330 @@
+#!/bin/bash
+
+# TODO:
+# - decryption/verification with signer key not available
+# - verification of signatures from expired/revoked keys
+
+test_description='PGP/MIME signature verification and decryption'
+. ./test-lib.sh
+
+add_gnupg_home ()
+{
+local output
+[ -d ${GNUPGHOME} ] && return
+mkdir -m 0700 "$GNUPGHOME"
+gpg --no-tty --import <../gnupg-secret-key.asc >"$GNUPGHOME"/import.log 
2>&1
+test_debug "cat $GNUPGHOME/import.log"
+if (gpg --quick-random --version >/dev/null 2>&1) ; then
+   echo quick-random >> "$GNUPGHOME"/gpg.conf
+elif (gpg --debug-quick-random --version >/dev/null 2>&1) ; then
+   echo debug-quick-random >> "$GNUPGHOME"/gpg.conf
+fi
+}
+
+##
+
+add_gnupg_home
+# get key fingerprint
+FINGERPRINT=$(gpg --no-tty --list-secret-keys --with-colons --fingerprint | 
grep '^fpr:' | cut -d: -f10)
+
+# for some reason this is needed for emacs_deliver_message to work,
+# although I can't figure out why
+add_email_corpus
+
+test_expect_success 'emacs delivery of signed message' \
+'emacs_deliver_message \
+"test signed message 001" \
+"This is a test signed message." \
+"(mml-secure-message-sign)"'
+
+test_begin_subtest "signature verification"
+output=$(notmuch show --format=json --verify subject:"test signed message 001" 
\
+| notmuch_json_show_sanitize \
+| sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "X",
+ "match": true,
+ "filename": "Y",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox"],
+ "headers": {"Subject": "test signed message 001",
+ "From": "Notmuch Test Suite ",
+ "To": "test_suite at notmuchmail.org",
+ "Cc": "",
+ "Bcc": "",
+ "Date": "01 Jan 2000 12:00:00 -"},
+ "body": [{"id": 1,
+ "sigstatus": [{"status": "good",
+ "fingerprint": "'$FINGERPRINT'",
+ "created": 946728000}],
+ "content-type": "text/plain",
+ "content": "This is a test signed message.\n"}]},
+ ['
+test_expect_equal \
+"$output" \
+"$expected"
+
+test_begin_subtest "signature verification with full owner trust"
+# give the key full owner trust
+echo "${FINGERPRINT}:6:" | gpg --no-tty --import-ownertrust 
>>"$GNUPGHOME"/trust.log 2>&1
+gpg --no-tty --check-trustdb >>"$GNUPGHOME"/trust.log 2>&1
+output=$(notmuch show --format=json --verify subject:"test signed message 001" 
\
+| notmuch_json_show_sanitize \
+| sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "X",
+ "match": true,
+ "filename": "Y",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox"],
+ "headers": {"Subject": "test signed message 001",
+ "From": "Notmuch Test Suite ",
+ "To": "test_suite at notmuchmail.org",
+ "Cc": "",
+ "Bcc": "",
+ "Date": "01 Jan 2000 12:00:00 -"},
+ "body": [{"id": 1,
+ "sigstatus": [{"status": "good",
+ "fingerprint": "'$FINGERPRINT'",
+ "created": 946728000,
+ "userid": " Notmuch Test Suite  (INSECURE!)"}],
+ "content-type": "text/plain",
+ "content": "This is a test signed message.\n"}]},
+ ['

[PATCH 06/11] test: add notmuch_show_sanitize_all function that is a little more aggressive.

2011-05-25 Thread Jameson Graef Rollins
The old notmuch_show_sanitize function only scrubed part of the
filename.  This one scrubs the full filename, as well as the message
id.
---
 test/test-lib.sh |6 ++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/test/test-lib.sh b/test/test-lib.sh
index 9e2e0b5..ae25635 100755
--- a/test/test-lib.sh
+++ b/test/test-lib.sh
@@ -502,6 +502,12 @@ notmuch_show_sanitize ()
 {
 sed -e "$NOTMUCH_SHOW_FILENAME_SQUELCH"
 }
+notmuch_show_sanitize_all ()
+{
+sed \
+   -e 's| filename:.*| filename:X|' \
+   -e 's| id:[^ ]* | id:X |'
+}

 # End of notmuch helper functions

-- 
1.7.4.4



[PATCH 05/11] test: new test-lib function to test for equality between files

2011-05-25 Thread Jameson Graef Rollins
We need to be able to test for the presence of a newline at the end of
output.  There's no good way to capture trailing newlines in bash, so
redirecting output to a file is the next best thing.  This new
function should be used when testing for output that is expected to
have trailing newlines.

The next commit will demonstrate the use of this.
---
 test/test-lib.sh |   23 +++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/test/test-lib.sh b/test/test-lib.sh
index f536172..9e2e0b5 100755
--- a/test/test-lib.sh
+++ b/test/test-lib.sh
@@ -441,6 +441,29 @@ test_expect_equal ()
 fi
 }

+test_expect_equal_file ()
+{
+   exec 1>&6 2>&7  # Restore stdout and stderr
+   inside_subtest=
+   test "$#" = 3 && { prereq=$1; shift; } || prereq=
+   test "$#" = 2 ||
+   error "bug in the test script: not 2 or 3 parameters to 
test_expect_equal"
+
+   output="$1"
+   expected="$2"
+   if ! test_skip "$@"
+   then
+   if diff -q "$expected" "$output" >/dev/null ; then
+   test_ok_ "$test_subtest_name"
+   else
+   testname=$this_test.$test_count
+   mv "$output" $testname.output
+   mv "$expected" $testname.expected
+   test_failure_ "$test_subtest_name" "$(diff -u 
$testname.expected $testname.output)"
+   fi
+fi
+}
+
 test_expect_equal_failure ()
 {
exec 1>&6 2>&7  # Restore stdout and stderr
-- 
1.7.4.4



[PATCH 04/11] Break up format->part function into part_start and part_content functions.

2011-05-25 Thread Jameson Graef Rollins
Future improvements (eg. crypto support) will require adding new part
header.  By breaking up the output of part headers from the output of
part content, we can easily out new part headers with new formatting
functions.
---
 notmuch-client.h |5 +-
 notmuch-reply.c  |   13 --
 notmuch-show.c   |  122 +++--
 show-message.c   |4 +-
 4 files changed, 85 insertions(+), 59 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index 7221c68..b278bc7 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -65,8 +65,9 @@ typedef struct notmuch_show_format {
notmuch_message_t *message);
 const char *header_end;
 const char *body_start;
-void (*part) (GMimeObject *part,
- int *part_count);
+void (*part_start) (GMimeObject *part,
+   int *part_count);
+void (*part_content) (GMimeObject *part);
 void (*part_end) (GMimeObject *part);
 const char *part_sep;
 const char *body_end;
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 7959935..9c35475 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -25,14 +25,18 @@
 #include "gmime-filter-headers.h"

 static void
-reply_part (GMimeObject *part,
-   unused (int *part_count));
+reply_part_content (GMimeObject *part);

 static const notmuch_show_format_t format_reply = {
 "",
"", NULL,
"", NULL, "",
-   "", reply_part, NULL, "", "",
+   "",
+   NULL,
+   reply_part_content,
+   NULL,
+   "",
+   "",
"", "",
 ""
 };
@@ -57,8 +61,7 @@ show_reply_headers (GMimeMessage *message)
 }

 static void
-reply_part (GMimeObject *part,
-   unused (int *part_count))
+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);
diff --git a/notmuch-show.c b/notmuch-show.c
index 65c780e..363cdbf 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -29,8 +29,11 @@ format_headers_text (const void *ctx,
 notmuch_message_t *message);

 static void
-format_part_text (GMimeObject *part,
- int *part_count);
+format_part_start_text (GMimeObject *part,
+   int *part_count);
+
+static void
+format_part_content_text (GMimeObject *part);

 static void
 format_part_end_text (GMimeObject *part);
@@ -39,7 +42,12 @@ static const notmuch_show_format_t format_text = {
 "",
"\fmessage{ ", format_message_text,
"\fheader{\n", format_headers_text, "\fheader}\n",
-   "\fbody{\n", format_part_text, format_part_end_text, "", 
"\fbody}\n",
+   "\fbody{\n",
+   format_part_start_text,
+   format_part_content_text,
+   format_part_end_text,
+   "",
+   "\fbody}\n",
"\fmessage}\n", "",
 ""
 };
@@ -53,8 +61,11 @@ format_headers_json (const void *ctx,
 notmuch_message_t *message);

 static void
-format_part_json (GMimeObject *part,
- int *part_count);
+format_part_start_json (unused (GMimeObject *part),
+   int *part_count);
+
+static void
+format_part_content_json (GMimeObject *part);

 static void
 format_part_end_json (GMimeObject *part);
@@ -63,7 +74,12 @@ static const notmuch_show_format_t format_json = {
 "[",
"{", format_message_json,
", \"headers\": {", format_headers_json, "}",
-   ", \"body\": [", format_part_json, format_part_end_json, ", ", "]",
+   ", \"body\": [",
+   format_part_start_json,
+   format_part_content_json,
+   format_part_end_json,
+   ", ",
+   "]",
"}", ", ",
 "]"
 };
@@ -77,20 +93,29 @@ static const notmuch_show_format_t format_mbox = {
 "",
 "", format_message_mbox,
 "", NULL, "",
-"", NULL, NULL, "", "",
+"",
+NULL,
+NULL,
+NULL,
+"",
+"",
 "", "",
 ""
 };

 static void
-format_part_raw (GMimeObject *part,
-unused (int *part_count));
+format_part_content_raw (GMimeObject *part);

 static const notmuch_show_format_t format_raw = {
 "",
"", NULL,
"", NULL, "",
-"", format_part_raw, NULL, "", "",
+"",
+NULL,
+format_part_content_raw,
+NULL,
+"",
+"",
"", "",
 ""
 };
@@ -372,46 +397,41 @@ show_part_content (GMimeObject *part, GMimeStream 
*stream_out)
 }

 static void
-format_part_text (GMimeObject *part, int *part_count)
+format_part_start_text (GMimeObject *part, int *part_count)
 {
-GMimeContentDisposition *disposition;
-

[PATCH 03/11] Use empty strings instead of NULL in format_reply structure.

2011-05-25 Thread Jameson Graef Rollins
This keeps things consistent with notmuch-show, and prevents having to
check for the existence of the field pointer for simple string output
formats.
---
 notmuch-reply.c |   12 ++--
 show-message.c  |2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index 8c5e76c..7959935 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -29,12 +29,12 @@ reply_part (GMimeObject *part,
unused (int *part_count));

 static const notmuch_show_format_t format_reply = {
-NULL,
-   NULL, NULL,
-   NULL, NULL, NULL,
-   NULL, reply_part, NULL, NULL, NULL,
-   NULL, NULL,
-NULL
+"",
+   "", NULL,
+   "", NULL, "",
+   "", reply_part, NULL, "", "",
+   "", "",
+""
 };

 static void
diff --git a/show-message.c b/show-message.c
index 2ec9eca..32bb860 100644
--- a/show-message.c
+++ b/show-message.c
@@ -46,7 +46,7 @@ show_message_part (GMimeObject *part,
 selected = (params->part <= 0 || state->part_count == params->part);

 if (selected || state->in_zone) {
-   if (!first && (params->part <= 0 || state->in_zone) && format->part_sep)
+   if (!first && (params->part <= 0 || state->in_zone))
fputs (format->part_sep, stdout);

format->part (part, &(state->part_count));
-- 
1.7.4.4



[PATCH 02/11] Integrate reply_part_content function into reply_part function.

2011-05-25 Thread Jameson Graef Rollins
After the last patch to eliminate some redundant code paths in
reply_part, the reply_part_content function was only being called
once.  Disolving the function and integrating its contents into the
reply_part function makes things a little simpler, and frees up some
name space that will be needed in the next patch.
---
 notmuch-reply.c |   52 +++-
 1 files changed, 23 insertions(+), 29 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index 5d72b1f..8c5e76c 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -38,34 +38,6 @@ static const notmuch_show_format_t format_reply = {
 };

 static void
-reply_part_content (GMimeObject *part)
-{
-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);
-}
-
-static void
 show_reply_headers (GMimeMessage *message)
 {
 GMimeStream *stream_stdout = NULL, *stream_filter = NULL;
@@ -94,7 +66,29 @@ reply_part (GMimeObject *part,
 if (g_mime_content_type_is_type (content_type, "text", "*") &&
!g_mime_content_type_is_type (content_type, "text", "html"))
 {
-   reply_part_content (part);
+   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);
 }
 else
 {
-- 
1.7.4.4



[PATCH 01/11] Simplify reply_part function to eliminate redundant code paths.

2011-05-25 Thread Jameson Graef Rollins
This is the same logic but with less code.
---
 notmuch-reply.c |   41 ++---
 1 files changed, 14 insertions(+), 27 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index ab15650..5d72b1f 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -88,31 +88,8 @@ static void
 reply_part (GMimeObject *part,
unused (int *part_count))
 {
-GMimeContentDisposition *disposition;
-GMimeContentType *content_type;
-
-disposition = g_mime_object_get_content_disposition (part);
-if (disposition &&
-   strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0)
-{
-   const char *filename = g_mime_part_get_filename (GMIME_PART (part));
-   content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
-
-   if (g_mime_content_type_is_type (content_type, "text", "*") &&
-   !g_mime_content_type_is_type (content_type, "text", "html"))
-   {
-   reply_part_content (part);
-   }
-   else
-   {
-   printf ("Attachment: %s (%s)\n", filename,
-   g_mime_content_type_to_string (content_type));
-   }
-
-   return;
-}
-
-content_type = g_mime_object_get_content_type (GMIME_OBJECT (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", "*") &&
!g_mime_content_type_is_type (content_type, "text", "html"))
@@ -121,8 +98,18 @@ reply_part (GMimeObject *part,
 }
 else
 {
-   printf ("Non-text part: %s\n",
-   g_mime_content_type_to_string (content_type));
+   if (disposition &&
+   strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 
0)
+   {
+   const char *filename = g_mime_part_get_filename (GMIME_PART (part));
+   printf ("Attachment: %s (%s)\n", filename,
+   g_mime_content_type_to_string (content_type));
+   }
+   else
+   {
+   printf ("Non-text part: %s\n",
+   g_mime_content_type_to_string (content_type));
+   }
 }
 }

-- 
1.7.4.4



New crypto patch series

2011-05-25 Thread Jameson Graef Rollins
Hi, folks.  This is a series of patches that constitute a complete
rework of notmuch crypto support (signature verification and
decryption of PGP/MIME messages, with emacs ui support), including
some relevant preparatory patches, on top of the notmuch/master branch
at b6862c7eb9bfb00183e568b40d77ea25ade21db2.  This work is also
available on the "new-crypto" branch of my notmuch repo:

git://finestructure.net/notmuch [new-crypto]
aa41285c5f75f8ea30d4582f6b8e1aa306f1632c

It's sounding unlikely that Carl will accept this work in to master
any time soon, due to concerns he has about how the crypto processing
affects part numbering (a concern that I think is pretty minor, and
really don't affect the usability of the new functionality, fwiw).  In
the mean time, I wanted to get these patches out there, for those of
us that depend on this functionality.

jamie.



[PATCH 3/5] Fix hiding a message while some citations are shown in notmuch-show view.

2011-05-25 Thread Carl Worth
On Thu, 26 May 2011 02:10:14 +0400, Dmitry Kurochkin  wrote:
> Before the change, message and citation invisibility overlays
> conflicted: if some citation is made visible and then the whole
> message is hidden, that citation remained visible.

That sounds like quite a bug. I'd love to see this series also add a
test case for that.

-Carl

-- 
carl.d.worth at intel.com
-- 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/20110525/51a2c0fc/attachment.pgp>


[PATCH 4/4] emacs: Allow the user to choose the "From" address when replying to a message.

2011-05-25 Thread Thomas Jost
---
 emacs/notmuch-mua.el  |9 -
 emacs/notmuch-show.el |6 ++
 emacs/notmuch.el  |7 +++
 3 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 7c08a6e..d04e69c 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -69,7 +69,7 @@ list."
(push header message-hidden-headers)))
notmuch-mua-hidden-headers))

-(defun notmuch-mua-reply (query-string)
+(defun notmuch-mua-reply (query-string  sender)
   (let (headers
body
(args '("reply")))
@@ -90,6 +90,9 @@ list."
  (setq headers (mail-header-extract)
   (forward-line 1)
   (setq body (buffer-substring (point) (point-max
+;; If sender is non-nil, set the From: header to its value.
+(when sender
+  (mail-header-set 'from sender headers))
 (let
;; Overlay the composition window on that being used to read
;; the original message.
@@ -190,6 +193,10 @@ name and addresses configured in the notmuch configuration 
file."
 (user-mail-address (cadr address-components)))
 (notmuch-mua-forward-message)))

+(defun notmuch-mua-reply-prompt-for-sender (query-string)
+  (interactive)
+  (notmuch-mua-reply query-string (notmuch-mua-prompt-for-sender)))
+
 (defun notmuch-mua-send-and-exit ( arg)
   (interactive "P")
   (message-send-and-exit arg))
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 50b20b2..2c69e96 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -852,6 +852,7 @@ function is used. "
(define-key map "f" 'notmuch-show-forward-message)
(define-key map "F" 'notmuch-show-forward-message-prompt-for-sender)
(define-key map "r" 'notmuch-show-reply)
+   (define-key map "R" 'notmuch-show-reply-prompt-for-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)
@@ -1160,6 +1161,11 @@ any effects from previous calls to
   (interactive)
   (notmuch-mua-reply (notmuch-show-get-message-id)))

+(defun notmuch-show-reply-prompt-for-sender ()
+  "Reply to the current message, prompting for the From: address first."
+  (interactive)
+  (notmuch-mua-reply-prompt-for-sender (notmuch-show-get-message-id)))
+
 (defun notmuch-show-forward-message ()
   "Forward the current message."
   (interactive)
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 1791d84..153dc74 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -204,6 +204,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-prompt-for-sender)
 (define-key map "m" 'notmuch-mua-new-mail)
 (define-key map "M" 'notmuch-mua-new-mail-prompt-for-sender)
 (define-key map "s" 'notmuch-search)
@@ -449,6 +450,12 @@ Complete list of currently available key bindings:
   (let ((message-id (notmuch-search-find-thread-id)))
 (notmuch-mua-reply message-id)))

+(defun notmuch-search-reply-to-thread-prompt-for-sender ()
+  "Begin composing a reply to the entire current thread in a new buffer, 
prompting for the From: address first."
+  (interactive)
+  (let ((message-id (notmuch-search-find-thread-id)))
+(notmuch-mua-reply-prompt-for-sender message-id)))
+
 (defun notmuch-call-notmuch-process ( args)
   "Synchronously invoke \"notmuch\" with the given list of arguments.

-- 
1.7.5.1



[PATCH 3/4] emacs: Allow the user to choose the "From" address when forwarding a message.

2011-05-25 Thread Thomas Jost
---
 emacs/notmuch-mua.el  |8 
 emacs/notmuch-show.el |7 +++
 2 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 0bde02c..7c08a6e 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -182,6 +182,14 @@ name and addresses configured in the notmuch configuration 
file."
   (interactive)
   (notmuch-mua-new-mail t))

+(defun notmuch-mua-forward-message-prompt-for-sender ()
+  (interactive)
+  (let* ((sender (notmuch-mua-prompt-for-sender))
+(address-components (mail-extract-address-components sender))
+(user-full-name (car address-components))
+(user-mail-address (cadr address-components)))
+(notmuch-mua-forward-message)))
+
 (defun notmuch-mua-send-and-exit ( arg)
   (interactive "P")
   (message-send-and-exit arg))
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 93f46ac..50b20b2 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -850,6 +850,7 @@ function is used. "
(define-key map "m" 'notmuch-mua-new-mail)
(define-key map "M" 'notmuch-mua-new-mail-prompt-for-sender)
(define-key map "f" 'notmuch-show-forward-message)
+   (define-key map "F" 'notmuch-show-forward-message-prompt-for-sender)
(define-key map "r" 'notmuch-show-reply)
(define-key map "|" 'notmuch-show-pipe-message)
(define-key map "w" 'notmuch-show-save-attachments)
@@ -1165,6 +1166,12 @@ any effects from previous calls to
   (with-current-notmuch-show-message
(notmuch-mua-forward-message)))

+(defun notmuch-show-forward-message-prompt-for-sender ()
+  "Forward the current message, prompting for the From: address first."
+  (interactive)
+  (with-current-notmuch-show-message
+   (notmuch-mua-forward-message-prompt-for-sender)))
+
 (defun notmuch-show-next-message ()
   "Show the next message."
   (interactive)
-- 
1.7.5.1



[PATCH 2/4] emacs: Move the "prompt for sender" code to a new function.

2011-05-25 Thread Thomas Jost
This allows the code to be reused in different functions without duplicating it.
---
 emacs/notmuch-mua.el |   15 +--
 1 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index cd4d75d..0bde02c 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -157,21 +157,24 @@ name and addresses configured in the notmuch 
configuration file."
  (concat (notmuch-user-name) " <" address ">"))
(cons (notmuch-user-primary-email) (notmuch-user-other-email)

+(defvar notmuch-mua-sender-history nil)
+
+(defun notmuch-mua-prompt-for-sender ()
+  (interactive)
+  (let ((collection (notmuch-mua-sender-collection)))
+(ido-completing-read "Send mail From: " collection
+nil 'confirm nil 'notmuch-mua-sender-history (car 
collection
+
 (defun notmuch-mua-new-mail-from ( sender)
   (if sender
   (notmuch-mua-mail nil nil (list (cons 'from sender)))
 (notmuch-mua-mail)))

-(defvar notmuch-mua-sender-history nil)
-
 (defun notmuch-mua-new-mail ( prompt-for-sender)
   "Begin composing a new email with notmuch."
   (interactive "P")
   (if prompt-for-sender
-  (let* ((collection (notmuch-mua-sender-collection))
-(sender (ido-completing-read "Send mail From: " collection
- nil 'confirm nil 
'notmuch-mua-sender-history (car collection
-   (notmuch-mua-new-mail-from sender))
+  (notmuch-mua-new-mail-from (notmuch-mua-prompt-for-sender))
 (notmuch-mua-mail)))

 (defun notmuch-mua-new-mail-prompt-for-sender ()
-- 
1.7.5.1



[PATCH 1/4] emacs: Allow the user choose the "From" address when composing a new message from notmuch-show-mode too.

2011-05-25 Thread Thomas Jost
---
 emacs/notmuch-show.el |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 825988c..93f46ac 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -847,7 +847,8 @@ function is used. "
(define-key map (kbd "") 'notmuch-show-previous-button)
(define-key map (kbd "TAB") 'notmuch-show-next-button)
(define-key map "s" 'notmuch-search)
-   (define-key map "m" 'notmuch-mua-mail)
+   (define-key map "m" 'notmuch-mua-new-mail)
+   (define-key map "M" 'notmuch-mua-new-mail-prompt-for-sender)
(define-key map "f" 'notmuch-show-forward-message)
(define-key map "r" 'notmuch-show-reply)
(define-key map "|" 'notmuch-show-pipe-message)
-- 
1.7.5.1



[PATCH] emacs: Allow user to choose "From" address when composing a new message.

2011-05-25 Thread Thomas Jost
On Tue, 24 May 2011 15:02:01 -0700, Carl Worth  wrote:
> In order to select a From address, the user simply presses M instead of
> m to begin composing a message. By default the list of names/addresses
> to be used during completion will be automatically generated by the
> settings in the notmuch configuration file. The user can customize
> the notmuch-identities variable to provide an alternate list.

Thanks, IMHO that's better than my previous solution. And it makes my
.emacs smaller, woohoo! :)

One little issue though: you did not update notmuch-show-mode-map in
notmuch-show.el. I'll reply with a patch that fixes that (or you can
just integrate it in your commit when pushing it).

I'll also send a few additional patches that make it possible to choose
the "From" address when forwarding a message and when replying to a
message.

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/20110525/65a0e32e/attachment.pgp>


[PATCH] emacs: Allow user to choose "From" address when composing a new message.

2011-05-25 Thread Carl Worth
On Wed, 25 May 2011 15:21:06 +0200, Thomas Jost  
wrote:
> Thanks, IMHO that's better than my previous solution. And it makes my
> .emacs smaller, woohoo! :)

Thanks for the review.

> One little issue though: you did not update notmuch-show-mode-map in
> notmuch-show.el. I'll reply with a patch that fixes that (or you can
> just integrate it in your commit when pushing it).

Good catch.

> I'll also send a few additional patches that make it possible to choose
> the "From" address when forwarding a message and when replying to a
> message.

The only real concern I have with the series is that it grabs 'R' for
reply-with-custom-from where I've been planning to implement 'R' as
reply-to-sender-only, (a long-missing and often-requested feature).

When I first started implementing the custom-from feature I planned to
use a prefix argument to get the behavior (such as "C-u m" rather than
"M" for compose-new-mail-with-custom-from). You might even see I've got
some code written along those lines.

When I went to test it though, it didn't work. That was probably some
silly mistake on my part, (we do already have working code that changes
behavior with a prefix argument in the case of "M-RET" for example).

If you want to update the series to move away from capital-letter
keybindings in favor of a prefix argument, I'll be glad to accept it.

Otherwise, I might get around to doing that myself at some point.

Thanks again,

-Carl

-- 
carl.d.worth at intel.com
-- 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/20110525/986943a8/attachment.pgp>


[PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Austin Clements
On Wed, May 25, 2011 at 1:56 PM, Daniel Schoepe
 wrote:
> I accidentally used `filter' in the previous patch which isn't defined
> by default during runtime, updated version in the attachment.

Cool.  My inner parser is happy.

A few comments on the code:

> +(defcustom notmuch-hello-tag-list-make-query nil
> +  "Function or string to generate queries for the all tags list.
> +
> +This variable controls which query results are shown for each tag
> +in the \"all tags\" list. It can be nil (for default behaviour,
> +displaying all messages for a tag), a string that is used as a
> +filter for messages having that tag (equivalent to \"tag:TAG
> +and (THIS-VARIABLE)\", or a function that is given a tag and
> +should return the query that is to be used for the tag. If it
> +returns nil, the corresponding tag will be hidden."
> +  :type '(choice (const nil :tag "tag:TAG") string function)
> +  :group 'notmuch)

At least in Emacs 23.3.1, it has to be (const :tag "tag:TAG" nil).  I
didn't think the order mattered, but the tag didn't display otherwise.
 It would also be good to give descriptive tags to the other choices.

It would be more consistent if the function form of this also returned
a filter expression, rather than a whole expression.  This also
simplifies the documentation.

So, perhaps something like

(defcustom notmuch-hello-tag-list-counts nil
  "Method for generating counts displayed in the all tags list.

This variable controls the query used to generate counts for each
tag in the \"all tags\" list.  If nil, the tag list will count
all messages with each tag.  This can be a query string that will
filter the messages counted for each tag.  Finally, this can be a
function that will be called for each tag and should return a
filter query for that tag, or nil to hide the tag."
  :type '(choice (const :tag "Count all messages" nil)
 (const :tag "Count unread messages" "tag:unread")
 (const :tag "Custom filter" string)
 (const :tag "Custom filter function" function))
  :group 'notmuch)

> +(defun notmuch-hello-generate-tag-alist ()
> +  "Return an alist from tags to queries to display in the all-tags section."
> +  (notmuch-filter
> +   'cdr
> +   (mapcar '(lambda (tag)

You don't need the quote before a lambda form.  (You can also change
'cdr to #'cdr to further hint the compiler, though it appears to not
matter in this case.)

> +(defun notmuch-filter (pred lst)
> +  "Return a list containing all elements from LST that satisfy PRED."

notmuch-remove-if-not would be more canonical (yeah, it's unwieldy,
blame Common Lisp).  Also, since Elisp doesn't do tail-recursion, the
standard way to define a remove-if-not function is

(defun notmuch-remove-if-not (predicate list)
  "Return a copy of LIST with all items not satisfying PREDICATE removed."
  (let (out)
(while list
  (when (funcall predicate (car list))
(push (car list) out))
  (setq list (cdr list)))
(nreverse out)))

(Why oh why Elisp hasn't just made remove-if and remove-if-not
standard I don't know; they're redefined all over the Elisp code base.
 Any everybody's afraid to use cl-seq's remove-if-not because it's so
ridiculously complicated.)


[PATCH] Change in increment_mtime for BSD compatibility of test suite

2011-05-25 Thread Felix Geller
Use `-t' option rather than `-d' which is not supported by BSD's
touch. I'm not sure whether this is the cleanest way to do this, please
let me know if there is a better way. There are additional changes
(e.g., sed does not support `-r' but instead `-E') but they seem to be
incompatible between GNU and BSD. What's the recommended way to handle
this?

Cheers,
Felix


diff --git a/test/test-lib.sh b/test/test-lib.sh
index f536172..d2af857 100755
--- a/test/test-lib.sh
+++ b/test/test-lib.sh
@@ -218,9 +218,10 @@ increment_mtime_amount=0
 increment_mtime ()
 {
 dir="$1"
-
+last_mod_date=`date -j -f %Y%m%d%H%M%S \`stat -f %Sm -t %Y%m%d%H%M%S 
${dir}\` +%s`
 increment_mtime_amount=$((increment_mtime_amount + 1))
-touch -d "+${increment_mtime_amount} seconds" "$dir"
+new_date=`date -j -r ${last_mod_date} -v+${increment_mtime_amount}S 
+%Y%m%d%H%M.%S`
+touch -t ${new_date} ${dir}
 }

 # Generate a new message in the mail directory, with a unique message
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 202 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20110525/3c4d9478/attachment.pgp>


[PATCH] fixed return value check of sysoncf in get_name_from_passwd_file / get_username_from_passwd_file

2011-05-25 Thread Matthias Guedemann

When trying to port notmuch to DragonFlyBSD I found it core dumped
immediately. The reason was that the "sysconf(_SC_GETPW_R_SIZE_MAX)"
call returned -1 which is used for talloc memory allocation. The check
was there but was done _after_ the allocation, the attached patch fixes
this.

regards
Matthias


diff --git a/notmuch-config.c b/notmuch-config.c
index d86c042..6e4c5c4 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -109,13 +109,15 @@ notmuch_config_destructor (notmuch_config_t *config)
 static char *
 get_name_from_passwd_file (void *ctx)
 {
-long pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
-char *pw_buf = talloc_zero_size (ctx, pw_buf_size);
+long pw_buf_size;
+char *pw_buf;
 struct passwd passwd, *ignored;
 char *name;
 int e;

+pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
 if (pw_buf_size == -1) pw_buf_size = 64;
+pw_buf = talloc_size (ctx, pw_buf_size);

 while ((e = getpwuid_r (getuid (), , pw_buf,
 pw_buf_size, )) == ERANGE) {
@@ -142,13 +144,16 @@ get_name_from_passwd_file (void *ctx)
 static char *
 get_username_from_passwd_file (void *ctx)
 {
-long pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
-char *pw_buf = talloc_zero_size (ctx, pw_buf_size);
+long pw_buf_size;
+char *pw_buf;
 struct passwd passwd, *ignored;
 char *name;
 int e;

+pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
 if (pw_buf_size == -1) pw_buf_size = 64;
+pw_buf = talloc_zero_size (ctx, pw_buf_size);
+
 while ((e = getpwuid_r (getuid (), , pw_buf,
 pw_buf_size, )) == ERANGE) {
 pw_buf_size = pw_buf_size * 2;


[PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Daniel Schoepe
On Wed, 25 May 2011 00:10:43 -0400, Austin Clements  wrote:
> Out of curiosity, what use cases do you envision for this?  So far
> I've only heard two, both of which seem like great ideas, but neither
> of which require such a heavy-handed solution: displaying unread
> counts for tags rather than total counts, and hiding unused tags.

Another thing I use this for, is to hide messages/threads with a
"killed"-tag.

Anyway, I don't think this solution is very "heavy-handed", since it
doesn't add any significant complexity to the UI code and for people who
know elisp, writing such a query-construction function is not something
"heavy-weight" either, so I don't think giving up the extra flexibility
is really worth it.

The only problem I see is what Carl Worth mentioned: Users unaccustomed
to elisp can't do much with this configuration variable.

> I would argue that we *always* want to display unread counts (maybe in
> addition to total counts, or maybe not).  In fact, I'm generally
> surprised by how little notmuch treats the "unread" specially, given
> how important that tag is to the user.  For example, I would similarly
> find unread counts in the search results far more useful than the
> count of messages matching the query.

I think most users would agree with this, but I still think we
should keep/make it configurable.

> Hiding unused tags also seems like a genuinely useful feature, and
> could be accomplished with a very simple customization UI (perhaps
> even linked directly from the hello buffer).
> 
> It seems to me like anything more sophisticated is better suited to a
> saved search.

I think a sensible compromise would be to allow either a function or a
string that is appended (which people could set to "and tag:unread") for
the proposed configuration variable and additionally to add a
variable that lists tags that should be hidden (which would also be
easily modifiable in M-x customize).

Cheers,
Daniel
-- 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/20110525/f1d8d2dc/attachment.pgp>


[PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Austin Clements
On Wed, May 25, 2011 at 6:04 AM, Daniel Schoepe
 wrote:
> On Wed, 25 May 2011 00:10:43 -0400, Austin Clements  
> wrote:
>> Out of curiosity, what use cases do you envision for this? ?So far
>> I've only heard two, both of which seem like great ideas, but neither
>> of which require such a heavy-handed solution: displaying unread
>> counts for tags rather than total counts, and hiding unused tags.
>
> Another thing I use this for, is to hide messages/threads with a
> "killed"-tag.

Ah, interesting.

> I think a sensible compromise would be to allow either a function or a
> string that is appended (which people could set to "and tag:unread") for
> the proposed configuration variable and additionally to add a
> variable that lists tags that should be hidden (which would also be
> easily modifiable in M-x customize).

In principle, I completely agree, but the little parser in my head
screams "parse error!  parse error!" when I feed it "and tag:unread"
and that bothers me.

May I suggest a slightly different way of looking at this that will
quell my inner parser?  Instead of configuring a weird "query
fragment" like "and tag:unread" to be string-concatenated with the tag
query, configure a *filter* query like merely "tag:unread" that
narrows down what you'd like to be counted within the scope of a tag.
The implementations are hardly different---simply generate the query
"tag: and (  )"---but a filter is a well-formed query,
not some string fragment.  Furthermore, the user can't get bitten by
precedence and wind up with a query that counts messages that don't
even have that tag.


[PATCH] Save and restore point explicitly in `notmuch-wash-toggle-invisible-action'.

2011-05-25 Thread Dmitry Kurochkin
On Tue, 24 May 2011 16:20:34 -0700, Carl Worth  wrote:
> On Tue, 24 May 2011 18:43:41 -0400, Austin Clements  
> wrote:
> > Saving point this way is a bit dangerous, though.  For example, if
> > you're near the end of the buffer and shorten the label, attempting to
> > restore the point could result in an error (or, a more benign example:
> > the cursor could wind up outside the label so pressing RET repeatedly
> > won't toggle it).
> > 
> > Unfortunately, I don't know of a clean solution to this, but I think I
> > would rather the cursor move, but stay within the label (probably
> > moving to the beginning), than have problems like the above.
> 
> Here's my fix. Let me know what you think.
> 

(button-end cite-button) would move the point outside the button - to
the next character after it.

Regards,
  Dmitry

> -Carl
> 
> From a32e02bf0d2b57d51695f7d4ea6cdda9acb21322 Mon Sep 17 00:00:00 2001
> From: Carl Worth 
> Date: Mon, 23 May 2011 19:29:46 +0400
> Subject: [PATCH] Carefully preverse point when changing button text in
>  `notmuch-wash-toggle-invisible-action'.
> 
> Previously, save-excursion was used to attempt to save the point, but
> this was unreliable since the region containing the marker saved by
> save-excursion was deleted. Instead, we save an integer position
> indicating the offset of point within the old button. Then, we restore
> point to the same offset within the new button, (but cap the offset to
> avoid leaving the button entirely).
> ---
>  emacs/notmuch-wash.el |   13 +++--
>  1 files changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el
> index 8455eee..3dceb8b 100644
> --- a/emacs/notmuch-wash.el
> +++ b/emacs/notmuch-wash.el
> @@ -82,13 +82,14 @@ collapse the remaining lines into a button.")
>(let* ((new-start (button-start cite-button))
>(overlay (button-get cite-button 'overlay))
>(button-label (notmuch-wash-button-label overlay))
> +  (button-offset (- (point) new-start))
>(inhibit-read-only t))
> -(save-excursion
> -  (goto-char new-start)
> -  (insert button-label)
> -  (let ((old-end (button-end cite-button)))
> - (move-overlay cite-button new-start (point))
> - (delete-region (point) old-end
> +(goto-char new-start)
> +(insert button-label)
> +(let ((old-end (button-end cite-button)))
> +  (move-overlay cite-button new-start (point))
> +  (delete-region (point) old-end))
> +(goto-char (min (button-end cite-button) (+ new-start button-offset
>(force-window-update)
>(redisplay t))
>  
> -- 
> 1.7.5.1
> 
Non-text part: application/pgp-signature


[PATCH] Save and restore point explicitly in `notmuch-wash-toggle-invisible-action'.

2011-05-25 Thread Dmitry Kurochkin
Before the change, save-excursion was used to save the point.
But the restored position is affected by buffer modifications,
which results in jumping cursor.  The patch saves and restores
point explicitly by using a variable instead of save-excursion.
---
 emacs/notmuch-wash.el |   13 +++--
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el
index 863459e..115c3bb 100644
--- a/emacs/notmuch-wash.el
+++ b/emacs/notmuch-wash.el
@@ -82,13 +82,14 @@ collapse the remaining lines into a button.")
   (let* ((new-start (button-start cite-button))
 (overlay (button-get cite-button 'overlay))
 (button-label (notmuch-wash-button-label overlay))
+(old-point (point))
 (inhibit-read-only t))
-(save-excursion
-  (goto-char new-start)
-  (insert button-label)
-  (let ((old-end (button-end cite-button)))
-   (move-overlay cite-button new-start (point))
-   (delete-region (point) old-end
+(goto-char new-start)
+(insert button-label)
+(let ((old-end (button-end cite-button)))
+  (move-overlay cite-button new-start (point))
+  (delete-region (point) old-end))
+(goto-char (min old-point (1- (button-end cite-button)
   (force-window-update)
   (redisplay t))

-- 
1.7.5.1



[PATCH] Save and restore point explicitly in `notmuch-wash-toggle-invisible-action'.

2011-05-25 Thread Dmitry Kurochkin
On Tue, 24 May 2011 18:43:41 -0400, Austin Clements  wrote:
> On Tue, May 24, 2011 at 6:16 PM, Dmitry Kurochkin
>  wrote:
> > When a user clicks the button, the cursor is somewhere inside the old
> > label. ?If we save the point as a marker, after step 3 it would end up
> > at the position where the old label was. ?If the new label is inserted
> > before the old one, that means after the new label. ?So the cursor jumps
> > from inside the button to the position after the button. ?Since the new
> > button is placed at the same position where the old one was, restoring
> > the point to the same offset it was at the beginning works as we need.
> 
> Saving point this way is a bit dangerous, though.  For example, if
> you're near the end of the buffer and shorten the label, attempting to
> restore the point could result in an error (or, a more benign example:
> the cursor could wind up outside the label so pressing RET repeatedly
> won't toggle it).
> 
> Unfortunately, I don't know of a clean solution to this, but I think I
> would rather the cursor move, but stay within the label (probably
> moving to the beginning), than have problems like the above.

Good point.  I will send an amended patch that moved to min(old-pos,
new-button-end - 1).  This leaves the cursor in place when possible and
avoids problems with out-of-bounds position (assuming the label is not
empty).

Regards,
  Dmitry


[PATCH] Save and restore point explicitly in `notmuch-wash-toggle-invisible-action'.

2011-05-25 Thread Dmitry Kurochkin
On Tue, 24 May 2011 15:01:04 -0700, Carl Worth  wrote:
> On Wed, 25 May 2011 00:43:20 +0400, Dmitry Kurochkin  gmail.com> wrote:
> > Now, looking at Emacs source code, save_excursion_save() uses
> > point_marker() to save the point.  As you said above, markers are
> > updated when the corresponding text is updated.  That explains why the
> > cursor jumps when using `save-excursion'.
> > 
> > On the other hand, `point' returns position as an integer.  Which is
> > just what we need.
> 
> Ah. So that explains why your patch is actually making a difference.
> 
> But I've usually had "jumping cursor" problems when using an integer,
> (and switching to a marker fixes it). For example, imagine the following
> operation:
> 
>   User positions cursor on some word
>   Our code saves point as an integer
>   Some operation inserts new text before point
>   Our code restores the cursor to the saved integer
> 
> This sequence restores point to the same integer position in the buffer,
> but logically makes the cursor appear to "jump" to the user, (since the
> cursor will no longer be on the word it was on before but will now be
> earlier in the buffer).
> 
> The fix for the above is to switch from an integer to a marker.
> 

Ah, I see now.

> So I'm curious to know the case you're hitting where you getbetter
> behavior by switching from a marker to an integer. Can you describe it
> in a bit more detail?
> 

I did not find a better way to update the button label than to:

1. insert the new label
2. move the button overlay from the old label to the new one
3. remove the old label

When a user clicks the button, the cursor is somewhere inside the old
label.  If we save the point as a marker, after step 3 it would end up
at the position where the old label was.  If the new label is inserted
before the old one, that means after the new label.  So the cursor jumps
from inside the button to the position after the button.  Since the new
button is placed at the same position where the old one was, restoring
the point to the same offset it was at the beginning works as we need.

Regards,
  Dmitry

> -Carl
Non-text part: application/pgp-signature


[PATCH] Save and restore point explicitly in `notmuch-wash-toggle-invisible-action'.

2011-05-25 Thread Dmitry Kurochkin
Hi Carl.

On Tue, 24 May 2011 13:20:56 -0700, Carl Worth  wrote:
> On Mon, 23 May 2011 19:29:46 +0400, Dmitry Kurochkin  gmail.com> wrote:
> > Before the change, save-excursion was used to save the point.
> > But the restored position is affected by buffer modifications,
> > which results in jumping cursor.  The patch saves and restores
> > point explicitly by using a variable instead of save-excursion.
> 
> Dmitry,
> 
> Thanks so much for the improvement to the button text! This will be a
> nice thing to add.
> 
> But this patch confuses me. I can understand how a buffer-position
> variable can cause the cursor to jump. That's usually the kind of thing
> that can be fixed by switching from an integer position to a marker
> instead, (since markers are updated when the corresponding text is
> updated).
> 

So we need to switch from marker to an integer position, right?

> But in this case, I don't see how:
> 
>   (let ((old-point (point)))
>   ... code here ...
> (goto-char old-point))
> 
> is distinct from:
> 
>   (save-excursion
>   ... code here ...
>)
> 
> except that save-excursion actually does the right thing in the case of
> abnormal exit (throw or error).
> 
> Can you help me understand what I'm missing here?
> 

Unfortunately, I am not an Emacs lisp expert.  I just noticed that the
cursor jumps and did the first thing that came to mind.  And it worked.

Now, looking at Emacs source code, save_excursion_save() uses
point_marker() to save the point.  As you said above, markers are
updated when the corresponding text is updated.  That explains why the
cursor jumps when using `save-excursion'.

On the other hand, `point' returns position as an integer.  Which is
just what we need.

Regards,
  Dmitry

> -Carl
> 
> -- 
> carl.d.worth at intel.com
Non-text part: application/pgp-signature


[PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Austin Clements
Out of curiosity, what use cases do you envision for this?  So far
I've only heard two, both of which seem like great ideas, but neither
of which require such a heavy-handed solution: displaying unread
counts for tags rather than total counts, and hiding unused tags.

I would argue that we *always* want to display unread counts (maybe in
addition to total counts, or maybe not).  In fact, I'm generally
surprised by how little notmuch treats the "unread" specially, given
how important that tag is to the user.  For example, I would similarly
find unread counts in the search results far more useful than the
count of messages matching the query.

Hiding unused tags also seems like a genuinely useful feature, and
could be accomplished with a very simple customization UI (perhaps
even linked directly from the hello buffer).

It seems to me like anything more sophisticated is better suited to a
saved search.

On Thu, May 19, 2011 at 7:18 PM, Daniel Schoepe
 wrote:
>
> From the commit message:
>
> ? ?emacs: Make queries used in the all-tags section configurable
>
> ? ?This patch adds a customization variable that controls what queries
> ? ?are used to construct the all-tags section in notmuch-hello. It allows
> ? ?the user to specify a function to construct the query given a tag. It
> ? ?also allows hiding tags by returning nil.
>
> Possible uses would be things like displaying the unread count for
> tags instead of all messages with that tag and/or hiding uninteresting
> tags like "signed" or "encrypted".
>
> -- Daniel


[PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Daniel Schoepe
On Tue, 24 May 2011 13:39:44 -0700, Carl Worth  wrote:
> This seems like a useful feature, but perhaps it's a little too general?
> 
> I'm imagining a user wanting to use this functionality but not knowing
> anything about writing an emacs-lisp function. For such a user, this
> variable won't provide much of a feature.
>
> I think that might be an argument for dropping this variable from the
> notmuch customization group. That customization page is starting to get
> crowded, and if there are things there that can't be easily manipulated
> with the available controls, I think they're mostly just clutter.
> 
> Perhaps this could be addressed by allowing this variable to be an alist
> instead of (or in addition to) a function. What do you think?

Yes, allowing both, an alist or a function for this variable seems
better than forcing the user to write a function, but how should the
alist control the behaviour? I don't think people would like having to
specify a query for each of their tags, and since, by assumption, they
cannot write a function to automate this, they probably wouldn't be much
better off.  (Except of course, if they only wanted to change it for a
few individual tags).

Another option would be to also allow various symbols like 'unread (meaning
"tag:TAG and tag:unread") for "popular" queries in addition to a function.

Cheers,
Daniel
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 



Re: [PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Daniel Schoepe
On Wed, 25 May 2011 00:10:43 -0400, Austin Clements amdra...@mit.edu wrote:
 Out of curiosity, what use cases do you envision for this?  So far
 I've only heard two, both of which seem like great ideas, but neither
 of which require such a heavy-handed solution: displaying unread
 counts for tags rather than total counts, and hiding unused tags.

Another thing I use this for, is to hide messages/threads with a
killed-tag.

Anyway, I don't think this solution is very heavy-handed, since it
doesn't add any significant complexity to the UI code and for people who
know elisp, writing such a query-construction function is not something
heavy-weight either, so I don't think giving up the extra flexibility
is really worth it.

The only problem I see is what Carl Worth mentioned: Users unaccustomed
to elisp can't do much with this configuration variable.

 I would argue that we *always* want to display unread counts (maybe in
 addition to total counts, or maybe not).  In fact, I'm generally
 surprised by how little notmuch treats the unread specially, given
 how important that tag is to the user.  For example, I would similarly
 find unread counts in the search results far more useful than the
 count of messages matching the query.

I think most users would agree with this, but I still think we
should keep/make it configurable.

 Hiding unused tags also seems like a genuinely useful feature, and
 could be accomplished with a very simple customization UI (perhaps
 even linked directly from the hello buffer).
 
 It seems to me like anything more sophisticated is better suited to a
 saved search.

I think a sensible compromise would be to allow either a function or a
string that is appended (which people could set to and tag:unread) for
the proposed configuration variable and additionally to add a
variable that lists tags that should be hidden (which would also be
easily modifiable in M-x customize).

Cheers,
Daniel


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


[PATCH] fixed return value check of sysoncf in get_name_from_passwd_file / get_username_from_passwd_file

2011-05-25 Thread Matthias Guedemann

When trying to port notmuch to DragonFlyBSD I found it core dumped
immediately. The reason was that the sysconf(_SC_GETPW_R_SIZE_MAX)
call returned -1 which is used for talloc memory allocation. The check
was there but was done _after_ the allocation, the attached patch fixes
this.

regards
Matthias


diff --git a/notmuch-config.c b/notmuch-config.c
index d86c042..6e4c5c4 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -109,13 +109,15 @@ notmuch_config_destructor (notmuch_config_t *config)
 static char *
 get_name_from_passwd_file (void *ctx)
 {
-long pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
-char *pw_buf = talloc_zero_size (ctx, pw_buf_size);
+long pw_buf_size;
+char *pw_buf;
 struct passwd passwd, *ignored;
 char *name;
 int e;
 
+pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
 if (pw_buf_size == -1) pw_buf_size = 64;
+pw_buf = talloc_size (ctx, pw_buf_size);
 
 while ((e = getpwuid_r (getuid (), passwd, pw_buf,
 pw_buf_size, ignored)) == ERANGE) {
@@ -142,13 +144,16 @@ get_name_from_passwd_file (void *ctx)
 static char *
 get_username_from_passwd_file (void *ctx)
 {
-long pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
-char *pw_buf = talloc_zero_size (ctx, pw_buf_size);
+long pw_buf_size;
+char *pw_buf;
 struct passwd passwd, *ignored;
 char *name;
 int e;
 
+pw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
 if (pw_buf_size == -1) pw_buf_size = 64;
+pw_buf = talloc_zero_size (ctx, pw_buf_size);
+
 while ((e = getpwuid_r (getuid (), passwd, pw_buf,
 pw_buf_size, ignored)) == ERANGE) {
 pw_buf_size = pw_buf_size * 2;
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] emacs: Allow user to choose From address when composing a new message.

2011-05-25 Thread Thomas Jost
On Tue, 24 May 2011 15:02:01 -0700, Carl Worth cwo...@cworth.org wrote:
 In order to select a From address, the user simply presses M instead of
 m to begin composing a message. By default the list of names/addresses
 to be used during completion will be automatically generated by the
 settings in the notmuch configuration file. The user can customize
 the notmuch-identities variable to provide an alternate list.

Thanks, IMHO that's better than my previous solution. And it makes my
.emacs smaller, woohoo! :)

One little issue though: you did not update notmuch-show-mode-map in
notmuch-show.el. I'll reply with a patch that fixes that (or you can
just integrate it in your commit when pushing it).

I'll also send a few additional patches that make it possible to choose
the From address when forwarding a message and when replying to a
message.

Regards,

-- 
Thomas/Schnouki


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


[PATCH 1/4] emacs: Allow the user choose the From address when composing a new message from notmuch-show-mode too.

2011-05-25 Thread Thomas Jost
---
 emacs/notmuch-show.el |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 825988c..93f46ac 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -847,7 +847,8 @@ function is used. 
(define-key map (kbd backtab) 'notmuch-show-previous-button)
(define-key map (kbd TAB) 'notmuch-show-next-button)
(define-key map s 'notmuch-search)
-   (define-key map m 'notmuch-mua-mail)
+   (define-key map m 'notmuch-mua-new-mail)
+   (define-key map M 'notmuch-mua-new-mail-prompt-for-sender)
(define-key map f 'notmuch-show-forward-message)
(define-key map r 'notmuch-show-reply)
(define-key map | 'notmuch-show-pipe-message)
-- 
1.7.5.1

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


[PATCH 2/4] emacs: Move the prompt for sender code to a new function.

2011-05-25 Thread Thomas Jost
This allows the code to be reused in different functions without duplicating it.
---
 emacs/notmuch-mua.el |   15 +--
 1 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index cd4d75d..0bde02c 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -157,21 +157,24 @@ name and addresses configured in the notmuch 
configuration file.
  (concat (notmuch-user-name)   address ))
(cons (notmuch-user-primary-email) (notmuch-user-other-email)
 
+(defvar notmuch-mua-sender-history nil)
+
+(defun notmuch-mua-prompt-for-sender ()
+  (interactive)
+  (let ((collection (notmuch-mua-sender-collection)))
+(ido-completing-read Send mail From:  collection
+nil 'confirm nil 'notmuch-mua-sender-history (car 
collection
+
 (defun notmuch-mua-new-mail-from (optional sender)
   (if sender
   (notmuch-mua-mail nil nil (list (cons 'from sender)))
 (notmuch-mua-mail)))
 
-(defvar notmuch-mua-sender-history nil)
-
 (defun notmuch-mua-new-mail (optional prompt-for-sender)
   Begin composing a new email with notmuch.
   (interactive P)
   (if prompt-for-sender
-  (let* ((collection (notmuch-mua-sender-collection))
-(sender (ido-completing-read Send mail From:  collection
- nil 'confirm nil 
'notmuch-mua-sender-history (car collection
-   (notmuch-mua-new-mail-from sender))
+  (notmuch-mua-new-mail-from (notmuch-mua-prompt-for-sender))
 (notmuch-mua-mail)))
 
 (defun notmuch-mua-new-mail-prompt-for-sender ()
-- 
1.7.5.1

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


[PATCH 3/4] emacs: Allow the user to choose the From address when forwarding a message.

2011-05-25 Thread Thomas Jost
---
 emacs/notmuch-mua.el  |8 
 emacs/notmuch-show.el |7 +++
 2 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 0bde02c..7c08a6e 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -182,6 +182,14 @@ name and addresses configured in the notmuch configuration 
file.
   (interactive)
   (notmuch-mua-new-mail t))
 
+(defun notmuch-mua-forward-message-prompt-for-sender ()
+  (interactive)
+  (let* ((sender (notmuch-mua-prompt-for-sender))
+(address-components (mail-extract-address-components sender))
+(user-full-name (car address-components))
+(user-mail-address (cadr address-components)))
+(notmuch-mua-forward-message)))
+
 (defun notmuch-mua-send-and-exit (optional arg)
   (interactive P)
   (message-send-and-exit arg))
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 93f46ac..50b20b2 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -850,6 +850,7 @@ function is used. 
(define-key map m 'notmuch-mua-new-mail)
(define-key map M 'notmuch-mua-new-mail-prompt-for-sender)
(define-key map f 'notmuch-show-forward-message)
+   (define-key map F 'notmuch-show-forward-message-prompt-for-sender)
(define-key map r 'notmuch-show-reply)
(define-key map | 'notmuch-show-pipe-message)
(define-key map w 'notmuch-show-save-attachments)
@@ -1165,6 +1166,12 @@ any effects from previous calls to
   (with-current-notmuch-show-message
(notmuch-mua-forward-message)))
 
+(defun notmuch-show-forward-message-prompt-for-sender ()
+  Forward the current message, prompting for the From: address first.
+  (interactive)
+  (with-current-notmuch-show-message
+   (notmuch-mua-forward-message-prompt-for-sender)))
+
 (defun notmuch-show-next-message ()
   Show the next message.
   (interactive)
-- 
1.7.5.1

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


[PATCH 4/4] emacs: Allow the user to choose the From address when replying to a message.

2011-05-25 Thread Thomas Jost
---
 emacs/notmuch-mua.el  |9 -
 emacs/notmuch-show.el |6 ++
 emacs/notmuch.el  |7 +++
 3 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 7c08a6e..d04e69c 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -69,7 +69,7 @@ list.
(push header message-hidden-headers)))
notmuch-mua-hidden-headers))
 
-(defun notmuch-mua-reply (query-string)
+(defun notmuch-mua-reply (query-string optional sender)
   (let (headers
body
(args '(reply)))
@@ -90,6 +90,9 @@ list.
  (setq headers (mail-header-extract)
   (forward-line 1)
   (setq body (buffer-substring (point) (point-max
+;; If sender is non-nil, set the From: header to its value.
+(when sender
+  (mail-header-set 'from sender headers))
 (let
;; Overlay the composition window on that being used to read
;; the original message.
@@ -190,6 +193,10 @@ name and addresses configured in the notmuch configuration 
file.
 (user-mail-address (cadr address-components)))
 (notmuch-mua-forward-message)))
 
+(defun notmuch-mua-reply-prompt-for-sender (query-string)
+  (interactive)
+  (notmuch-mua-reply query-string (notmuch-mua-prompt-for-sender)))
+
 (defun notmuch-mua-send-and-exit (optional arg)
   (interactive P)
   (message-send-and-exit arg))
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 50b20b2..2c69e96 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -852,6 +852,7 @@ function is used. 
(define-key map f 'notmuch-show-forward-message)
(define-key map F 'notmuch-show-forward-message-prompt-for-sender)
(define-key map r 'notmuch-show-reply)
+   (define-key map R 'notmuch-show-reply-prompt-for-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)
@@ -1160,6 +1161,11 @@ any effects from previous calls to
   (interactive)
   (notmuch-mua-reply (notmuch-show-get-message-id)))
 
+(defun notmuch-show-reply-prompt-for-sender ()
+  Reply to the current message, prompting for the From: address first.
+  (interactive)
+  (notmuch-mua-reply-prompt-for-sender (notmuch-show-get-message-id)))
+
 (defun notmuch-show-forward-message ()
   Forward the current message.
   (interactive)
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 1791d84..153dc74 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -204,6 +204,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-prompt-for-sender)
 (define-key map m 'notmuch-mua-new-mail)
 (define-key map M 'notmuch-mua-new-mail-prompt-for-sender)
 (define-key map s 'notmuch-search)
@@ -449,6 +450,12 @@ Complete list of currently available key bindings:
   (let ((message-id (notmuch-search-find-thread-id)))
 (notmuch-mua-reply message-id)))
 
+(defun notmuch-search-reply-to-thread-prompt-for-sender ()
+  Begin composing a reply to the entire current thread in a new buffer, 
prompting for the From: address first.
+  (interactive)
+  (let ((message-id (notmuch-search-find-thread-id)))
+(notmuch-mua-reply-prompt-for-sender message-id)))
+
 (defun notmuch-call-notmuch-process (rest args)
   Synchronously invoke \notmuch\ with the given list of arguments.
 
-- 
1.7.5.1

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


Re: [PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Austin Clements
On Wed, May 25, 2011 at 6:04 AM, Daniel Schoepe
daniel.scho...@googlemail.com wrote:
 On Wed, 25 May 2011 00:10:43 -0400, Austin Clements amdra...@mit.edu wrote:
 Out of curiosity, what use cases do you envision for this?  So far
 I've only heard two, both of which seem like great ideas, but neither
 of which require such a heavy-handed solution: displaying unread
 counts for tags rather than total counts, and hiding unused tags.

 Another thing I use this for, is to hide messages/threads with a
 killed-tag.

Ah, interesting.

 I think a sensible compromise would be to allow either a function or a
 string that is appended (which people could set to and tag:unread) for
 the proposed configuration variable and additionally to add a
 variable that lists tags that should be hidden (which would also be
 easily modifiable in M-x customize).

In principle, I completely agree, but the little parser in my head
screams parse error!  parse error! when I feed it and tag:unread
and that bothers me.

May I suggest a slightly different way of looking at this that will
quell my inner parser?  Instead of configuring a weird query
fragment like and tag:unread to be string-concatenated with the tag
query, configure a *filter* query like merely tag:unread that
narrows down what you'd like to be counted within the scope of a tag.
The implementations are hardly different---simply generate the query
tag:tag and ( filter )---but a filter is a well-formed query,
not some string fragment.  Furthermore, the user can't get bitten by
precedence and wind up with a query that counts messages that don't
even have that tag.
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Daniel Schoepe
On Wed, 25 May 2011 10:44:51 -0400, Austin Clements amdra...@mit.edu wrote:
 May I suggest a slightly different way of looking at this that will
 quell my inner parser?  Instead of configuring a weird query
 fragment like and tag:unread to be string-concatenated with the tag
 query, configure a *filter* query like merely tag:unread that
 narrows down what you'd like to be counted within the scope of a tag.
 The implementations are hardly different---simply generate the query
 tag:tag and ( filter )---but a filter is a well-formed query,
 not some string fragment.  Furthermore, the user can't get bitten by
 precedence and wind up with a query that counts messages that don't
 even have that tag.

Good point, I attached an updated patch that implements this.
From 6a4a5fd3e2a1baa25f86f85d6c3324db26582b82 Mon Sep 17 00:00:00 2001
From: Daniel Schoepe daniel.scho...@googlemail.com
Date: Fri, 20 May 2011 00:53:50 +0200
Subject: [PATCH] emacs: Make queries used in the all-tags section
 configurable

This patch adds a customization variable that controls what queries
are used to construct the all-tags section in notmuch-hello. It allows
the user to specify a function to construct the query given a tag or
a string that is used as a filter for each tag.
It also adds a variable to hide various tags from the all-tags section.

Signed-off-by: Daniel Schoepe daniel.scho...@googlemail.com
---
 emacs/notmuch-hello.el |   37 ++---
 1 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index e58dd24..a513bb0 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -55,6 +55,24 @@
   :type 'boolean
   :group 'notmuch)
 
+(defcustom notmuch-hello-tag-list-make-query nil
+  Function or string to generate queries for the all tags list.
+
+This variable controls which query results are shown for each tag
+in the \all tags\ list. It can be nil (for default behaviour,
+displaying all messages for a tag), a string that is used as a
+filter for messages having that tag (equivalent to \tag:TAG
+and (THIS-VARIABLE)\, or a function that is given a tag and
+should return the query that is to be used for the tag. If it
+returns nil, the corresponding tag will be hidden.
+  :type '(choice (const nil :tag tag:TAG) string function)
+  :group 'notmuch)
+
+(defcustom notmuch-hello-hide-tags nil
+  List of tags to be hidden in the \all tags\-section.
+  :type '(repeat string)
+  :group 'notmuch)
+
 (defface notmuch-hello-logo-background
   'class color)
   (background dark))
@@ -318,6 +336,21 @@ Complete list of currently available key bindings:
  ;;(setq buffer-read-only t)
 )
 
+(defun notmuch-hello-generate-tag-alist ()
+  Return an alist from tags to queries to display in the all-tags section.
+  (filter 'cdr
+	  (mapcar '(lambda (tag)
+		 (cons tag
+			   (cond
+			((functionp notmuch-hello-tag-list-make-query)
+			 (funcall notmuch-hello-tag-list-make-query tag))
+			((stringp notmuch-hello-tag-list-make-query)
+			 (concat tag: tag  and (
+ notmuch-hello-tag-list-make-query )))
+			(t (concat tag: tag)
+		  (filter (lambda (tag) (not (member tag notmuch-hello-hide-tags)))
+			  (process-lines notmuch-command search-tags)
+
 ;;;###autoload
 (defun notmuch-hello (optional no-display)
   Run notmuch and display saved searches, known tags, etc.
@@ -396,9 +429,7 @@ Complete list of currently available key bindings:
 		  if ( (string-to-number (notmuch-saved-search-count (cdr elem))) 0)
 		  collect elem)))
 	 (saved-widest (notmuch-hello-longest-label saved-alist))
-	 (alltags-alist (if notmuch-show-all-tags-list
-(mapcar '(lambda (tag) (cons tag (concat tag: tag)))
-	(process-lines notmuch-command search-tags
+	 (alltags-alist (if notmuch-show-all-tags-list (notmuch-hello-generate-tag-alist)))
 	 (alltags-widest (notmuch-hello-longest-label alltags-alist))
 	 (widest (max saved-widest alltags-widest)))
 
-- 
1.7.5.1



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


Re: [PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Daniel Schoepe

I accidentally used `filter' in the previous patch which isn't defined
by default during runtime, updated version in the attachment.
From e8f5e997b7082a50f75d7329a69fccc126a21e5e Mon Sep 17 00:00:00 2001
From: Daniel Schoepe daniel.scho...@googlemail.com
Date: Fri, 20 May 2011 00:53:50 +0200
Subject: [PATCH] emacs: Make queries used in the all-tags section
 configurable

This patch adds a customization variable that controls what queries
are used to construct the all-tags section in notmuch-hello. It allows
the user to specify a function to construct the query given a tag or
a string that is used as a filter for each tag.
It also adds a variable to hide various tags from the all-tags section.

Signed-off-by: Daniel Schoepe daniel.scho...@googlemail.com
---
 emacs/notmuch-hello.el |   38 +++---
 emacs/notmuch-lib.el   |   12 
 2 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index e58dd24..b3f133c 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -55,6 +55,24 @@
   :type 'boolean
   :group 'notmuch)
 
+(defcustom notmuch-hello-tag-list-make-query nil
+  Function or string to generate queries for the all tags list.
+
+This variable controls which query results are shown for each tag
+in the \all tags\ list. It can be nil (for default behaviour,
+displaying all messages for a tag), a string that is used as a
+filter for messages having that tag (equivalent to \tag:TAG
+and (THIS-VARIABLE)\, or a function that is given a tag and
+should return the query that is to be used for the tag. If it
+returns nil, the corresponding tag will be hidden.
+  :type '(choice (const nil :tag tag:TAG) string function)
+  :group 'notmuch)
+
+(defcustom notmuch-hello-hide-tags nil
+  List of tags to be hidden in the \all tags\-section.
+  :type '(repeat string)
+  :group 'notmuch)
+
 (defface notmuch-hello-logo-background
   'class color)
   (background dark))
@@ -318,6 +336,22 @@ Complete list of currently available key bindings:
  ;;(setq buffer-read-only t)
 )
 
+(defun notmuch-hello-generate-tag-alist ()
+  Return an alist from tags to queries to display in the all-tags section.
+  (notmuch-filter
+   'cdr
+   (mapcar '(lambda (tag)
+	  (cons tag
+		(cond
+		 ((functionp notmuch-hello-tag-list-make-query)
+		  (funcall notmuch-hello-tag-list-make-query tag))
+		 ((stringp notmuch-hello-tag-list-make-query)
+		  (concat tag: tag  and (
+			  notmuch-hello-tag-list-make-query )))
+		 (t (concat tag: tag)
+	   (notmuch-filter (lambda (tag) (not (member tag notmuch-hello-hide-tags)))
+			   (process-lines notmuch-command search-tags)
+
 ;;;###autoload
 (defun notmuch-hello (optional no-display)
   Run notmuch and display saved searches, known tags, etc.
@@ -396,9 +430,7 @@ Complete list of currently available key bindings:
 		  if ( (string-to-number (notmuch-saved-search-count (cdr elem))) 0)
 		  collect elem)))
 	 (saved-widest (notmuch-hello-longest-label saved-alist))
-	 (alltags-alist (if notmuch-show-all-tags-list
-(mapcar '(lambda (tag) (cons tag (concat tag: tag)))
-	(process-lines notmuch-command search-tags
+	 (alltags-alist (if notmuch-show-all-tags-list (notmuch-hello-generate-tag-alist)))
 	 (alltags-widest (notmuch-hello-longest-label alltags-alist))
 	 (widest (max saved-widest alltags-widest)))
 
diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
index cc80fb2..a3195ff 100644
--- a/emacs/notmuch-lib.el
+++ b/emacs/notmuch-lib.el
@@ -120,6 +120,18 @@ within the current window.
   (or (memq prop buffer-invisibility-spec)
 	  (assq prop buffer-invisibility-spec)
 
+;; notmuch- prefix to avoid clashes with user-defined filter-functions:
+;; For instance, the filter-function suggested in the elisp cookbook
+;; on the emacswiki always filters out elements that are nil
+;; even if the predicate returns t for nil; hence this has slightly
+;; different semantics than what some users have defined for themselves.
+(defun notmuch-filter (pred lst)
+  Return a list containing all elements from LST that satisfy PRED.
+  (and lst
+ (if (funcall pred (car lst))
+	 (cons (car lst) (notmuch-filter pred (cdr lst)))
+   (notmuch-filter pred (cdr lst)
+
 ; This lets us avoid compiling these replacement functions when emacs
 ; is sufficiently new enough to supply them alone. We do the macro
 ; treatment rather than just wrapping our defun calls in a when form
-- 
1.7.5.1



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


Re: [PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Austin Clements
On Wed, May 25, 2011 at 1:56 PM, Daniel Schoepe
daniel.scho...@googlemail.com wrote:
 I accidentally used `filter' in the previous patch which isn't defined
 by default during runtime, updated version in the attachment.

Cool.  My inner parser is happy.

A few comments on the code:

 +(defcustom notmuch-hello-tag-list-make-query nil
 +  Function or string to generate queries for the all tags list.
 +
 +This variable controls which query results are shown for each tag
 +in the \all tags\ list. It can be nil (for default behaviour,
 +displaying all messages for a tag), a string that is used as a
 +filter for messages having that tag (equivalent to \tag:TAG
 +and (THIS-VARIABLE)\, or a function that is given a tag and
 +should return the query that is to be used for the tag. If it
 +returns nil, the corresponding tag will be hidden.
 +  :type '(choice (const nil :tag tag:TAG) string function)
 +  :group 'notmuch)

At least in Emacs 23.3.1, it has to be (const :tag tag:TAG nil).  I
didn't think the order mattered, but the tag didn't display otherwise.
 It would also be good to give descriptive tags to the other choices.

It would be more consistent if the function form of this also returned
a filter expression, rather than a whole expression.  This also
simplifies the documentation.

So, perhaps something like

(defcustom notmuch-hello-tag-list-counts nil
  Method for generating counts displayed in the all tags list.

This variable controls the query used to generate counts for each
tag in the \all tags\ list.  If nil, the tag list will count
all messages with each tag.  This can be a query string that will
filter the messages counted for each tag.  Finally, this can be a
function that will be called for each tag and should return a
filter query for that tag, or nil to hide the tag.
  :type '(choice (const :tag Count all messages nil)
 (const :tag Count unread messages tag:unread)
 (const :tag Custom filter string)
 (const :tag Custom filter function function))
  :group 'notmuch)

 +(defun notmuch-hello-generate-tag-alist ()
 +  Return an alist from tags to queries to display in the all-tags section.
 +  (notmuch-filter
 +   'cdr
 +   (mapcar '(lambda (tag)

You don't need the quote before a lambda form.  (You can also change
'cdr to #'cdr to further hint the compiler, though it appears to not
matter in this case.)

 +(defun notmuch-filter (pred lst)
 +  Return a list containing all elements from LST that satisfy PRED.

notmuch-remove-if-not would be more canonical (yeah, it's unwieldy,
blame Common Lisp).  Also, since Elisp doesn't do tail-recursion, the
standard way to define a remove-if-not function is

(defun notmuch-remove-if-not (predicate list)
  Return a copy of LIST with all items not satisfying PREDICATE removed.
  (let (out)
(while list
  (when (funcall predicate (car list))
(push (car list) out))
  (setq list (cdr list)))
(nreverse out)))

(Why oh why Elisp hasn't just made remove-if and remove-if-not
standard I don't know; they're redefined all over the Elisp code base.
 Any everybody's afraid to use cl-seq's remove-if-not because it's so
ridiculously complicated.)
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Daniel Schoepe
On Wed, 25 May 2011 15:11:16 -0400, Austin Clements amdra...@mit.edu wrote:
 At least in Emacs 23.3.1, it has to be (const :tag tag:TAG nil).  I
 didn't think the order mattered, but the tag didn't display otherwise.
  It would also be good to give descriptive tags to the other choices.
 
 It would be more consistent if the function form of this also returned
 a filter expression, rather than a whole expression.  This also
 simplifies the documentation.

Thanks for the suggestions. (At first, I wanted to allow the user
to be able to also include messages that don't have that tag, but this
really no longer belongs in the all tags-section).

 So, perhaps something like

 (defcustom notmuch-hello-tag-list-counts nil
   Method for generating counts displayed in the all tags list.
 
 This variable controls the query used to generate counts for each
 tag in the \all tags\ list.  If nil, the tag list will count
 all messages with each tag.  This can be a query string that will
 filter the messages counted for each tag.  Finally, this can be a
 function that will be called for each tag and should return a
 filter query for that tag, or nil to hide the tag.
   :type '(choice (const :tag Count all messages nil)
  (const :tag Count unread messages tag:unread)
  (const :tag Custom filter string)
  (const :tag Custom filter function function))
   :group 'notmuch)

That is slightly less accurate though, since the query is not only used
to generate the counts, but also the searches that are performed when
one presses return on a tag in the list.

  +(defun notmuch-hello-generate-tag-alist ()
  +  Return an alist from tags to queries to display in the all-tags 
  section.
  +  (notmuch-filter
  +   'cdr
  +   (mapcar '(lambda (tag)
 
 You don't need the quote before a lambda form.  (You can also change
 'cdr to #'cdr to further hint the compiler, though it appears to not
 matter in this case.)

Oh, yeah, normally I'm aware of that, don't know what made me quote it
at the time I wrote it.

  +(defun notmuch-filter (pred lst)
  +  Return a list containing all elements from LST that satisfy PRED.
 
 notmuch-remove-if-not would be more canonical (yeah, it's unwieldy,
 blame Common Lisp).  Also, since Elisp doesn't do tail-recursion, the
 standard way to define a remove-if-not function is
 
 (defun notmuch-remove-if-not (predicate list)
   Return a copy of LIST with all items not satisfying PREDICATE removed.
   (let (out)
 (while list
   (when (funcall predicate (car list))
 (push (car list) out))
   (setq list (cdr list)))
 (nreverse out)))
 
 (Why oh why Elisp hasn't just made remove-if and remove-if-not
 standard I don't know; they're redefined all over the Elisp code base.
  Any everybody's afraid to use cl-seq's remove-if-not because it's so
 ridiculously complicated.)

Ah, thanks. I guess too much exposure to Haskell (and how smart GHC is)
makes me write things in a functional style without thinking about
performance.

I incorporated most of you recommendations in the attached patch.
From 2056a455cdec6b980426552b8dcd7055f6cd0805 Mon Sep 17 00:00:00 2001
From: Daniel Schoepe daniel.scho...@googlemail.com
Date: Fri, 20 May 2011 00:53:50 +0200
Subject: [PATCH] emacs: Make queries used in the all-tags section
 configurable

This patch adds a customization variable that controls what queries
are used to construct the all-tags section in notmuch-hello. It allows
the user to specify a function to construct the query given a tag or
a string that is used as a filter for each tag.
It also adds a variable to hide various tags from the all-tags section.

Signed-off-by: Daniel Schoepe daniel.scho...@googlemail.com
---
 emacs/notmuch-hello.el |   43 ---
 emacs/notmuch-lib.el   |9 +
 2 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index e58dd24..bd95849 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -55,6 +55,26 @@
   :type 'boolean
   :group 'notmuch)
 
+(defcustom notmuch-hello-tag-list-make-query nil
+  Function or string to generate queries for the all tags list.
+
+This variable controls which query results are shown for each tag
+in the \all tags\ list. If nil, it will use all messages with
+that tag. If this is set to a string, it is used as a filter for
+messages having that tag (equivalent to \tag:TAG and (THIS-VARIABLE)\).
+Finally this can be a function that will be called for each tag and
+should return a filter for that tag, or nil to hide the tag.
+  :type '(choice (const :tag All messages nil)
+		 (const :tag Unread messages tag:unread)
+		 (const :tag Custom filter string)
+		 (const :tag Custom filter function function))
+  :group 'notmuch)
+
+(defcustom notmuch-hello-hide-tags nil
+  List of tags to be hidden in the \all tags\-section.
+  :type '(repeat string)
+  :group 'notmuch)
+
 (defface 

[PATCH] Fix hiding a message while some citations are visible

2011-05-25 Thread Dmitry Kurochkin
This patch series does some fixes and improvements for hiding and
showing messages in notmuch-show.  However it comes with a
regression: isearch is broken for hidden overlays when
`invisible' property is a list.  I have opened emacs bug #8721
[1] and sent a patch.  It has been committed to emacs trunk
r104356.

I do not know if this should be pushed or wait until emacs with
the fix is released.

Regards,
  Dmitry

[1] http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8721
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 1/5] Pass message to the `notmuch-show-insert-text/plain-hook' hook.

2011-05-25 Thread Dmitry Kurochkin
Before the change, the `notmuch-show-insert-text/plain-hook' was
given only the `depth' argument.  The patch adds another one -
the message.  Currently, the new message argument is not used by
any on the hooks.  But it will be used later to get access to
message invisibility specs when wash buttons are inserted.
---
 emacs/notmuch-show.el |2 +-
 emacs/notmuch-wash.el |   10 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index bd348e1..786debf 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -531,7 +531,7 @@ current buffer, if possible.
 (save-excursion
   (save-restriction
(narrow-to-region start (point-max))
-   (run-hook-with-args 'notmuch-show-insert-text/plain-hook depth
+   (run-hook-with-args 'notmuch-show-insert-text/plain-hook msg depth
   t)
 
 (defun notmuch-show-insert-part-text/x-vcalendar (msg part content-type nth 
depth declared-type)
diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el
index 115c3bb..7d87e85 100644
--- a/emacs/notmuch-wash.el
+++ b/emacs/notmuch-wash.el
@@ -147,7 +147,7 @@ insert before the button, probably for indentation.
 'overlay overlay
 :type button-type
 
-(defun notmuch-wash-excerpt-citations (depth)
+(defun notmuch-wash-excerpt-citations (msg depth)
   Excerpt citations and up to one signature.
   (goto-char (point-min))
   (beginning-of-line)
@@ -185,7 +185,7 @@ insert before the button, probably for indentation.
 
 ;;
 
-(defun notmuch-wash-elide-blank-lines (depth)
+(defun notmuch-wash-elide-blank-lines (msg depth)
   Elide leading, trailing and successive blank lines.
 
   ;; Algorithm derived from `article-strip-multiple-blank-lines' in
@@ -213,7 +213,7 @@ insert before the button, probably for indentation.
 
 ;;
 
-(defun notmuch-wash-tidy-citations (depth)
+(defun notmuch-wash-tidy-citations (msg depth)
   Improve the display of cited regions of a message.
 
 Perform several transformations on the message body:
@@ -244,7 +244,7 @@ Perform several transformations on the message body:
 
 ;;
 
-(defun notmuch-wash-wrap-long-lines (depth)
+(defun notmuch-wash-wrap-long-lines (msg depth)
   Wrap any long lines in the message to the width of the window.
 
 When doing so, maintaining citation leaders in the wrapped text.
@@ -263,7 +263,7 @@ When doing so, maintaining citation leaders in the wrapped 
text.
 
 (defvar diff-file-header-re) ; From `diff-mode.el'.
 
-(defun notmuch-wash-convert-inline-patch-to-part (depth)
+(defun notmuch-wash-convert-inline-patch-to-part (msg depth)
   Convert an inline patch into a fake 'text/x-diff' attachment.
 
 Given that this function guesses whether a buffer includes a
-- 
1.7.5.1

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


[PATCH 2/5] Set message invisibility spec properties before inserting the body.

2011-05-25 Thread Dmitry Kurochkin
This would allow body-inserting code (in particular, wash
button-inserting code) to use message invisibility specs.
---
 emacs/notmuch-show.el |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 786debf..34c0b79 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -693,6 +693,9 @@ current buffer, if possible.
 
 (setq content-start (point-marker))
 
+(plist-put msg :headers-invis-spec headers-invis-spec)
+(plist-put msg :message-invis-spec message-invis-spec)
+
 ;; Set `headers-start' to point after the 'Subject:' header to be
 ;; compatible with the existing implementation. This just sets it
 ;; to after the first header.
@@ -730,10 +733,7 @@ current buffer, if possible.
 ;; message.
 (put-text-property message-start message-end :notmuch-message-extent (cons 
message-start message-end))
 
-(plist-put msg :headers-invis-spec headers-invis-spec)
 (overlay-put (make-overlay headers-start headers-end) 'invisible 
headers-invis-spec)
-
-(plist-put msg :message-invis-spec message-invis-spec)
 (overlay-put (make-overlay body-start body-end) 'invisible 
message-invis-spec)
 
 ;; Save the properties for this message. Currently this saves the
-- 
1.7.5.1

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


[PATCH 3/5] Fix hiding a message while some citations are shown in notmuch-show view.

2011-05-25 Thread Dmitry Kurochkin
Before the change, message and citation invisibility overlays
conflicted: if some citation is made visible and then the whole
message is hidden, that citation remained visible.  This happened
because the citation's overlay has an invisible property which
takes priority over the message overlay.  The message
invisibility spec does not affect citation visibility, it is
determined solely by the citation overlay invisibility spec.
Hence, if citation is made visible, it is not hidden by message
invisibility spec.

The patch changes citation overlay invisibility property to be a
list which contains both the citation and the message
invisibility specs.  This makes the citation invisible if either
of them is added to the `buffer-invisibility-spec'.  Note that
all citation visibility states are restored when the message
hidden and shown again.
---
 emacs/notmuch-wash.el |   12 +++-
 1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el
index 7d87e85..bd521ba 100644
--- a/emacs/notmuch-wash.el
+++ b/emacs/notmuch-wash.el
@@ -107,7 +107,8 @@ collapse the remaining lines into a button.)
   :supertype 'notmuch-wash-button-invisibility-toggle-type)
 
 (defun notmuch-wash-region-isearch-show (overlay)
-  (remove-from-invisibility-spec (overlay-get overlay 'invisible)))
+  (dolist (invis-spec (overlay-get overlay 'invisible))
+(remove-from-invisibility-spec invis-spec)))
 
 (defun notmuch-wash-button-label (overlay)
   (let* ((type (overlay-get overlay 'type))
@@ -118,7 +119,7 @@ collapse the remaining lines into a button.)
 (lines-count (count-lines (overlay-start overlay) (overlay-end 
overlay
 (format label-format lines-count)))
 
-(defun notmuch-wash-region-to-button (beg end type prefix)
+(defun notmuch-wash-region-to-button (msg beg end type prefix)
   Auxilary function to do the actual making of overlays and buttons
 
 BEG and END are buffer locations. TYPE should a string, either
@@ -131,11 +132,12 @@ insert before the button, probably for indentation.
   ;; since the newly created symbol has no plist.
 
   (let ((overlay (make-overlay beg end))
+   (message-invis-spec (plist-get msg :message-invis-spec))
(invis-spec (make-symbol (concat notmuch- type -region)))
(button-type (intern-soft (concat notmuch-wash-button-
  type -toggle-type
 (add-to-invisibility-spec invis-spec)
-(overlay-put overlay 'invisible invis-spec)
+(overlay-put overlay 'invisible (list invis-spec message-invis-spec))
 (overlay-put overlay 'isearch-open-invisible 
#'notmuch-wash-region-isearch-show)
 (overlay-put overlay 'type type)
 (goto-char (1+ end))
@@ -166,7 +168,7 @@ insert before the button, probably for indentation.
  (goto-char cite-end)
  (forward-line (- notmuch-wash-citation-lines-suffix))
  (notmuch-wash-region-to-button
-  hidden-start (point-marker)
+  msg hidden-start (point-marker)
   citation \n)
   (if (and (not (eobp))
   (re-search-forward notmuch-wash-signature-regexp nil t))
@@ -180,7 +182,7 @@ insert before the button, probably for indentation.
  (set-marker sig-end-marker (point-max))
  (overlay-put (make-overlay sig-start-marker sig-end-marker) 'face 
'message-cited-text)
  (notmuch-wash-region-to-button
-  sig-start-marker sig-end-marker
+  msg sig-start-marker sig-end-marker
   signature \n))
 
 ;;
-- 
1.7.5.1

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


[PATCH 4/5] Set higher priority for headers and hidden citation overlays.

2011-05-25 Thread Dmitry Kurochkin
Before the patch, message, headers and hidden citation overlays
had zero priority.  All these overlay have `invisible' property.
Emacs documentation says that we should not make assumptions
about which overlay will prevail when they have the same priority
[1].  It happens to work as we need, but we should not rely on
undocumented behavior.

[1] http://www.gnu.org/s/emacs/manual/html_node/elisp/Overlay-Properties.html
---
 emacs/notmuch-show.el |4 +++-
 emacs/notmuch-wash.el |1 +
 2 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 34c0b79..e1846bc 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -733,7 +733,9 @@ current buffer, if possible.
 ;; message.
 (put-text-property message-start message-end :notmuch-message-extent (cons 
message-start message-end))
 
-(overlay-put (make-overlay headers-start headers-end) 'invisible 
headers-invis-spec)
+(let ((headers-overlay (make-overlay headers-start headers-end)))
+  (overlay-put headers-overlay 'invisible headers-invis-spec)
+  (overlay-put headers-overlay 'priority 10))
 (overlay-put (make-overlay body-start body-end) 'invisible 
message-invis-spec)
 
 ;; Save the properties for this message. Currently this saves the
diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el
index bd521ba..992fa8f 100644
--- a/emacs/notmuch-wash.el
+++ b/emacs/notmuch-wash.el
@@ -139,6 +139,7 @@ insert before the button, probably for indentation.
 (add-to-invisibility-spec invis-spec)
 (overlay-put overlay 'invisible (list invis-spec message-invis-spec))
 (overlay-put overlay 'isearch-open-invisible 
#'notmuch-wash-region-isearch-show)
+(overlay-put overlay 'priority 10)
 (overlay-put overlay 'type type)
 (goto-char (1+ end))
 (save-excursion
-- 
1.7.5.1

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


[PATCH 5/5] Simplify message and headers visibility code in notmuch-show view.

2011-05-25 Thread Dmitry Kurochkin
Before the change, headers and message visibility functions took
extra care to correctly set `buffer-invisibility-spec'.  This was
needed because headers overlay `invisible' property had only
headers' invisibility spec.  So visibility of headers was
determined only by the headers invisibility spec.  The patch sets
headers overlay `invisible' property a list with both the headers
and the message invisibility spec.  This makes headers invisible
if either of them is added to the `buffer-invisibility-spec' and
allows to simplify the code.
---
 emacs/notmuch-show.el |   18 +-
 1 files changed, 5 insertions(+), 13 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index e1846bc..2f7154e 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -733,8 +733,9 @@ current buffer, if possible.
 ;; message.
 (put-text-property message-start message-end :notmuch-message-extent (cons 
message-start message-end))
 
-(let ((headers-overlay (make-overlay headers-start headers-end)))
-  (overlay-put headers-overlay 'invisible headers-invis-spec)
+(let ((headers-overlay (make-overlay headers-start headers-end))
+  (invis-specs (list headers-invis-spec message-invis-spec)))
+  (overlay-put headers-overlay 'invisible invis-specs)
   (overlay-put headers-overlay 'priority 10))
 (overlay-put (make-overlay body-start body-end) 'invisible 
message-invis-spec)
 
@@ -974,20 +975,11 @@ All currently available key bindings:
   (add-to-invisibility-spec spec
 
 (defun notmuch-show-message-visible (props visible-p)
-  (if visible-p
-  ;; When making the message visible, the headers may or not be
-  ;; visible. So we check that property separately.
-  (let ((headers-visible (plist-get props :headers-visible)))
-   (notmuch-show-element-visible props headers-visible :headers-invis-spec)
-   (notmuch-show-element-visible props t :message-invis-spec))
-(notmuch-show-element-visible props nil :headers-invis-spec)
-(notmuch-show-element-visible props nil :message-invis-spec))
-
+  (notmuch-show-element-visible props visible-p :message-invis-spec)
   (notmuch-show-set-prop :message-visible visible-p props))
 
 (defun notmuch-show-headers-visible (props visible-p)
-  (if (plist-get props :message-visible)
-  (notmuch-show-element-visible props visible-p :headers-invis-spec))
+  (notmuch-show-element-visible props visible-p :headers-invis-spec)
   (notmuch-show-set-prop :headers-visible visible-p props))
 
 ;; Functions for setting and getting attributes of the current
-- 
1.7.5.1

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


Re: [PATCH] emacs: Allow user to choose From address when composing a new message.

2011-05-25 Thread Carl Worth
On Wed, 25 May 2011 15:21:06 +0200, Thomas Jost schno...@schnouki.net wrote:
 Thanks, IMHO that's better than my previous solution. And it makes my
 .emacs smaller, woohoo! :)

Thanks for the review.

 One little issue though: you did not update notmuch-show-mode-map in
 notmuch-show.el. I'll reply with a patch that fixes that (or you can
 just integrate it in your commit when pushing it).

Good catch.

 I'll also send a few additional patches that make it possible to choose
 the From address when forwarding a message and when replying to a
 message.

The only real concern I have with the series is that it grabs 'R' for
reply-with-custom-from where I've been planning to implement 'R' as
reply-to-sender-only, (a long-missing and often-requested feature).

When I first started implementing the custom-from feature I planned to
use a prefix argument to get the behavior (such as C-u m rather than
M for compose-new-mail-with-custom-from). You might even see I've got
some code written along those lines.

When I went to test it though, it didn't work. That was probably some
silly mistake on my part, (we do already have working code that changes
behavior with a prefix argument in the case of M-RET for example).

If you want to update the series to move away from capital-letter
keybindings in favor of a prefix argument, I'll be glad to accept it.

Otherwise, I might get around to doing that myself at some point.

Thanks again,

-Carl

-- 
carl.d.wo...@intel.com


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


Re: [PATCH 3/5] Fix hiding a message while some citations are shown in notmuch-show view.

2011-05-25 Thread Carl Worth
On Thu, 26 May 2011 02:10:14 +0400, Dmitry Kurochkin 
dmitry.kuroch...@gmail.com wrote:
 Before the change, message and citation invisibility overlays
 conflicted: if some citation is made visible and then the whole
 message is hidden, that citation remained visible.

That sounds like quite a bug. I'd love to see this series also add a
test case for that.

-Carl

-- 
carl.d.wo...@intel.com


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


Re: [PATCH 3/5] Fix hiding a message while some citations are shown in notmuch-show view.

2011-05-25 Thread Dmitry Kurochkin
On Wed, 25 May 2011 15:23:47 -0700, Carl Worth cwo...@cworth.org wrote:
 On Thu, 26 May 2011 02:10:14 +0400, Dmitry Kurochkin 
 dmitry.kuroch...@gmail.com wrote:
  Before the change, message and citation invisibility overlays
  conflicted: if some citation is made visible and then the whole
  message is hidden, that citation remained visible.
 
 That sounds like quite a bug. I'd love to see this series also add a
 test case for that.
 

I am not sure how it is best to test this.  The common `printc' method
for emacs tests does not work, because it prints invisible parts as
well.  We need either to find a way to print only visible text on the
console, or test it inside emacs somehow.  Any suggestions?

Note that this is exactly the patch that hits the isearch emacs bug.  Do
I understand correctly that you are ready to push the series despite of
it (given that we have a test)?

Regards,
  Dmitry

 -Carl
 
 -- 
 carl.d.wo...@intel.com
Non-text part: application/pgp-signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Austin Clements
On Wed, May 25, 2011 at 5:21 PM, Daniel Schoepe
daniel.scho...@googlemail.com wrote:
 On Wed, 25 May 2011 15:11:16 -0400, Austin Clements amdra...@mit.edu wrote:
 So, perhaps something like

 (defcustom notmuch-hello-tag-list-counts nil
   Method for generating counts displayed in the all tags list.

 This variable controls the query used to generate counts for each
 tag in the \all tags\ list.  If nil, the tag list will count
 all messages with each tag.  This can be a query string that will
 filter the messages counted for each tag.  Finally, this can be a
 function that will be called for each tag and should return a
 filter query for that tag, or nil to hide the tag.
   :type '(choice (const :tag Count all messages nil)
                  (const :tag Count unread messages tag:unread)
                  (const :tag Custom filter string)
                  (const :tag Custom filter function function))
   :group 'notmuch)

 That is slightly less accurate though, since the query is not only used
 to generate the counts, but also the searches that are performed when
 one presses return on a tag in the list.

'Doh.  That's what I get for not reading the surrounding code.  I
misunderstood what your patch was going for and assumed it was what
*I* wanted notmuch to do, which is to show me useful counts (e.g.,
unread count), but not to change the underlying query.  ]:--8)

So, to me, it seems like this turns the all tags section into another
saved searches section, just with a slight twist, and makes me wonder
if there's a better way to reconcile these.

 Ah, thanks. I guess too much exposure to Haskell (and how smart GHC is)
 makes me write things in a functional style without thinking about
 performance.

Hah, been there.  I have to constantly remind myself that Elisp is
*not* a self-respecting functional programming language, despite how
much it may look like Scheme.
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 3/5] Fix hiding a message while some citations are shown in notmuch-show view.

2011-05-25 Thread Carl Worth
On Thu, 26 May 2011 02:34:28 +0400, Dmitry Kurochkin 
dmitry.kuroch...@gmail.com wrote:
 I am not sure how it is best to test this.  The common `printc' method
 for emacs tests does not work, because it prints invisible parts as
 well.  We need either to find a way to print only visible text on the
 console, or test it inside emacs somehow.  Any suggestions?

Unfortunately, I don't have a good plan here. I delayed implementing any
automated testing at all of the emacs interface precisely because of
this problem. It's seems to me that surely emacs must have some built-in
mechanism for copying the visible portion of a block of text, but I've
not been able to find it.

We could do something cheesy (and slow) by marching through the buffer
character-by-character in elisp and testing for visibility, but the
emacs tests are already the slowest part of make test[*] so that would
be obnoxious.

 Note that this is exactly the patch that hits the isearch emacs bug.  Do
 I understand correctly that you are ready to push the series despite of
 it (given that we have a test)?

Breaking isearch would be really unfortunate. That's a really nice
feature of the emacs frontend currently.

So I would notice that breakage, (while I've apparently never before
noticed the breakage of having visible citations in a hidden message).

So no, I'm not saying I'm ready to push the series while emacs is broken.

-Carl

[*] Maybe the performance of the emacs testing could be significantly
improved by sharing a single invocation of emacs? Perhaps this wouldn't
even be hard by just using emacsclient?



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


Re: [PATCH 3/5] Fix hiding a message while some citations are shown in notmuch-show view.

2011-05-25 Thread Dmitry Kurochkin
On Wed, 25 May 2011 15:46:40 -0700, Carl Worth cwo...@cworth.org wrote:
 On Thu, 26 May 2011 02:34:28 +0400, Dmitry Kurochkin 
 dmitry.kuroch...@gmail.com wrote:
  I am not sure how it is best to test this.  The common `printc' method
  for emacs tests does not work, because it prints invisible parts as
  well.  We need either to find a way to print only visible text on the
  console, or test it inside emacs somehow.  Any suggestions?
 
 Unfortunately, I don't have a good plan here. I delayed implementing any
 automated testing at all of the emacs interface precisely because of
 this problem. It's seems to me that surely emacs must have some built-in
 mechanism for copying the visible portion of a block of text, but I've
 not been able to find it.
 

Me too.

 We could do something cheesy (and slow) by marching through the buffer
 character-by-character in elisp and testing for visibility, but the
 emacs tests are already the slowest part of make test[*] so that would
 be obnoxious.
 

Indeed.

  Note that this is exactly the patch that hits the isearch emacs bug.  Do
  I understand correctly that you are ready to push the series despite of
  it (given that we have a test)?
 
 Breaking isearch would be really unfortunate. That's a really nice
 feature of the emacs frontend currently.
 
 So I would notice that breakage, (while I've apparently never before
 noticed the breakage of having visible citations in a hidden message).
 
 So no, I'm not saying I'm ready to push the series while emacs is broken.
 

Well, emacs trunk is not broken :)  The bug is in lisp code, so you can
fix it in .emacs by redefining `isearch-range-invisible' function.  I do
that now.

I do not think I will make myself work on the test until it is likely to
be pushed.  I will try to not to forget about it, so sometime later I
may be back to it :)

Please consider pushing other patches from the series.  They do not fix
any bug, but do simplify the code.  The last patch uses list for
invisible overlay property as well.  But it does not break isearch
because we do not search in hidden messages.

BTW would be nice to have a set of known-to-fail tests, i.e. bugs that
are not fixed yet.  If we had it, the above test could be implemented
and committed before we have the fix pushed.

 -Carl
 
 [*] Maybe the performance of the emacs testing could be significantly
 improved by sharing a single invocation of emacs? Perhaps this wouldn't
 even be hard by just using emacsclient?
 

This is possible as long as tests do not affect each other.  Would be a
nice improvement.

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


Re: [PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Daniel Schoepe
On Wed, 25 May 2011 18:42:30 -0400, Austin Clements amdra...@mit.edu wrote:
 'Doh.  That's what I get for not reading the surrounding code.  I
 misunderstood what your patch was going for and assumed it was what
 *I* wanted notmuch to do, which is to show me useful counts (e.g.,
 unread count), but not to change the underlying query.  ]:--8)

I thought about that too, but figured it should be rather rare that
someone wants only a portion of some messages _counted_, but all
displayed when clicking on the search next to the count.

I'm somewhat indifferent, since I rarely use those links
directly, so any more opinions on this are very much appreciated.

 So, to me, it seems like this turns the all tags section into another
 saved searches section, just with a slight twist, and makes me wonder
 if there's a better way to reconcile these.

Well, it already was sort of a non-configurable saved searches section
before, so I didn't really turn it into one. :)

Since the main difference between those sections is the clear visual
distinction, it might be an option to provide the user with functions to
easily declare new sections for the hello screen, where this sort of
thing is configurable. (One possible use that comes to mind would be to
group tags into different categories.)


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


New crypto patch series

2011-05-25 Thread Jameson Graef Rollins
Hi, folks.  This is a series of patches that constitute a complete
rework of notmuch crypto support (signature verification and
decryption of PGP/MIME messages, with emacs ui support), including
some relevant preparatory patches, on top of the notmuch/master branch
at b6862c7eb9bfb00183e568b40d77ea25ade21db2.  This work is also
available on the new-crypto branch of my notmuch repo:

git://finestructure.net/notmuch [new-crypto]
aa41285c5f75f8ea30d4582f6b8e1aa306f1632c

It's sounding unlikely that Carl will accept this work in to master
any time soon, due to concerns he has about how the crypto processing
affects part numbering (a concern that I think is pretty minor, and
really don't affect the usability of the new functionality, fwiw).  In
the mean time, I wanted to get these patches out there, for those of
us that depend on this functionality.

jamie.

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


[PATCH 03/11] Use empty strings instead of NULL in format_reply structure.

2011-05-25 Thread Jameson Graef Rollins
This keeps things consistent with notmuch-show, and prevents having to
check for the existence of the field pointer for simple string output
formats.
---
 notmuch-reply.c |   12 ++--
 show-message.c  |2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index 8c5e76c..7959935 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -29,12 +29,12 @@ reply_part (GMimeObject *part,
unused (int *part_count));
 
 static const notmuch_show_format_t format_reply = {
-NULL,
-   NULL, NULL,
-   NULL, NULL, NULL,
-   NULL, reply_part, NULL, NULL, NULL,
-   NULL, NULL,
-NULL
+,
+   , NULL,
+   , NULL, ,
+   , reply_part, NULL, , ,
+   , ,
+
 };
 
 static void
diff --git a/show-message.c b/show-message.c
index 2ec9eca..32bb860 100644
--- a/show-message.c
+++ b/show-message.c
@@ -46,7 +46,7 @@ show_message_part (GMimeObject *part,
 selected = (params-part = 0 || state-part_count == params-part);
 
 if (selected || state-in_zone) {
-   if (!first  (params-part = 0 || state-in_zone)  format-part_sep)
+   if (!first  (params-part = 0 || state-in_zone))
fputs (format-part_sep, stdout);
 
format-part (part, (state-part_count));
-- 
1.7.4.4

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


[PATCH 05/11] test: new test-lib function to test for equality between files

2011-05-25 Thread Jameson Graef Rollins
We need to be able to test for the presence of a newline at the end of
output.  There's no good way to capture trailing newlines in bash, so
redirecting output to a file is the next best thing.  This new
function should be used when testing for output that is expected to
have trailing newlines.

The next commit will demonstrate the use of this.
---
 test/test-lib.sh |   23 +++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/test/test-lib.sh b/test/test-lib.sh
index f536172..9e2e0b5 100755
--- a/test/test-lib.sh
+++ b/test/test-lib.sh
@@ -441,6 +441,29 @@ test_expect_equal ()
 fi
 }
 
+test_expect_equal_file ()
+{
+   exec 16 27  # Restore stdout and stderr
+   inside_subtest=
+   test $# = 3  { prereq=$1; shift; } || prereq=
+   test $# = 2 ||
+   error bug in the test script: not 2 or 3 parameters to 
test_expect_equal
+
+   output=$1
+   expected=$2
+   if ! test_skip $@
+   then
+   if diff -q $expected $output /dev/null ; then
+   test_ok_ $test_subtest_name
+   else
+   testname=$this_test.$test_count
+   mv $output $testname.output
+   mv $expected $testname.expected
+   test_failure_ $test_subtest_name $(diff -u 
$testname.expected $testname.output)
+   fi
+fi
+}
+
 test_expect_equal_failure ()
 {
exec 16 27  # Restore stdout and stderr
-- 
1.7.4.4

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


[PATCH 01/11] Simplify reply_part function to eliminate redundant code paths.

2011-05-25 Thread Jameson Graef Rollins
This is the same logic but with less code.
---
 notmuch-reply.c |   41 ++---
 1 files changed, 14 insertions(+), 27 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index ab15650..5d72b1f 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -88,31 +88,8 @@ static void
 reply_part (GMimeObject *part,
unused (int *part_count))
 {
-GMimeContentDisposition *disposition;
-GMimeContentType *content_type;
-
-disposition = g_mime_object_get_content_disposition (part);
-if (disposition 
-   strcmp (disposition-disposition, GMIME_DISPOSITION_ATTACHMENT) == 0)
-{
-   const char *filename = g_mime_part_get_filename (GMIME_PART (part));
-   content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
-
-   if (g_mime_content_type_is_type (content_type, text, *) 
-   !g_mime_content_type_is_type (content_type, text, html))
-   {
-   reply_part_content (part);
-   }
-   else
-   {
-   printf (Attachment: %s (%s)\n, filename,
-   g_mime_content_type_to_string (content_type));
-   }
-
-   return;
-}
-
-content_type = g_mime_object_get_content_type (GMIME_OBJECT (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, *) 
!g_mime_content_type_is_type (content_type, text, html))
@@ -121,8 +98,18 @@ reply_part (GMimeObject *part,
 }
 else
 {
-   printf (Non-text part: %s\n,
-   g_mime_content_type_to_string (content_type));
+   if (disposition 
+   strcmp (disposition-disposition, GMIME_DISPOSITION_ATTACHMENT) == 
0)
+   {
+   const char *filename = g_mime_part_get_filename (GMIME_PART (part));
+   printf (Attachment: %s (%s)\n, filename,
+   g_mime_content_type_to_string (content_type));
+   }
+   else
+   {
+   printf (Non-text part: %s\n,
+   g_mime_content_type_to_string (content_type));
+   }
 }
 }
 
-- 
1.7.4.4

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


[PATCH 09/11] Add decryption of PGP/MIME-encrypted parts with --decrypt.

2011-05-25 Thread Jameson Graef Rollins
This adds support for decrypting PGP/MIME-encrypted parts to
notmuch-show and notmuch-reply.  The --decrypt option implies
--verify.  Once decryption (and possibly signature verification) is
done, a new part_encstatus formatter is emitted, the part_sigstatus
formatter is emitted, and the entire multipart/encrypted part is
replaced by the contents of the encrypted part.

At the moment only a json part_encstatus formatting function is
available, even though decryption is done for all formats.  Emacs
support to follow.
---
 notmuch-client.h |2 ++
 notmuch-reply.c  |   36 
 notmuch-show.c   |   25 -
 notmuch.1|   11 +++
 notmuch.c|8 
 show-message.c   |   29 -
 6 files changed, 101 insertions(+), 10 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index dc4ed7a..8a27260 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -67,6 +67,7 @@ typedef struct notmuch_show_format {
 const char *body_start;
 void (*part_start) (GMimeObject *part,
int *part_count);
+void (*part_encstatus) (int status);
 void (*part_sigstatus) (const GMimeSignatureValidity* validity);
 void (*part_content) (GMimeObject *part);
 void (*part_end) (GMimeObject *part);
@@ -82,6 +83,7 @@ typedef struct notmuch_show_params {
 int raw;
 int part;
 GMimeCipherContext* cryptoctx;
+int decrypt;
 } notmuch_show_params_t;
 
 /* There's no point in continuing when we've detected that we've done
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 99bb15f..5265af6 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -34,6 +34,7 @@ static const notmuch_show_format_t format_reply = {
,
NULL,
NULL,
+   NULL,
reply_part_content,
NULL,
,
@@ -438,7 +439,10 @@ guess_from_received_header (notmuch_config_t *config, 
notmuch_message_t *message
 }
 
 static int
-notmuch_reply_format_default(void *ctx, notmuch_config_t *config, 
notmuch_query_t *query)
+notmuch_reply_format_default(void *ctx,
+notmuch_config_t *config,
+notmuch_query_t *query,
+notmuch_show_params_t *params)
 {
 GMimeMessage *reply;
 notmuch_messages_t *messages;
@@ -446,9 +450,6 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t 
*config, notmuch_query_
 const char *subject, *from_addr = NULL;
 const char *in_reply_to, *orig_references, *references;
 const notmuch_show_format_t *format = format_reply;
-notmuch_show_params_t params;
-params.part = -1;
-params.cryptoctx = NULL;
 
 for (messages = notmuch_query_search_messages (query);
 notmuch_messages_valid (messages);
@@ -508,7 +509,7 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t 
*config, notmuch_query_
notmuch_message_get_header (message, from));
 
show_message_body (notmuch_message_get_filename (message),
-  format, params);
+  format, params);
 
notmuch_message_destroy (message);
 }
@@ -517,7 +518,10 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t 
*config, notmuch_query_
 
 /* This format is currently tuned for a git send-email --notmuch hook */
 static int
-notmuch_reply_format_headers_only(void *ctx, notmuch_config_t *config, 
notmuch_query_t *query)
+notmuch_reply_format_headers_only(void *ctx,
+ notmuch_config_t *config,
+ notmuch_query_t *query,
+ unused (notmuch_show_params_t *params))
 {
 GMimeMessage *reply;
 notmuch_messages_t *messages;
@@ -579,9 +583,12 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
 notmuch_query_t *query;
 char *opt, *query_string;
 int i, ret = 0;
-int (*reply_format_func)(void *ctx, notmuch_config_t *config, 
notmuch_query_t *query);
+int (*reply_format_func)(void *ctx, notmuch_config_t *config, 
notmuch_query_t *query, notmuch_show_params_t *params);
+notmuch_show_params_t params;
 
 reply_format_func = notmuch_reply_format_default;
+params.part = -1;
+params.cryptoctx = NULL;
 
 for (i = 0; i  argc  argv[i][0] == '-'; i++) {
if (strcmp (argv[i], --) == 0) {
@@ -598,6 +605,16 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
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(notmuch_gmime_session_get_type(), NULL);
+   if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, 
gpg)))
+   fprintf (stderr, Failed to construct gpg 

[PATCH 02/11] Integrate reply_part_content function into reply_part function.

2011-05-25 Thread Jameson Graef Rollins
After the last patch to eliminate some redundant code paths in
reply_part, the reply_part_content function was only being called
once.  Disolving the function and integrating its contents into the
reply_part function makes things a little simpler, and frees up some
name space that will be needed in the next patch.
---
 notmuch-reply.c |   52 +++-
 1 files changed, 23 insertions(+), 29 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index 5d72b1f..8c5e76c 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -38,34 +38,6 @@ static const notmuch_show_format_t format_reply = {
 };
 
 static void
-reply_part_content (GMimeObject *part)
-{
-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);
-}
-
-static void
 show_reply_headers (GMimeMessage *message)
 {
 GMimeStream *stream_stdout = NULL, *stream_filter = NULL;
@@ -94,7 +66,29 @@ reply_part (GMimeObject *part,
 if (g_mime_content_type_is_type (content_type, text, *) 
!g_mime_content_type_is_type (content_type, text, html))
 {
-   reply_part_content (part);
+   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);
 }
 else
 {
-- 
1.7.4.4

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


[PATCH 07/11] test: add crypto tests for signature verification and decryption

2011-05-25 Thread Jameson Graef Rollins
This adds a new crypto test script to the test suite to test
PGP/MIME signature verification and message decryption.  Included here
is a test GNUPGHOME with a test secret key (passwordless), and test
for:

  * signing/verification
  * signing/verification with full owner trust
  * verification with signer key unavailable
  * encryption/decryption
  * decryption failure with missing key
  * encryption/decryption + signing/verfifying
  * reply to encrypted message
  * verification of signature from revoked key

These tests are not expected to pass now, but will as crypto
functionality is included.
---
 test/basic |5 +-
 test/crypto|  330 
 test/gnupg-secret-key.NOTE |9 ++
 test/gnupg-secret-key.asc  |   34 +
 test/notmuch-test  |1 +
 test/test-lib.sh   |   29 
 6 files changed, 407 insertions(+), 1 deletions(-)
 create mode 100755 test/crypto
 create mode 100644 test/gnupg-secret-key.NOTE
 create mode 100644 test/gnupg-secret-key.asc

diff --git a/test/basic b/test/basic
index 3b43ad9..d6c0d00 100755
--- a/test/basic
+++ b/test/basic
@@ -57,7 +57,10 @@ available=$(ls -1 ../ | \
 sed -r -e 
/^(aggregate-results.sh|Makefile|Makefile.local|notmuch-test)/d \
   -e /^(README|test-lib.sh|test-results|tmp.*|valgrind|corpus*)/d \
   -e 
/^(emacs.expected-output|smtp-dummy|smtp-dummy.c|test-verbose)/d \
-  -e /^(test.expected-output|.*~)/d | sort)
+  -e /^(test.expected-output|.*~)/d \
+  -e /^(gnupg-secret-key.asc)/d \
+  -e /^(gnupg-secret-key.NOTE)/d \
+  | sort)
 test_expect_equal $tests_in_suite $available
 
 EXPECTED=../test.expected-output
diff --git a/test/crypto b/test/crypto
new file mode 100755
index 000..3b0f381
--- /dev/null
+++ b/test/crypto
@@ -0,0 +1,330 @@
+#!/bin/bash
+
+# TODO:
+# - decryption/verification with signer key not available
+# - verification of signatures from expired/revoked keys
+
+test_description='PGP/MIME signature verification and decryption'
+. ./test-lib.sh
+
+add_gnupg_home ()
+{
+local output
+[ -d ${GNUPGHOME} ]  return
+mkdir -m 0700 $GNUPGHOME
+gpg --no-tty --import ../gnupg-secret-key.asc $GNUPGHOME/import.log 
21
+test_debug cat $GNUPGHOME/import.log
+if (gpg --quick-random --version /dev/null 21) ; then
+   echo quick-random  $GNUPGHOME/gpg.conf
+elif (gpg --debug-quick-random --version /dev/null 21) ; then
+   echo debug-quick-random  $GNUPGHOME/gpg.conf
+fi
+}
+
+##
+
+add_gnupg_home
+# get key fingerprint
+FINGERPRINT=$(gpg --no-tty --list-secret-keys --with-colons --fingerprint | 
grep '^fpr:' | cut -d: -f10)
+
+# for some reason this is needed for emacs_deliver_message to work,
+# although I can't figure out why
+add_email_corpus
+
+test_expect_success 'emacs delivery of signed message' \
+'emacs_deliver_message \
+test signed message 001 \
+This is a test signed message. \
+(mml-secure-message-sign)'
+
+test_begin_subtest signature verification
+output=$(notmuch show --format=json --verify subject:test signed message 001 
\
+| notmuch_json_show_sanitize \
+| sed -e 's|created: [1234567890]*|created: 946728000|')
+expected='[[[{id: X,
+ match: true,
+ filename: Y,
+ timestamp: 946728000,
+ date_relative: 2000-01-01,
+ tags: [inbox],
+ headers: {Subject: test signed message 001,
+ From: Notmuch Test Suite test_su...@notmuchmail.org,
+ To: test_su...@notmuchmail.org,
+ Cc: ,
+ Bcc: ,
+ Date: 01 Jan 2000 12:00:00 -},
+ body: [{id: 1,
+ sigstatus: [{status: good,
+ fingerprint: '$FINGERPRINT',
+ created: 946728000}],
+ content-type: text/plain,
+ content: This is a test signed message.\n}]},
+ ['
+test_expect_equal \
+$output \
+$expected
+
+test_begin_subtest signature verification with full owner trust
+# give the key full owner trust
+echo ${FINGERPRINT}:6: | gpg --no-tty --import-ownertrust 
$GNUPGHOME/trust.log 21
+gpg --no-tty --check-trustdb $GNUPGHOME/trust.log 21
+output=$(notmuch show --format=json --verify subject:test signed message 001 
\
+| notmuch_json_show_sanitize \
+| sed -e 's|created: [1234567890]*|created: 946728000|')
+expected='[[[{id: X,
+ match: true,
+ filename: Y,
+ timestamp: 946728000,
+ date_relative: 2000-01-01,
+ tags: [inbox],
+ headers: {Subject: test signed message 001,
+ From: Notmuch Test Suite test_su...@notmuchmail.org,
+ To: test_su...@notmuchmail.org,
+ Cc: ,
+ Bcc: ,
+ Date: 01 Jan 2000 12:00:00 -},
+ body: [{id: 1,
+ sigstatus: [{status: good,
+ fingerprint: '$FINGERPRINT',
+ created: 946728000,
+ userid:  Notmuch Test Suite test_su...@notmuchmail.org (INSECURE!)}],
+ content-type: text/plain,
+ content: This is a test signed message.\n}]},
+ ['
+test_expect_equal \
+$output \
+$expected
+
+test_begin_subtest signature verification with signer key unavailable
+# move the gnupghome temporarily 

[PATCH 06/11] test: add notmuch_show_sanitize_all function that is a little more aggressive.

2011-05-25 Thread Jameson Graef Rollins
The old notmuch_show_sanitize function only scrubed part of the
filename.  This one scrubs the full filename, as well as the message
id.
---
 test/test-lib.sh |6 ++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/test/test-lib.sh b/test/test-lib.sh
index 9e2e0b5..ae25635 100755
--- a/test/test-lib.sh
+++ b/test/test-lib.sh
@@ -502,6 +502,12 @@ notmuch_show_sanitize ()
 {
 sed -e $NOTMUCH_SHOW_FILENAME_SQUELCH
 }
+notmuch_show_sanitize_all ()
+{
+sed \
+   -e 's| filename:.*| filename:X|' \
+   -e 's| id:[^ ]* | id:X |'
+}
 
 # End of notmuch helper functions
 
-- 
1.7.4.4

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


[PATCH 04/11] Break up format-part function into part_start and part_content functions.

2011-05-25 Thread Jameson Graef Rollins
Future improvements (eg. crypto support) will require adding new part
header.  By breaking up the output of part headers from the output of
part content, we can easily out new part headers with new formatting
functions.
---
 notmuch-client.h |5 +-
 notmuch-reply.c  |   13 --
 notmuch-show.c   |  122 +++--
 show-message.c   |4 +-
 4 files changed, 85 insertions(+), 59 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index 7221c68..b278bc7 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -65,8 +65,9 @@ typedef struct notmuch_show_format {
notmuch_message_t *message);
 const char *header_end;
 const char *body_start;
-void (*part) (GMimeObject *part,
- int *part_count);
+void (*part_start) (GMimeObject *part,
+   int *part_count);
+void (*part_content) (GMimeObject *part);
 void (*part_end) (GMimeObject *part);
 const char *part_sep;
 const char *body_end;
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 7959935..9c35475 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -25,14 +25,18 @@
 #include gmime-filter-headers.h
 
 static void
-reply_part (GMimeObject *part,
-   unused (int *part_count));
+reply_part_content (GMimeObject *part);
 
 static const notmuch_show_format_t format_reply = {
 ,
, NULL,
, NULL, ,
-   , reply_part, NULL, , ,
+   ,
+   NULL,
+   reply_part_content,
+   NULL,
+   ,
+   ,
, ,
 
 };
@@ -57,8 +61,7 @@ show_reply_headers (GMimeMessage *message)
 }
 
 static void
-reply_part (GMimeObject *part,
-   unused (int *part_count))
+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);
diff --git a/notmuch-show.c b/notmuch-show.c
index 65c780e..363cdbf 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -29,8 +29,11 @@ format_headers_text (const void *ctx,
 notmuch_message_t *message);
 
 static void
-format_part_text (GMimeObject *part,
- int *part_count);
+format_part_start_text (GMimeObject *part,
+   int *part_count);
+
+static void
+format_part_content_text (GMimeObject *part);
 
 static void
 format_part_end_text (GMimeObject *part);
@@ -39,7 +42,12 @@ static const notmuch_show_format_t format_text = {
 ,
\fmessage{ , format_message_text,
\fheader{\n, format_headers_text, \fheader}\n,
-   \fbody{\n, format_part_text, format_part_end_text, , 
\fbody}\n,
+   \fbody{\n,
+   format_part_start_text,
+   format_part_content_text,
+   format_part_end_text,
+   ,
+   \fbody}\n,
\fmessage}\n, ,
 
 };
@@ -53,8 +61,11 @@ format_headers_json (const void *ctx,
 notmuch_message_t *message);
 
 static void
-format_part_json (GMimeObject *part,
- int *part_count);
+format_part_start_json (unused (GMimeObject *part),
+   int *part_count);
+
+static void
+format_part_content_json (GMimeObject *part);
 
 static void
 format_part_end_json (GMimeObject *part);
@@ -63,7 +74,12 @@ static const notmuch_show_format_t format_json = {
 [,
{, format_message_json,
, \headers\: {, format_headers_json, },
-   , \body\: [, format_part_json, format_part_end_json, , , ],
+   , \body\: [,
+   format_part_start_json,
+   format_part_content_json,
+   format_part_end_json,
+   , ,
+   ],
}, , ,
 ]
 };
@@ -77,20 +93,29 @@ static const notmuch_show_format_t format_mbox = {
 ,
 , format_message_mbox,
 , NULL, ,
-, NULL, NULL, , ,
+,
+NULL,
+NULL,
+NULL,
+,
+,
 , ,
 
 };
 
 static void
-format_part_raw (GMimeObject *part,
-unused (int *part_count));
+format_part_content_raw (GMimeObject *part);
 
 static const notmuch_show_format_t format_raw = {
 ,
, NULL,
, NULL, ,
-, format_part_raw, NULL, , ,
+,
+NULL,
+format_part_content_raw,
+NULL,
+,
+,
, ,
 
 };
@@ -372,46 +397,41 @@ show_part_content (GMimeObject *part, GMimeStream 
*stream_out)
 }
 
 static void
-format_part_text (GMimeObject *part, int *part_count)
+format_part_start_text (GMimeObject *part, int *part_count)
 {
-GMimeContentDisposition *disposition;
-GMimeContentType *content_type;
+GMimeContentDisposition *disposition = 
g_mime_object_get_content_disposition (part);
 
-disposition 

[PATCH 10/11] emacs: Add support for PGP/MIME verification/decryption

2011-05-25 Thread Jameson Graef Rollins
A new emacs configuration variable notmuch-crypto-process-mime
controls the processing of PGP/MIME signatures and encrypted parts.
When this is set true, notmuch-query will use the notmuch show
--decrypt flag to decrypt encrypted messages and/or calculate the
sigstatus of signed messages.  If sigstatus is available, notmuch-show
will place a specially color-coded header at the begining of the
signed message.

Also included is the ability to switch decryption/verification on/off
on the fly, which is bound to M-RET in notmuch-search-mode.
---
 emacs/Makefile.local|1 +
 emacs/notmuch-crypto.el |  104 +++
 emacs/notmuch-lib.el|5 ++
 emacs/notmuch-mua.el|9 +++-
 emacs/notmuch-query.el  |7 ++-
 emacs/notmuch-show.el   |   65 -
 emacs/notmuch.el|   10 -
 7 files changed, 175 insertions(+), 26 deletions(-)
 create mode 100644 emacs/notmuch-crypto.el

diff --git a/emacs/Makefile.local b/emacs/Makefile.local
index 1c09d87..1022777 100644
--- a/emacs/Makefile.local
+++ b/emacs/Makefile.local
@@ -12,6 +12,7 @@ emacs_sources := \
$(dir)/notmuch-address.el \
$(dir)/notmuch-maildir-fcc.el \
$(dir)/notmuch-message.el \
+   $(dir)/notmuch-crypto.el \
$(dir)/coolj.el
 
 emacs_images := \
diff --git a/emacs/notmuch-crypto.el b/emacs/notmuch-crypto.el
new file mode 100644
index 000..944452b
--- /dev/null
+++ b/emacs/notmuch-crypto.el
@@ -0,0 +1,104 @@
+;; notmuch-crypto.el --- functions for handling display of cryptographic 
metadata.
+;;
+;; Copyright © Jameson Rollins
+;;
+;; This file is part of Notmuch.
+;;
+;; Notmuch is free software: you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Notmuch is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Notmuch.  If not, see http://www.gnu.org/licenses/.
+;;
+;; Authors: Jameson Rollins jroll...@finestructure.net
+
+(defcustom notmuch-crypto-process-mime nil
+  Should cryptographic MIME parts be processed?
+
+If this variable is non-nil signatures in multipart/signed
+messages will be verified and multipart/encrypted parts will be
+decrypted.  The result of the crypto operation will be displayed
+in a specially colored header button at the top of the processed
+part.  Signed parts will have variously colored headers depending
+on the success or failure of the verification process and on the
+validity of user ID of the signer.
+
+The effect of setting this variable can be seen temporarily by
+viewing a signed or encrypted message with M-RET in notmuch
+search.
+  :group 'notmuch
+  :type 'boolean)
+
+(define-button-type 'notmuch-crypto-status-button-type
+  'action '(lambda (button) (message (button-get button 'help-echo)))
+  'follow-link t
+  'help-echo Set notmuch-crypto-process-mime to process cryptographic mime 
parts.
+  'face '(:foreground blue)
+  'mouse-face '(:foreground blue))
+
+(defun notmuch-crypto-insert-sigstatus-button (sigstatus from)
+  (let* ((status (plist-get sigstatus :status))
+(help-msg nil)
+(label multipart/signed: signature not processed)
+(face '(:background red :foreground black)))
+(cond
+ ((string= status good)
+  ; if userid present, userid has full or greater validity
+  (if (plist-member sigstatus :userid)
+ (let ((userid (plist-get sigstatus :userid)))
+   (setq label (concat Good signature by:  userid))
+   (setq face '(:background green :foreground black)))
+   (let ((fingerprint (concat 0x (plist-get sigstatus :fingerprint
+ (setq label (concat Good signature by key:  fingerprint))
+ (setq face '(:background orange :foreground black)
+ ((string= status error)
+  (let ((keyid (concat 0x (plist-get sigstatus :keyid
+   (setq label (concat Unknown key ID  keyid  or unsupported 
algorithm))
+   (setq face '(:background red :foreground black
+ ((string= status bad)
+  (let ((keyid (concat 0x (plist-get sigstatus :keyid
+   (setq label (concat Bad signature (claimed key ID  keyid )))
+   (setq face '(:background red :foreground black
+ (t
+  (setq label Unknown signature status)
+  (if status (setq label (concat label  \ status \)
+(insert-button
+ (concat [  label  ])
+ :type 'notmuch-crypto-status-button-type
+ 'help-echo help-msg
+ 'face face
+ 'mouse-face face
+ :notmuch-sigstatus sigstatus
+ :notmuch-from from)
+(insert \n)))
+
+(defun 

[PATCH 08/11] Add signature verification of PGP/MIME-signed parts with --verify.

2011-05-25 Thread Jameson Graef Rollins
This is primarily for notmuch-show, although the functionality is
added to show-message.  Once signatures are processed a new
part_sigstatus formatter is emitted, and the entire multipart/signed
part is replaced with the contents of the signed part.

At the moment only a json part_sigstatus formatting function is
available.  Emacs support to follow.

The original work for this patch was done by

  Daniel Kahn Gillmor d...@fifthhorseman.net

whose help with this functionality I greatly appreciate.
---
 Makefile.local  |1 +
 notmuch-client.h|5 ++
 notmuch-gmime-session.c |   49 
 notmuch-reply.c |2 +
 notmuch-show.c  |   96 +++
 notmuch.1   |   11 +
 notmuch.c   |8 
 show-message.c  |   41 +++-
 8 files changed, 212 insertions(+), 1 deletions(-)
 create mode 100644 notmuch-gmime-session.c

diff --git a/Makefile.local b/Makefile.local
index 8a8832d..f726f1f 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -246,6 +246,7 @@ notmuch_client_srcs =   \
notmuch-show.c  \
notmuch-tag.c   \
notmuch-time.c  \
+   notmuch-gmime-session.c \
query-string.c  \
show-message.c  \
json.c  \
diff --git a/notmuch-client.h b/notmuch-client.h
index b278bc7..dc4ed7a 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -67,6 +67,7 @@ typedef struct notmuch_show_format {
 const char *body_start;
 void (*part_start) (GMimeObject *part,
int *part_count);
+void (*part_sigstatus) (const GMimeSignatureValidity* validity);
 void (*part_content) (GMimeObject *part);
 void (*part_end) (GMimeObject *part);
 const char *part_sep;
@@ -80,6 +81,7 @@ typedef struct notmuch_show_params {
 int entire_thread;
 int raw;
 int part;
+GMimeCipherContext* cryptoctx;
 } notmuch_show_params_t;
 
 /* There's no point in continuing when we've detected that we've done
@@ -233,4 +235,7 @@ notmuch_config_set_maildir_synchronize_flags 
(notmuch_config_t *config,
 notmuch_bool_t
 debugger_is_active (void);
 
+GType
+notmuch_gmime_session_get_type (void);
+
 #endif
diff --git a/notmuch-gmime-session.c b/notmuch-gmime-session.c
new file mode 100644
index 000..d83d9b3
--- /dev/null
+++ b/notmuch-gmime-session.c
@@ -0,0 +1,49 @@
+#include notmuch-client.h
+
+/* CRUFTY BOILERPLATE for GMimeSession (dkg thinks this will go away once 
GMime 2.6 comes out) */
+typedef struct _NotmuchGmimeSession NotmuchGmimeSession;
+typedef struct _NotmuchGmimeSessionClass NotmuchGmimeSessionClass;
+
+struct _NotmuchGmimeSession {
+GMimeSession parent_object;
+};
+
+struct _NotmuchGmimeSessionClass {
+GMimeSessionClass parent_class;
+};
+
+static void notmuch_gmime_session_class_init (NotmuchGmimeSessionClass *klass);
+
+static GMimeSessionClass *parent_class = NULL;
+
+GType
+notmuch_gmime_session_get_type (void)
+{
+static GType type = 0;
+
+if (!type) {
+   static const GTypeInfo info = {
+   sizeof (NotmuchGmimeSessionClass),
+   NULL, /* base_class_init */
+   NULL, /* base_class_finalize */
+   (GClassInitFunc) notmuch_gmime_session_class_init,
+   NULL, /* class_finalize */
+   NULL, /* class_data */
+   sizeof (NotmuchGmimeSession),
+   0,/* n_preallocs */
+   NULL, /* object_init */
+   NULL, /* value_table */
+   };
+   type = g_type_register_static (GMIME_TYPE_SESSION, 
NotmuchGmimeSession, info, 0);
+}
+return type;
+}
+
+static void
+notmuch_gmime_session_class_init (NotmuchGmimeSessionClass *klass)
+{
+GMimeSessionClass *session_class = GMIME_SESSION_CLASS (klass);
+parent_class = g_type_class_ref (GMIME_TYPE_SESSION);
+session_class-request_passwd = NULL;
+}
+/* END CRUFTY BOILERPLATE */
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 9c35475..99bb15f 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -33,6 +33,7 @@ static const notmuch_show_format_t format_reply = {
, NULL, ,
,
NULL,
+   NULL,
reply_part_content,
NULL,
,
@@ -447,6 +448,7 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t 
*config, notmuch_query_
 const notmuch_show_format_t *format = format_reply;
 notmuch_show_params_t params;
 params.part = -1;
+params.cryptoctx = NULL;
 
 for (messages = notmuch_query_search_messages (query);
 notmuch_messages_valid (messages);
diff --git a/notmuch-show.c b/notmuch-show.c
index 363cdbf..bb54e56 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -44,6 +44,7 @@ static const notmuch_show_format_t format_text = {
\fheader{\n, format_headers_text, \fheader}\n,
\fbody{\n,
format_part_start_text,
+

[PATCH 11/11] tag signed/encrypted during notmuch new

2011-05-25 Thread Jameson Graef Rollins
This patch adds the tag signed to messages with any multipart/signed
parts, and the tag encrypted to messages with any
multipart/encrypted parts.  This only occurs when messages are indexed
during notmuch new, so a database rebuild is required to have old
messages tagged.
---
 lib/index.cc   |6 ++
 test/crypto|   16 
 .../emacs.expected-output/notmuch-hello-view-inbox |6 +++---
 .../emacs.expected-output/notmuch-search-tag-inbox |6 +++---
 .../notmuch-show-thread-maildir-storage|8 
 test/multipart |4 ++--
 test/search|6 +++---
 test/search-output |2 ++
 8 files changed, 31 insertions(+), 23 deletions(-)

diff --git a/lib/index.cc b/lib/index.cc
index bdfb8ed..e8e9922 100644
--- a/lib/index.cc
+++ b/lib/index.cc
@@ -325,6 +325,12 @@ _index_mime_part (notmuch_message_t *message,
GMimeMultipart *multipart = GMIME_MULTIPART (part);
int i;
 
+   if (GMIME_IS_MULTIPART_SIGNED (multipart))
+ _notmuch_message_add_term (message, tag, signed);
+
+   if (GMIME_IS_MULTIPART_ENCRYPTED (multipart))
+ _notmuch_message_add_term (message, tag, encrypted);
+
for (i = 0; i  g_mime_multipart_get_count (multipart); i++) {
if (GMIME_IS_MULTIPART_SIGNED (multipart)) {
/* Don't index the signature. */
diff --git a/test/crypto b/test/crypto
index 3b0f381..c5abcc3 100755
--- a/test/crypto
+++ b/test/crypto
@@ -46,7 +46,7 @@ expected='[[[{id: X,
  filename: Y,
  timestamp: 946728000,
  date_relative: 2000-01-01,
- tags: [inbox],
+ tags: [inbox,signed],
  headers: {Subject: test signed message 001,
  From: Notmuch Test Suite test_su...@notmuchmail.org,
  To: test_su...@notmuchmail.org,
@@ -76,7 +76,7 @@ expected='[[[{id: X,
  filename: Y,
  timestamp: 946728000,
  date_relative: 2000-01-01,
- tags: [inbox],
+ tags: [inbox,signed],
  headers: {Subject: test signed message 001,
  From: Notmuch Test Suite test_su...@notmuchmail.org,
  To: test_su...@notmuchmail.org,
@@ -106,7 +106,7 @@ expected='[[[{id: X,
  filename: Y,
  timestamp: 946728000,
  date_relative: 2000-01-01,
- tags: [inbox],
+ tags: [inbox,signed],
  headers: {Subject: test signed message 001,
  From: Notmuch Test Suite test_su...@notmuchmail.org,
  To: test_su...@notmuchmail.org,
@@ -141,7 +141,7 @@ output=$(notmuch show --format=text --decrypt subject:test 
encrypted message 00
 | sed -e 's|created: [1234567890]*|created: 946728000|')
 expected='message{ id:X depth:0 match:1 filename:X
 header{
-Notmuch Test Suite test_su...@notmuchmail.org (2000-01-01) (inbox)
+Notmuch Test Suite test_su...@notmuchmail.org (2000-01-01) (encrypted inbox)
 Subject: test encrypted message 001
 From: Notmuch Test Suite test_su...@notmuchmail.org
 To: test_su...@notmuchmail.org
@@ -172,7 +172,7 @@ expected='[[[{id: X,
  filename: Y,
  timestamp: 946728000,
  date_relative: 2000-01-01,
- tags: [inbox],
+ tags: [encrypted,inbox],
  headers: {Subject: test encrypted message 001,
  From: Notmuch Test Suite test_su...@notmuchmail.org,
  To: test_su...@notmuchmail.org,
@@ -223,7 +223,7 @@ expected='[[[{id: X,
  filename: Y,
  timestamp: 946728000,
  date_relative: 2000-01-01,
- tags: [inbox],
+ tags: [encrypted,inbox],
  headers: {Subject: test encrypted message 001,
  From: Notmuch Test Suite test_su...@notmuchmail.org,
  To: test_su...@notmuchmail.org,
@@ -258,7 +258,7 @@ expected='[[[{id: X,
  filename: Y,
  timestamp: 946728000,
  date_relative: 2000-01-01,
- tags: [inbox],
+ tags: [encrypted,inbox],
  headers: {Subject: test encrypted message 002,
  From: Notmuch Test Suite test_su...@notmuchmail.org,
  To: test_su...@notmuchmail.org,
@@ -309,7 +309,7 @@ expected='[[[{id: X,
  filename: Y,
  timestamp: 946728000,
  date_relative: 2000-01-01,
- tags: [inbox],
+ tags: [inbox,signed],
  headers: {Subject: test signed message 001,
  From: Notmuch Test Suite test_su...@notmuchmail.org,
  To: test_su...@notmuchmail.org,
diff --git a/test/emacs.expected-output/notmuch-hello-view-inbox 
b/test/emacs.expected-output/notmuch-hello-view-inbox
index 6472c46..894ae5f 100644
--- a/test/emacs.expected-output/notmuch-hello-view-inbox
+++ b/test/emacs.expected-output/notmuch-hello-view-inbox
@@ -1,16 +1,16 @@
   2009-11-17 [5/5]   Mikhail Gusarov, Carl Worth, Keith Packard  [notmuch] 
[PATCH 1/2] Close message file after parsing message headers (inbox unread)
-  2009-11-17 [7/7]   Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, 
Carl Worth  [notmuch] Working with Maildir storage? (inbox unread)
+  2009-11-17 [7/7]   Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, 
Carl Worth  [notmuch] Working with Maildir storage? (inbox signed unread)
   2009-11-17 [2/2]   Alex Botero-Lowry, Carl Worth  [notmuch] 

Re: [PATCH 3/5] Fix hiding a message while some citations are shown in notmuch-show view.

2011-05-25 Thread Carl Worth
On Thu, 26 May 2011 03:10:11 +0400, Dmitry Kurochkin 
dmitry.kuroch...@gmail.com wrote:
 On Wed, 25 May 2011 15:46:40 -0700, Carl Worth cwo...@cworth.org wrote:
 Well, emacs trunk is not broken :)  The bug is in lisp code, so you can
 fix it in .emacs by redefining `isearch-range-invisible' function.  I do
 that now.

Oh, in that case we can fix this is notmuch emacs lisp by just defining
and using a fixed function. Is the broken function something we're
calling directly? Or is it being called indirectly? (being called by
other emacs lisp code that we are calling)?

If we can incorporate the fix, that would be great.

 Please consider pushing other patches from the series.  They do not fix
 any bug, but do simplify the code.  The last patch uses list for
 invisible overlay property as well.  But it does not break isearch
 because we do not search in hidden messages.

Hmmm... we should probably do that. I'd like isearch in notmuch to
search anything that is hidden.

 BTW would be nice to have a set of known-to-fail tests, i.e. bugs that
 are not fixed yet.  If we had it, the above test could be implemented
 and committed before we have the fix pushed.

We do! Use test_expect_equal_failure (yes, the name is horrible!)
instead of test_expect_equal and you should get what you want.

-Carl

-- 
carl.d.wo...@intel.com


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


Re: [PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Carl Worth
On Thu, 26 May 2011 01:21:17 +0200, Daniel Schoepe 
daniel.scho...@googlemail.com wrote:
 Since the main difference between those sections is the clear visual
 distinction, it might be an option to provide the user with functions to
 easily declare new sections for the hello screen, where this sort of
 thing is configurable. 

Yes!

This sounds very much like what I want myself. (I'm planning to write a
new How I process mail post summarizing some things I've learned about
notmuch and my personal habits over the past two months.)

I definitely have two very distinct groups of saved searches based on
how I use them. And it would be nice to have them visually separated in
the interface.

-Carl

-- 
carl.d.wo...@intel.com


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


Re: [PATCH] emacs: Make the queries used in the all-tags section

2011-05-25 Thread Austin Clements
On May 25, 2011 7:21 PM, Daniel Schoepe daniel.scho...@googlemail.com
wrote:

 On Wed, 25 May 2011 18:42:30 -0400, Austin Clements amdra...@mit.edu
wrote:
  'Doh.  That's what I get for not reading the surrounding code.  I
  misunderstood what your patch was going for and assumed it was what
  *I* wanted notmuch to do, which is to show me useful counts (e.g.,
  unread count), but not to change the underlying query.  ]:--8)

 I thought about that too, but figured it should be rather rare that
 someone wants only a portion of some messages _counted_, but all
 displayed when clicking on the search next to the count.

My use case of counting only unread messages (but still showing all of them,
like just about every other mail client out there) is an example of this.
But you're right that I can't think of any other examples (which is why I
suggested just baking this specific thing in earlier).

 I'm somewhat indifferent, since I rarely use those links
 directly, so any more opinions on this are very much appreciated.

Actually, here's a new thought that may help address your original problem
(assuming I understand it correctly now).  One of my design criteria for the
custom query parser (need to get back to those patches...) was to support
implicit tag filters such as hiding everything with tag:spam or tag:killed
(or tag:muted, etc) unless these tags are specifically requested by a
query.  That would apply equally to generated queries like the all tags
list, so you could filter out tag:killed messages centrally using a
mechanism like this, rather than having to work it in to every query
somehow.

  So, to me, it seems like this turns the all tags section into another
  saved searches section, just with a slight twist, and makes me wonder
  if there's a better way to reconcile these.

 Well, it already was sort of a non-configurable saved searches section
 before, so I didn't really turn it into one. :)

True.

 Since the main difference between those sections is the clear visual
 distinction, it might be an option to provide the user with functions to
 easily declare new sections for the hello screen, where this sort of
 thing is configurable. (One possible use that comes to mind would be to
 group tags into different categories.)

That would be awesome.
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch