[PATCH] emacs: User-defined sections in notmuch-hello

2011-05-27 Thread Daniel Schoepe


one-time-iterators

2011-05-27 Thread Patrick Totzke
Excerpts from Austin Clements's message of Fri May 27 03:41:44 +0100 2011:
> >> > > Have you tried simply calling list() on your thread
> >> > > iterator to see how expensive it is? ?My bet is that it's quite cheap,
> >> > > both memory-wise and CPU-wise.
> >> > Funny thing:
> >> > ?q=Database().create_query('*')
> >> > ?time tlist = list(q.search_threads())
> >> > raises a NotmuchError(STATUS.NOT_INITIALIZED) exception. For some reason
> >> > the list constructor must read mere than once from the iterator.
> >> > So this is not an option, but even if it worked, it would show
> >> > the same behaviour as my above test..
> >>
> >> Interesting. ?Looks like the Threads class implements __len__ and that
> >> its implementation exhausts the iterator. ?Which isn't a great idea in
> >> itself, but it turns out that Python's implementation of list() calls
> >> __len__ if it's available (presumably to pre-size the list) before
> >> iterating over the object, so it exhausts the iterator before even
> >> using it.
> >>
> >> That said, if list(q.search_threads()) did work, it wouldn't give you
> >> better performance than your experiment above.
true. Nevertheless I think that list(q.search_threads())
should be equivalent to [t for t in q.search_threads()], which is
something to be fixed in the bindings. Should I file an issue somehow?
Or is enough to state this as a TODO here on the list?

> >> > would it be very hard to implement a Query.search_thread_ids() ?
> >> > This name is a bit off because it had to be done on a lower level.
> >>
> >> Lazily fetching the thread metadata on the C side would probably
> >> address your problem automatically. ?But what are you doing that
> >> doesn't require any information about the threads you're manipulating?
> > Agreed. Unfortunately, there seems to be no way to get a list of thread
> > ids or a reliable iterator thereof by using the current python bindings.
> > It would be enough for me to have the ids because then I could
> > search for the few threads I actually need individually on demand.
> 
> There's no way to do that from the C API either, so don't feel left
> out.  ]:--8)  It seems to me that the right solution to your problem
> is to make thread information lazy (effectively, everything gathered
> in lib/thread.cc:_thread_add_message).  Then you could probably
> materialize that iterator cheaply. 
Alright. I'll put this on my mental notmuch wish list and 
hope that someone will have addressed this before I run out of
ideas how to improve my UI and have time to look at this myself.
For now, I go with the [t.get_thread_id for t in q.search_threads()]
approach to cache the thread ids myself and live with the fact that
this takes time for large result sets.

> In fact, it's probably worth
> trying a hack where you put dummy information in the thread object
> from _thread_add_message and see how long it takes just to walk the
> iterator (unfortunately I don't think profiling will help much here
> because much of your time is probably spent waiting for I/O).
I don't think I understand what you mean by dummy info in a thread
object.

> I don't think there would be any downside to doing this for eager
> consumers like the CLI.
one should think so, yes.
/p
-- next part --
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20110527/8bb52855/attachment.pgp>


normalizing part numbering across PGP/MIME processing

2011-05-27 Thread Carl Worth
On Fri, 27 May 2011 03:27:35 -0700, Jameson Graef Rollins  wrote:
> Ok.  So I very much hope this patch series satisfies those who were
> bothered by the part renumbering that was happening when PGP/MIME
> parts were processed.  For signed messages we no longer modify the
> parts at all, so numbering always remains constant, and for encrypted
> messages the numbering will only change if the encrypted message is
> itself multipart.

That sounds much better to me. I think the remaining issues I have with
the patch series are very minor and can be applied after the fact. I'd
push the series right now except that I happen to have no network access
at the moment. [I'm queueing up this message for delivery, so if I'm on
top of things when I'm back in range, I'll push right away.]

So, well done, Jameson! You've been extremely patient as I sat on this
patch series for *so* long, and then made you rebuild it so many
times. I hope you think the rebuilds were at least worth it for the much
cleaner final state, (I know that the useless waiting wasn't worth it).

I promise you don't need to rebuild this branch anymore, nor keep asking
me to merge it. Go enjoy a good US-holiday weekend. You've earned it!

That said, here are the (minor) issues I have with the series:

  * More tests should be switched to the new text_expect_equal_file

This isn't a problem with the series---but will be a nice
fix. I think the current "notmuch search --output=tags *" is
broken due to a missing final newline---or at least has been
broken that way recently. So it will be nice to have this
support for testing a final newline.

  * The series duplicates some existing code into a new
emacs_deliver_message

The previously-existing code should be removed and replaced with
a call to the new function.

  * Should we set the crypto option to verify/decrypt by default?

That would certainly be convenient for me at least.

For people who don't want this, they can set the variable to
nil. But then they'll still have the following issue:

  * I'm not a fan of the M-RET option for decrypting a message

If someone is going to have encrypted messages not decrypted by
default, then they can currently decrypt by opening the message
with M-RET. But I think in common use, the user is likely to
only realize too late that they want to decrypt the message.

So what I'd love to see is a keybinding for decrypting a message
from the view of the message itself. (One natural place would be
by activating the button of the encrypted part---but a
keybinding to review with decryption would be fine too---likely
easier to code and easier to use.)

  * I can't actually get decryption to work for me. :-(

When I run "notmuch show --decrypt" on a message encrypted with
my public key I get a segfault within libgmime, specifically in
the g_mime_session_request_passwd function.

My first guess is that this is due to the fact that gpg-agent
can't be run on my system (Debian unstable):

$ gpg-agent
gpg-agent: symbol lookup error: /usr/lib/libassuan.so.0: undefined 
symbol: gpg_err_set_errno

I've got a Debian bug report queued up for this.

I also tried running the same "notmuch show" command without
gpg-agent installed. How is libgmime supposed to actually
request a password in a case like this?

Anyway, I know that not everyone has this same problem with the
series, so I'm not blocking it for this.

-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/20110527/23ad4e6a/attachment.pgp>


[PATCH] test: use `princ' instead of `message' calls in emacs tests

2011-05-27 Thread Carl Worth
On Tue, 10 May 2011 10:25:08 +0400, Dmitry Kurochkin  wrote:
> The patch replaces all (message (buffer-string)) calls in emacs
> tests with (princ (buffer-string)).  This avoids accidentally
> interpreting '%' as format specifiers and makes code simpler
> because we do not need to capture stderr.
> 
> Also, the patch works around an Emacs (23.3+1-1 on current Debian
> Unstable) segfault in "Ensure that emacs doesn't drop results"
> test.

Thanks so much for the fix! I hadn't noticed the segfault until the
recent additional include of test-lib.el, (which of course shouldn't
actually be changing anything), which seems to tickle the emacs bug a
little more frequently for me at least.

The segfault made it obvious that this was an emacs bug, but it was
annoying to hit. It will be nice to have this fix in place.

This change is pushed now.

-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/20110527/d94d24fd/attachment.pgp>


one-time-iterators

2011-05-27 Thread Austin Clements
On Fri, May 27, 2011 at 2:04 PM, Patrick Totzke
 wrote:
> Excerpts from Austin Clements's message of Fri May 27 03:41:44 +0100 2011:
>> >> > > Have you tried simply calling list() on your thread
>> >> > > iterator to see how expensive it is? ?My bet is that it's quite cheap,
>> >> > > both memory-wise and CPU-wise.
>> >> > Funny thing:
>> >> > ?q=Database().create_query('*')
>> >> > ?time tlist = list(q.search_threads())
>> >> > raises a NotmuchError(STATUS.NOT_INITIALIZED) exception. For some reason
>> >> > the list constructor must read mere than once from the iterator.
>> >> > So this is not an option, but even if it worked, it would show
>> >> > the same behaviour as my above test..
>> >>
>> >> Interesting. ?Looks like the Threads class implements __len__ and that
>> >> its implementation exhausts the iterator. ?Which isn't a great idea in
>> >> itself, but it turns out that Python's implementation of list() calls
>> >> __len__ if it's available (presumably to pre-size the list) before
>> >> iterating over the object, so it exhausts the iterator before even
>> >> using it.
>> >>
>> >> That said, if list(q.search_threads()) did work, it wouldn't give you
>> >> better performance than your experiment above.
> true. Nevertheless I think that list(q.search_threads())
> should be equivalent to [t for t in q.search_threads()], which is
> something to be fixed in the bindings. Should I file an issue somehow?
> Or is enough to state this as a TODO here on the list?

Yes, they should be equivalent.

Sebastian was thinking about fixing the larger issue of generator
exhaustion, which would address this, though the performance would
depend on the cost of iterating twice.  This is why generators
shouldn't support __len__.  Unfortunately, it's probably hard to get
rid of at this point and I doubt there's a way to tell list() to
overlook the presence of a __len__ method.

>> >> > would it be very hard to implement a Query.search_thread_ids() ?
>> >> > This name is a bit off because it had to be done on a lower level.
>> >>
>> >> Lazily fetching the thread metadata on the C side would probably
>> >> address your problem automatically. ?But what are you doing that
>> >> doesn't require any information about the threads you're manipulating?
>> > Agreed. Unfortunately, there seems to be no way to get a list of thread
>> > ids or a reliable iterator thereof by using the current python bindings.
>> > It would be enough for me to have the ids because then I could
>> > search for the few threads I actually need individually on demand.
>>
>> There's no way to do that from the C API either, so don't feel left
>> out. ?]:--8) ?It seems to me that the right solution to your problem
>> is to make thread information lazy (effectively, everything gathered
>> in lib/thread.cc:_thread_add_message). ?Then you could probably
>> materialize that iterator cheaply.
> Alright. I'll put this on my mental notmuch wish list and
> hope that someone will have addressed this before I run out of
> ideas how to improve my UI and have time to look at this myself.
> For now, I go with the [t.get_thread_id for t in q.search_threads()]
> approach to cache the thread ids myself and live with the fact that
> this takes time for large result sets.
>
>> In fact, it's probably worth
>> trying a hack where you put dummy information in the thread object
>> from _thread_add_message and see how long it takes just to walk the
>> iterator (unfortunately I don't think profiling will help much here
>> because much of your time is probably spent waiting for I/O).
> I don't think I understand what you mean by dummy info in a thread
> object.

In _thread_add_message, rather than looking up the message's author,
subject, etc, just hard-code some dummy values.  Performance-wise,
this would simulate making the thread metadata lookup lazy, so you
could see if making this lazy would address your problem.


normalizing part numbering across PGP/MIME processing

2011-05-27 Thread Daniel Kahn Gillmor
On Fri, 27 May 2011 03:27:35 -0700, Jameson Graef Rollins  wrote:
> Ok.  So I very much hope this patch series satisfies those who were
> bothered by the part renumbering that was happening when PGP/MIME
> parts were processed.  For signed messages we no longer modify the
> parts at all, so numbering always remains constant, and for encrypted
> messages the numbering will only change if the encrypted message is
> itself multipart.  We'll have to live with the encrypted multipart
> renumbering until we have a more sophisticated part numbering scheme.
> However, that's a separate issue that can hopefully be dealt with
> after the full crypto functionality is pulled.

These patches resolve my outstanding part-numbering concern with the
crypto verification business.  I recommend merging them to the mainline.

Then can we release 0.6 pretty please? :)

There's nothing stopping us from releasing 0.7 if there are more
features pending, but i'd really like to be able to say "please run 0.6
or later to handle verifying cryptographic signatures".

 --dkg
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 965 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20110527/d45b6e14/attachment.pgp>


[PATCH] test: change "#!/bin/bash" to "#!/usr/bin/env bash" enhances portability

2011-05-27 Thread Carl Worth
On Wed,  1 Dec 2010 21:27:52 +0100, Joel Borggr?n-Franck  wrote:
> From: Joel Borggr?n-Franck 
> 
> Change #!/bin/bash at start of tests to "#!/usr/bin/env bash". That way
> systems running on bash < 4 can prepend bash >= 4 to path before
> running the tests.

Thanks for the patch, Joel!

This issue recently came up again on IRC, so I dug out this patch,
applied, and pushed it.

-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/20110527/f9cf0cd3/attachment.pgp>


[PATCH] emacs: Give mutlipart/{signed, encrypted} their own part handler.

2011-05-27 Thread Jameson Graef Rollins
This is the best way to make the displayed output for
decrypted/verified messages clearer.  The special sigstatus and
encstatus buttons are now displayed under the part header button.  The
part header button is also tweaked to provide information to user
about how to proces crypto.
---

This patch replaces the previous version of this patch (9d7a9e3a) that
was mistakenly not emitting the sigstatus button for decrypted signed
messages.

 emacs/notmuch-crypto.el |   12 
 emacs/notmuch-show.el   |   60 +++
 2 files changed, 56 insertions(+), 16 deletions(-)

diff --git a/emacs/notmuch-crypto.el b/emacs/notmuch-crypto.el
index 944452b..cb02840 100644
--- a/emacs/notmuch-crypto.el
+++ b/emacs/notmuch-crypto.el
@@ -46,7 +46,7 @@ search."
 (defun notmuch-crypto-insert-sigstatus-button (sigstatus from)
   (let* ((status (plist-get sigstatus :status))
 (help-msg nil)
-(label "multipart/signed: signature not processed")
+(label "Signature not processed")
 (face '(:background "red" :foreground "black")))
 (cond
  ((string= status "good")
@@ -82,17 +82,17 @@ search."
 (defun notmuch-crypto-insert-encstatus-button (encstatus)
   (let* ((status (plist-get encstatus :status))
 (help-msg nil)
-(label "multipart/encrypted: decryption not attempted")
+(label "Decryption not attempted")
 (face '(:background "purple" :foreground "black")))
 (cond
  ((string= status "good")
-  (setq label "decryption successful"))
+  (setq label "Decryption successful"))
  ((string= status "bad")
-  (setq label "decryption error"))
+  (setq label "Decryption error"))
  (t
-  (setq label (concat "unknown encstatus \"" status "\""
+  (setq label (concat "Unknown encstatus \"" status "\""
 (insert-button
- (concat "[ multipart/encrypted: " label " ]")
+ (concat "[ " label " ]")
  :type 'notmuch-crypto-status-button-type
  'help-echo help-msg
  'face face
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index aa6ddd1..6c498ab 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -446,6 +446,56 @@ current buffer, if possible."
   (indent-rigidly start (point) 1)))
   t)

+(defun notmuch-show-insert-part-multipart/signed (msg part content-type nth 
depth declared-type)
+  (let ((button (notmuch-show-insert-part-header nth declared-type 
content-type nil)))
+(button-put button 'face '(:foreground "blue"))
+;; add signature status button if sigstatus provided
+(if (plist-member part :sigstatus)
+   (let* ((headers (plist-get msg :headers))
+  (from (plist-get headers :From))
+  (sigstatus (car (plist-get part :sigstatus
+ (notmuch-crypto-insert-sigstatus-button sigstatus from))
+  ;; if we're not adding sigstatus, tell the user how they can get it
+  (button-put button 'help-echo "Set notmuch-crypto-process-mime to 
process cryptographic mime parts.")))
+
+  (let ((inner-parts (plist-get part :content))
+   (start (point)))
+;; Show all of the parts.
+(mapc (lambda (inner-part)
+   (notmuch-show-insert-bodypart msg inner-part depth))
+ inner-parts)
+
+(when notmuch-show-indent-multipart
+  (indent-rigidly start (point) 1)))
+  t)
+
+(defun notmuch-show-insert-part-multipart/encrypted (msg part content-type nth 
depth declared-type)
+  (let ((button (notmuch-show-insert-part-header nth declared-type 
content-type nil)))
+(button-put button 'face '(:foreground "blue"))
+;; add encryption status button if encstatus specified
+(if (plist-member part :encstatus)
+   (let ((encstatus (car (plist-get part :encstatus
+ (notmuch-crypto-insert-encstatus-button encstatus)
+ ;; add signature status button if sigstatus specified
+ (if (plist-member part :sigstatus)
+ (let* ((headers (plist-get msg :headers))
+(from (plist-get headers :From))
+(sigstatus (car (plist-get part :sigstatus
+   (notmuch-crypto-insert-sigstatus-button sigstatus from
+  ;; if we're not adding encstatus, tell the user how they can get it
+  (button-put button 'help-echo "Set notmuch-crypto-process-mime to 
process cryptographic mime parts.")))
+
+  (let ((inner-parts (plist-get part :content))
+   (start (point)))
+;; Show all of the parts.
+(mapc (lambda (inner-part)
+   (notmuch-show-insert-bodypart msg inner-part depth))
+ inner-parts)
+
+(when notmuch-show-indent-multipart
+  (indent-rigidly start (point) 1)))
+  t)
+
 (defun notmuch-show-insert-part-multipart/* (msg part content-type nth depth 
declared-type)
   (notmuch-show-insert-part-header nth declared-type content-type nil)
   (let ((inner-parts (plist-get part :content))
@@ -593,16 +643,6 @@ current buffer, if possible."
   "Insert the body part PART at 

[PATCH 2/2] emacs: Cleaner interface when prompting for sender address

2011-05-27 Thread Thomas Jost
Most of the time, every entry in the list of identities has the same user name
part. It can then be filled in automatically, and the user can only be prompted
for the email address, which makes the interface much cleaner.
---
Hi Jameson,

Once again, a very good suggestion. I had doubts at first (because I sometimes
send mails using a nickname or on behalf of a group using that group's name),
but then I noticed I already had only one name in notmuch-identities :) So
here's a patch.

It handle 3 different cases:
- notmuch-identities is not set --> only one name
- notmuch-identities set with only one name
- notmuch-identities set with several different names

I tried to make it as compact and readable as possible, so the first two cases
are handled by a single call to ido-completing-read. But there is probably still
room for improvements: reviews, comments and suggestions are welcome.

Regards,
Thomas

 emacs/notmuch-mua.el |   33 +++--
 1 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 556d2bf..274c5da 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -162,20 +162,33 @@ the From: header is already filled in by notmuch."
   :group 'notmuch
   :type 'boolean)

-(defun notmuch-mua-sender-collection ()
-  (if notmuch-identities
-  notmuch-identities
-(mapcar (lambda (address)
- (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
+  (let (name addresses one-name-only)
+;; If notmuch-identities is non-nil, check if there is a fixed user name.
+(if notmuch-identities
+   (let ((components (mapcar 'mail-extract-address-components 
notmuch-identities)))
+ (setq name  (caar components)
+   addresses (mapcar 'cadr components)
+   one-name-only (eval
+  (cons 'and
+(mapcar (lambda (identity)
+  (string-equal name (car 
identity)))
+components)
+  ;; If notmuch-identities is nil, use values from the notmuch 
configuration file.
+  (setq name  (notmuch-user-name)
+   addresses (cons (notmuch-user-primary-email) 
(notmuch-user-other-email))
+   one-name-only t))
+;; Now prompt the user, either for an email address only or for a full 
identity.
+(if one-name-only
+   (let ((address
+  (ido-completing-read (concat "Sender address for " name ": ") 
addresses
+   nil nil nil 'notmuch-mua-sender-history 
(car addresses
+ (concat name " <" address ">"))
+  (ido-completing-read "Send mail From: " notmuch-identities
+  nil nil nil 'notmuch-mua-sender-history (car 
notmuch-identities)

 (defun notmuch-mua-new-mail ( prompt-for-sender)
   "Invoke the notmuch mail composition window.
-- 
1.7.5.2



[PATCH 1/2] emacs: Don't always prompt for the "From" address when replying

2011-05-27 Thread Thomas Jost
When replying, the From: address is already filled in by notmuch reply, so most
of the time there is no need to prompt the user for it.
---
Hi Jameson,

You're right, this is mostly annoying when replying to messages. Here's a fix.

Regards,
Thomas

 emacs/notmuch-mua.el |7 +--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 7c05a81..556d2bf 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -155,7 +155,10 @@ name and addresses configured in the notmuch configuration 
file."
   :type '(repeat string))

 (defcustom notmuch-always-prompt-for-sender nil
-  "Always prompt for the From: address when composing a new message."
+  "Always prompt for the From: address when composing or forwarding a message.
+
+This is not taken into account when replying to a message, because in that case
+the From: header is already filled in by notmuch."
   :group 'notmuch
   :type 'boolean)

@@ -203,7 +206,7 @@ the From: address first."
   "Invoke the notmuch reply window."
   (interactive "P")
   (let ((sender
-(when (or prompt-for-sender notmuch-always-prompt-for-sender)
+(when prompt-for-sender
   (notmuch-mua-prompt-for-sender
 (notmuch-mua-reply query-string sender)))

-- 
1.7.5.2



one-time-iterators

2011-05-27 Thread Michael Hudson-Doyle
On Thu, 26 May 2011 10:20:21 -0700, Carl Worth  wrote:
> On Thu, 26 May 2011 09:31:19 +0100, Patrick Totzke  googlemail.com> wrote:
> > Wow. This reads really complicated. All I want to say is:
> > if I change tags in my search-results view, I get Xapian errors :)
> 
> Yes, that's frustrating. I wish that we had a more reliable interface at
> the notmuch library level. But I'm not entirely sure what would be the
> best way to do this.
> 
> > The question: How do you solve this in the emacs code?
> > do you store all tids of a query? 
> 
> The emacs code does not use the notmuch library interface like your
> python bindings do. Instead, it uses the notmuch command-line tool, (and
> buffers up the text output by it). The support for asynchronous
> operations in the emacs interface means that it's likely possible
> someone could run into a similar problem:
> 
>   1. Start a search returning a *lot* of results
> 
>   2. When the first results come in, make some tag changes
> 
>   3. See if the original search aborts
> 
> I may have even had this happen to me before, but if I did I've never
> actually noticed it. I don't know what a good answer might be for this
> problem.

I've had exactly this happen to me.  Yay for post-vacation email
mountains and slow laptop drives...

Cheers,
mwh


[PATCH 2/2] emacs: Cleaner interface when prompting for sender address

2011-05-27 Thread Jameson Graef Rollins
On Fri, 27 May 2011 11:15:00 +0200, Thomas Jost  
wrote:
> Once again, a very good suggestion. I had doubts at first (because I sometimes
> send mails using a nickname or on behalf of a group using that group's name),
> but then I noticed I already had only one name in notmuch-identities :) So
> here's a patch.

Awesome again.  This definitely makes the interface much cleaner, imho.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20110527/7eea47d9/attachment.pgp>


[PATCH 1/2] emacs: Don't always prompt for the "From" address when replying

2011-05-27 Thread Jameson Graef Rollins
On Fri, 27 May 2011 11:14:59 +0200, Thomas Jost  
wrote:
> You're right, this is mostly annoying when replying to messages. Here's a fix.

Awesome.  Thanks, Thomas.  Tested and works great.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20110527/31cfbfc8/attachment-0001.pgp>


[PATCH 4/4] emacs: Give mutlipart/{signed, encrypted} their own part handler.

2011-05-27 Thread Jameson Graef Rollins
This is the best way to make the displayed output for
decrypted/verified messages clearer.  The special sigstatus and
encstatus buttons are now displayed under the part header button.  The
part header button is also tweaked to provide information to user
about how to proces crypto.
---
 emacs/notmuch-crypto.el |   12 
 emacs/notmuch-show.el   |   61 +++---
 2 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/emacs/notmuch-crypto.el b/emacs/notmuch-crypto.el
index 944452b..cb02840 100644
--- a/emacs/notmuch-crypto.el
+++ b/emacs/notmuch-crypto.el
@@ -46,7 +46,7 @@ search."
 (defun notmuch-crypto-insert-sigstatus-button (sigstatus from)
   (let* ((status (plist-get sigstatus :status))
 (help-msg nil)
-(label "multipart/signed: signature not processed")
+(label "Signature not processed")
 (face '(:background "red" :foreground "black")))
 (cond
  ((string= status "good")
@@ -82,17 +82,17 @@ search."
 (defun notmuch-crypto-insert-encstatus-button (encstatus)
   (let* ((status (plist-get encstatus :status))
 (help-msg nil)
-(label "multipart/encrypted: decryption not attempted")
+(label "Decryption not attempted")
 (face '(:background "purple" :foreground "black")))
 (cond
  ((string= status "good")
-  (setq label "decryption successful"))
+  (setq label "Decryption successful"))
  ((string= status "bad")
-  (setq label "decryption error"))
+  (setq label "Decryption error"))
  (t
-  (setq label (concat "unknown encstatus \"" status "\""
+  (setq label (concat "Unknown encstatus \"" status "\""
 (insert-button
- (concat "[ multipart/encrypted: " label " ]")
+ (concat "[ " label " ]")
  :type 'notmuch-crypto-status-button-type
  'help-echo help-msg
  'face face
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index aa6ddd1..131fc85 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -446,6 +446,57 @@ current buffer, if possible."
   (indent-rigidly start (point) 1)))
   t)

+(defun notmuch-show-insert-part-multipart/signed (msg part content-type nth 
depth declared-type)
+  (let ((button (notmuch-show-insert-part-header nth declared-type 
content-type nil)))
+(button-put button 'face '(:foreground "blue"))
+;; add signature status button if sigstatus provided
+(if (plist-member part :sigstatus)
+   (let* ((headers (plist-get msg :headers))
+  (from (plist-get headers :From))
+  (sigstatus (car (plist-get part :sigstatus
+ (notmuch-crypto-insert-sigstatus-button sigstatus from))
+  ;; if we're not adding sigstatus, tell the user how they can get it
+  (button-put button 'help-echo "Set notmuch-crypto-process-mime to 
process cryptographic mime parts.")))
+
+  (let ((inner-parts (plist-get part :content))
+   (start (point)))
+;; Show all of the parts.
+(mapc (lambda (inner-part)
+   (notmuch-show-insert-bodypart msg inner-part depth))
+ inner-parts)
+
+(when notmuch-show-indent-multipart
+  (indent-rigidly start (point) 1)))
+  t)
+
+(defun notmuch-show-insert-part-multipart/encrypted (msg part content-type nth 
depth declared-type)
+  (let ((button (notmuch-show-insert-part-header nth declared-type 
content-type nil)))
+(button-put button 'face '(:foreground "blue"))
+;; add encryption status button if encstatus specified
+(if (plist-member part :encstatus)
+   (let ((encstatus (car (plist-get part :encstatus
+ (notmuch-crypto-insert-encstatus-button encstatus))
+  ;; if we're not adding encstatus, tell the user how they can get it
+  (progn
+   (button-put button 'help-echo "Set notmuch-crypto-process-mime to 
process cryptographic mime parts.")
+   ;; add signature status button if sigstatus specified
+   (if (plist-member part :sigstatus)
+ (let* ((headers (plist-get msg :headers))
+(from (plist-get headers :From))
+(sigstatus (car (plist-get part :sigstatus
+   (notmuch-crypto-insert-sigstatus-button sigstatus from))
+
+  (let ((inner-parts (plist-get part :content))
+   (start (point)))
+;; Show all of the parts.
+(mapc (lambda (inner-part)
+   (notmuch-show-insert-bodypart msg inner-part depth))
+ inner-parts)
+
+(when notmuch-show-indent-multipart
+  (indent-rigidly start (point) 1)))
+  t)
+
 (defun notmuch-show-insert-part-multipart/* (msg part content-type nth depth 
declared-type)
   (notmuch-show-insert-part-header nth declared-type content-type nil)
   (let ((inner-parts (plist-get part :content))
@@ -593,16 +644,6 @@ current buffer, if possible."
   "Insert the body part PART at depth DEPTH in the current thread."
   (let ((content-type (downcase (plist-get part :content-type)))
(nth (plist-get part :id)))
-;; add encryption 

[PATCH 3/4] emacs: Do not attempt to render arbitrary application parts.

2011-05-27 Thread Jameson Graef Rollins
We probably shouldn't have been doing this anyway, but we do it here
specifically because we don't want the content of the
application/pgp-encrypted parts to be displayed and cluttering the
message show.
---
 emacs/notmuch-show.el |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 2f6be59..aa6ddd1 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -524,6 +524,11 @@ current buffer, if possible."
nil))
  nil

+(defun notmuch-show-insert-part-application/* (msg part content-type nth depth 
declared-type
+)
+  ;; do not render random "application" parts
+  (notmuch-show-insert-part-header nth content-type declared-type (plist-get 
part :filename)))
+
 (defun notmuch-show-insert-part-*/* (msg part content-type nth depth 
declared-type)
   ;; This handler _must_ succeed - it is the handler of last resort.
   (notmuch-show-insert-part-header nth content-type declared-type (plist-get 
part :filename))
-- 
1.7.4.4



[PATCH 2/4] Render all parts of multipart/encrypted when decrypting.

2011-05-27 Thread Jameson Graef Rollins
The primary goal here is to keep the decrypted output as similarly
structured as undecrypted output as possible.  Now, when decrypting
parts, only the original encrypted part is replaced by the it's
decrypted content.  If this part isn't itself a multipart, then all
part numbering should remain consistent during decryption.

The only draw back here is that the useless application/pgp-encrypted
sub-part of the multipart/encrypted part is also emitted.  But this
part can be easily ignored by clients.
---
 show-message.c |   22 --
 test/crypto|   39 +++
 2 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/show-message.c b/show-message.c
index 849c686..7a4bbc2 100644
--- a/show-message.c
+++ b/show-message.c
@@ -34,6 +34,7 @@ show_message_part (GMimeObject *part,
   notmuch_show_params_t *params,
   int first)
 {
+GMimeObject *decryptedpart = NULL;
 int selected;
 state->part_count += 1;

@@ -67,7 +68,7 @@ show_message_part (GMimeObject *part,
 g_mime_multipart_get_count (multipart));
} else {
GMimeMultipartEncrypted *encrypteddata = 
GMIME_MULTIPART_ENCRYPTED (part);
-   GMimeObject *decryptedpart = g_mime_multipart_encrypted_decrypt 
(encrypteddata, params->cryptoctx, );
+   decryptedpart = g_mime_multipart_encrypted_decrypt 
(encrypteddata, params->cryptoctx, );
if (decryptedpart) {
if ((selected || state->in_zone) && format->part_encstatus)
format->part_encstatus (1);
@@ -76,8 +77,6 @@ show_message_part (GMimeObject *part,
fprintf (stderr, "Failed to verify signed part: %s\n", 
(err ? err->message : "no error explanation given"));
if ((selected || state->in_zone) && format->part_sigstatus)
format->part_sigstatus (sigvalidity);
-   /* swap the part with the decrypted part */
-   part = decryptedpart;
} else {
fprintf (stderr, "Failed to decrypt part: %s\n", (err ? 
err->message : "no error explanation given"));
if ((selected || state->in_zone) && format->part_encstatus)
@@ -125,9 +124,20 @@ show_message_part (GMimeObject *part,
if (selected)
state->in_zone = 1;

-   for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {
-   show_message_part (g_mime_multipart_get_part (multipart, i),
-  state, format, params, i == 0);
+   if (decryptedpart) {
+   /* We emit the useless application/pgp-encrypted version
+* part here only to keep the emitted output as consistent
+* as possible between decrypted output and the
+* unprocessed multipart/mime. For some strange reason,
+* the actual encrypted data is the second part of the
+* multipart. */
+   show_message_part (g_mime_multipart_get_part (multipart, 0), state, 
format, params, TRUE);
+   show_message_part (decryptedpart, state, format, params, FALSE);
+   } else {
+   for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {
+   show_message_part (g_mime_multipart_get_part (multipart, i),
+  state, format, params, i == 0);
+   }
}

if (selected)
diff --git a/test/crypto b/test/crypto
index ef35c55..6ce51d9 100755
--- a/test/crypto
+++ b/test/crypto
@@ -160,15 +160,20 @@ To: test_suite at notmuchmail.org
 Date: 01 Jan 2000 12:00:00 -
 header}
 body{
-part{ ID: 1, Content-type: multipart/mixed
-part{ ID: 2, Content-type: text/plain
+part{ ID: 1, Content-type: multipart/encrypted
+part{ ID: 2, Content-type: application/pgp-encrypted
+Non-text part: application/pgp-encrypted
+part}
+part{ ID: 3, Content-type: multipart/mixed
+part{ ID: 4, Content-type: text/plain
 This is a test encrypted message.
 part}
-attachment{ ID: 3, Content-type: application/octet-stream
+attachment{ ID: 5, Content-type: application/octet-stream
 Attachment: TESTATTACHMENT (application/octet-stream)
 Non-text part: application/octet-stream
 attachment}
 part}
+part}
 body}
 message}'
 test_expect_equal \
@@ -194,33 +199,37 @@ expected='[[[{"id": "X",
  "body": [{"id": 1,
  "encstatus": [{"status": "good"}],
  "sigstatus": [],
- "content-type": "multipart/mixed",
+ "content-type": "multipart/encrypted",
  "content": [{"id": 2,
+ "content-type": "application/pgp-encrypted"},
+ {"id": 3,
+ "content-type": "multipart/mixed",
+ "content": [{"id": 4,
  "content-type": "text/plain",
  "content": "This is a test encrypted message.\n"},
- {"id": 3,
+ {"id": 5,
  "content-type": "application/octet-stream",
- "filename": "TESTATTACHMENT"}]}]},
+ "filename": "TESTATTACHMENT"}]}]}]},
  ['
 test_expect_equal \
 "$output" \
 

[PATCH 1/4] Do not replace multipart/signed part with content part when doing verification.

2011-05-27 Thread Jameson Graef Rollins
Some folks have complained about the part renumbering that occurs when
the entire multipart/signed part is replaced with the part contents
after verification.  This is primarily because it incurs an additional
computational cost to retrieve individual parts, since verification
has to be performed again to ensure that part numbering is consistent.
This patch simply leaves the full multipart/signed part as is.

The emacs crypto test is also updated to reflect this change.
---
 show-message.c |2 --
 test/crypto|   24 
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/show-message.c b/show-message.c
index 37252b2..849c686 100644
--- a/show-message.c
+++ b/show-message.c
@@ -105,8 +105,6 @@ show_message_part (GMimeObject *part,
}
if ((selected || state->in_zone) && format->part_sigstatus)
format->part_sigstatus (sigvalidity);
-   /* extract only data part, and ignore signature part */
-   part = g_mime_multipart_get_part (multipart, 0);
if (sigvalidity)
g_mime_signature_validity_free (sigvalidity);
}
diff --git a/test/crypto b/test/crypto
index c5abcc3..ef35c55 100755
--- a/test/crypto
+++ b/test/crypto
@@ -57,8 +57,12 @@ expected='[[[{"id": "X",
  "sigstatus": [{"status": "good",
  "fingerprint": "'$FINGERPRINT'",
  "created": 946728000}],
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
  "content-type": "text/plain",
- "content": "This is a test signed message.\n"}]},
+ "content": "This is a test signed message.\n"},
+ {"id": 3,
+ "content-type": "application/pgp-signature"}]}]},
  ['
 test_expect_equal \
 "$output" \
@@ -88,8 +92,12 @@ expected='[[[{"id": "X",
  "fingerprint": "'$FINGERPRINT'",
  "created": 946728000,
  "userid": " Notmuch Test Suite  (INSECURE!)"}],
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
  "content-type": "text/plain",
- "content": "This is a test signed message.\n"}]},
+ "content": "This is a test signed message.\n"},
+ {"id": 3,
+ "content-type": "application/pgp-signature"}]}]},
  ['
 test_expect_equal \
 "$output" \
@@ -117,8 +125,12 @@ expected='[[[{"id": "X",
  "sigstatus": [{"status": "error",
  "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'",
  "errors": 2}],
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
  "content-type": "text/plain",
- "content": "This is a test signed message.\n"}]},
+ "content": "This is a test signed message.\n"},
+ {"id": 3,
+ "content-type": "application/pgp-signature"}]}]},
  ['
 test_expect_equal \
 "$output" \
@@ -320,8 +332,12 @@ expected='[[[{"id": "X",
  "sigstatus": [{"status": "error",
  "keyid": "6D92612D94E46381",
  "errors": 8}],
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
  "content-type": "text/plain",
- "content": "This is a test signed message.\n"}]},
+ "content": "This is a test signed message.\n"},
+ {"id": 3,
+ "content-type": "application/pgp-signature"}]}]},
  ['
 test_expect_equal \
 "$output" \
-- 
1.7.4.4



normalizing part numbering across PGP/MIME processing

2011-05-27 Thread Jameson Graef Rollins
Ok.  So I very much hope this patch series satisfies those who were
bothered by the part renumbering that was happening when PGP/MIME
parts were processed.  For signed messages we no longer modify the
parts at all, so numbering always remains constant, and for encrypted
messages the numbering will only change if the encrypted message is
itself multipart.  We'll have to live with the encrypted multipart
renumbering until we have a more sophisticated part numbering scheme.
However, that's a separate issue that can hopefully be dealt with
after the full crypto functionality is pulled.

jamie.



[PATCH 2/2] Workaround for Emacs bug #8721.

2011-05-27 Thread Dmitry Kurochkin
On Fri, 27 May 2011 01:38:35 +0400, Dmitry Kurochkin  wrote:
> The patch adds `notmuch-isearch-range-invisible' function which
> is the same as `isearch-range-invisible' but with fixed Emacs bug
> `notmuch-isearch-range-invisible' instead of the original
> `isearch-range-invisible' when in `notmuch-show-mode'.

I've screwed up the commit message because of a line starting with '#'.

Attach is an amended patch.

Regards,
  Dmitry
-- next part --
A non-text attachment was scrubbed...
Name: 0001-Workaround-for-Emacs-bug-8721.patch
Type: text/x-diff
Size: 3417 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20110527/595cc12b/attachment.patch>


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

2011-05-27 Thread Dmitry Kurochkin
On Thu, 26 May 2011 14:31:30 -0700, Carl Worth  wrote:
> On Thu, 26 May 2011 14:26:34 +0400, Dmitry Kurochkin  gmail.com> wrote:
> > It is called indirectly.  What is the best way to fix it?  I imagine
> > that we can replace `isearch-range-invisible' function with another one,
> > which would call the fixed function if some special variable is set, or
> > if we are searching in a notmuch-show view.  Otherwise it would call the
> > original function.
> 
> I'm not sure what the best approach would be. I'd like to be a good
> "emacs citizen" but I don't know what the best way to do that is here.
> 

Agreed on being a good "emacs citizen".

> If we can predict what the first emacs release will be that contains the
> fix, then we could restrict our kludge here to older, unfixed
> emacs. That would help avoid some problems with "bad citizenship here".
> 
> I'm willing to take whatever you this is best here.
> 

I have just send two more patches to this thread.  One with new tests.
Another with a workaround for the bug.  The workaround should not break
anything since it affects only notmuch-show mode.

Regards,
  Dmitry

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


[PATCH 2/2] Workaround for Emacs bug #8721.

2011-05-27 Thread Dmitry Kurochkin
The patch adds `notmuch-isearch-range-invisible' function which
is the same as `isearch-range-invisible' but with fixed Emacs bug
`notmuch-isearch-range-invisible' instead of the original
`isearch-range-invisible' when in `notmuch-show-mode'.
---
 emacs/notmuch-wash.el |   67 +
 1 files changed, 67 insertions(+), 0 deletions(-)

diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el
index 992fa8f..f37fd95 100644
--- a/emacs/notmuch-wash.el
+++ b/emacs/notmuch-wash.el
@@ -298,4 +298,71 @@ for error."

 ;;

+;; Temporary workaround for Emacs bug #8721
+;; http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8721
+
+(defun notmuch-isearch-range-invisible (beg end)
+  "Same as `isearch-range-invisible' but with fixed Emacs bug #8721."
+  (when (/= beg end)
+;; Check that invisibility runs up to END.
+(save-excursion
+  (goto-char beg)
+  (let (;; can-be-opened keeps track if we can open some overlays.
+   (can-be-opened (eq search-invisible 'open))
+   ;; the list of overlays that could be opened
+   (crt-overlays nil))
+   (when (and can-be-opened isearch-hide-immediately)
+ (isearch-close-unnecessary-overlays beg end))
+   ;; If the following character is currently invisible,
+   ;; skip all characters with that same `invisible' property value.
+   ;; Do that over and over.
+   (while (and (< (point) end) (invisible-p (point)))
+ (if (get-text-property (point) 'invisible)
+ (progn
+   (goto-char (next-single-property-change (point) 'invisible
+   nil end))
+   ;; if text is hidden by an `invisible' text property
+   ;; we cannot open it at all.
+   (setq can-be-opened nil))
+   (when can-be-opened
+ (let ((overlays (overlays-at (point)))
+   ov-list
+   o
+   invis-prop)
+   (while overlays
+ (setq o (car overlays)
+   invis-prop (overlay-get o 'invisible))
+ (if (invisible-p invis-prop)
+ (if (overlay-get o 'isearch-open-invisible)
+ (setq ov-list (cons o ov-list))
+   ;; We found one overlay that cannot be
+   ;; opened, that means the whole chunk
+   ;; cannot be opened.
+   (setq can-be-opened nil)))
+ (setq overlays (cdr overlays)))
+   (if can-be-opened
+   ;; It makes sense to append to the open
+   ;; overlays list only if we know that this is
+   ;; t.
+   (setq crt-overlays (append ov-list crt-overlays)
+   (goto-char (next-overlay-change (point)
+   ;; See if invisibility reaches up thru END.
+   (if (>= (point) end)
+   (if (and can-be-opened (consp crt-overlays))
+   (progn
+ (setq isearch-opened-overlays
+   (append isearch-opened-overlays crt-overlays))
+ (mapc 'isearch-open-overlay-temporary crt-overlays)
+ nil)
+ (setq isearch-hidden t)))
+
+(defadvice isearch-range-invisible (around 
notmuch-isearch-range-invisible-advice activate)
+  "Call `notmuch-isearch-range-invisible' instead of the original
+`isearch-range-invisible' when in `notmuch-show-mode' mode."
+  (if (eq major-mode 'notmuch-show-mode)
+  (setq ad-return-value (notmuch-isearch-range-invisible beg end))
+ad-do-it))
+
+;;
+
 (provide 'notmuch-wash)
-- 
1.7.5.1



[PATCH v2 3/3] Emacs changes for reply to sender

2011-05-27 Thread Mark Walters
Reply to sender is currently bound to R
---
 emacs/notmuch-mua.el  |   10 ++
 emacs/notmuch-show.el |8 +++-
 emacs/notmuch.el  |2 +-
 3 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 61a723b..c9c5854 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -69,13 +69,15 @@ list."
(push header message-hidden-headers)))
notmuch-mua-hidden-headers))

-(defun notmuch-mua-reply (query-string  sender)
+(defun notmuch-mua-reply (query-string option-string  sender)
   (let (headers body)
 ;; This make assumptions about the output of `notmuch reply', but
 ;; really only that the headers come first followed by a blank
 ;; line and then the body.
 (with-temp-buffer
-  (call-process notmuch-command nil t nil "reply" query-string)
+  (if option-string
+ (call-process notmuch-command nil t nil "reply" option-string 
query-string)
+   (call-process notmuch-command nil t nil "reply" query-string))
   (goto-char (point-min))
   (if (re-search-forward "^$" nil t)
  (save-excursion
@@ -194,13 +196,13 @@ the From: address first."
(notmuch-mua-forward-message))
 (notmuch-mua-forward-message)))

-(defun notmuch-mua-new-reply (query-string  prompt-for-sender)
+(defun notmuch-mua-new-reply (query-string option-string  
prompt-for-sender)
   "Invoke the notmuch reply window."
   (interactive "P")
   (let ((sender
 (when (or prompt-for-sender notmuch-always-prompt-for-sender)
   (notmuch-mua-prompt-for-sender
-(notmuch-mua-reply query-string sender)))
+(notmuch-mua-reply query-string option-string sender)))

 (defun notmuch-mua-send-and-exit ( arg)
   (interactive "P")
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 2ba151e..852dadf 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -795,6 +795,7 @@ function is used. "
(define-key map "m" 'notmuch-mua-new-mail)
(define-key map "f" 'notmuch-show-forward-message)
(define-key map "r" 'notmuch-show-reply)
+   (define-key map "R" 'notmuch-show-reply-sender)
(define-key map "|" 'notmuch-show-pipe-message)
(define-key map "w" 'notmuch-show-save-attachments)
(define-key map "V" 'notmuch-show-view-raw-message)
@@ -1101,7 +1102,12 @@ any effects from previous calls to
 (defun notmuch-show-reply ( prompt-for-sender)
   "Reply to the current message."
   (interactive "P")
-  (notmuch-mua-new-reply (notmuch-show-get-message-id) prompt-for-sender))
+  (notmuch-mua-new-reply (notmuch-show-get-message-id) nil prompt-for-sender))
+
+(defun notmuch-show-reply-sender ( prompt-for-sender)
+  "Reply to the current message."
+  (interactive "P")
+  (notmuch-mua-new-reply (notmuch-show-get-message-id) "--reply-to=sender" 
prompt-for-sender))

 (defun notmuch-show-forward-message ( prompt-for-sender)
   "Forward the current message."
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index c22add7..e956420 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -440,7 +440,7 @@ Complete list of currently available key bindings:
   "Begin composing a reply to the entire current thread in a new buffer."
   (interactive "P")
   (let ((message-id (notmuch-search-find-thread-id)))
-(notmuch-mua-new-reply message-id prompt-for-sender)))
+(notmuch-mua-new-reply message-id nil prompt-for-sender)))

 (defun notmuch-call-notmuch-process ( args)
   "Synchronously invoke \"notmuch\" with the given list of arguments.
-- 
1.7.2.5



[PATCH v2 2/3] Documentation changes for --reply-to= option to notmuch reply.

2011-05-27 Thread Mark Walters
---
 notmuch.1 |   13 +
 notmuch.c |   10 ++
 2 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/notmuch.1 b/notmuch.1
index a1c7fa8..c434e77 100644
--- a/notmuch.1
+++ b/notmuch.1
@@ -388,6 +388,19 @@ Includes subject and quoted message body.
 .BR headers\-only
 Only produces In\-Reply\-To, References, To, Cc, and Bcc headers.
 .RE
+.RE
+.RS
+.TP 4
+.BR \-\-reply\-to= ( sender | all )
+.RS
+.TP 4
+.BR sender
+Replies only to the sender (or to all addresses in the To header if
+the sending address is one of the user's email addresses).
+.TP
+.BR all " (default)"
+Replies to all addresses.
+.RE

 See the
 .B "SEARCH SYNTAX"
diff --git a/notmuch.c b/notmuch.c
index 262d677..631f8e7 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -338,6 +338,16 @@ static command_t commands[] = {
   "\t\t\tOnly produces In-Reply-To, References, To\n"
   "\t\t\tCc, and Bcc headers.\n"
   "\n"
+  "\t--reply-to=(sender|all)\n"
+  "\n"
+  "\t\tsender:\n"
+  "\t\t\tReplies  only  to the sender (or to all addresses in the\n"
+  "\t\t\tTo header if the sending address is one of the user's\n"
+  "\t\t\temail addresses).\n"
+  "\n"
+  "\t\tall: (default)\n"
+  "\t\t\tReplies to all recipients.\n"
+  "\n"
   "\tSee \"notmuch help search-terms\" for details of the search\n"
   "\tterms syntax." },
 { "tag", notmuch_tag_command,
-- 
1.7.2.5



[PATCH v2 1/3] Adds the option "--reply-to=" to notmuch reply.

2011-05-27 Thread Mark Walters
Possible values are "sender" which replies just to sender and
"all" (the default).

More precisely reply to sender follows these rules:
reply only to sender unless it was the user
reply only to all people on the to line unless they were all the user
reply to all people on the cc line

Implementation details

Note we continue parsing addresses beyond the ones we reply to because
we want to make sure the from address is correct. (At the very least it
is the same as it would be if we replied to all.)

We overload the message variable in add_recipients_for_address_list so
if it is NULL we parse the address (looking for the users address)
but do not add to the message recipients list

We add the variable reply_to_all to the function chain to keep track
of whether we should reply to everyone.
---
 notmuch-reply.c |   46 +++---
 1 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index ab15650..98ae94a 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -191,7 +191,8 @@ add_recipients_for_address_list (GMimeMessage *message,
if (ret == NULL)
ret = addr;
} else {
-   g_mime_message_add_recipient (message, type, name, addr);
+if (message)
+ g_mime_message_add_recipient (message, type, name, addr);
}
}
 }
@@ -271,7 +272,8 @@ reply_to_header_is_redundant (notmuch_message_t *message)
 static const char *
 add_recipients_from_message (GMimeMessage *reply,
 notmuch_config_t *config,
-notmuch_message_t *message)
+notmuch_message_t *message,
+int reply_to_all)
 {
 struct {
const char *header;
@@ -311,9 +313,20 @@ add_recipients_from_message (GMimeMessage *reply,
recipients = notmuch_message_get_header (message,
 reply_to_map[i].fallback);

-   addr = add_recipients_for_string (reply, config,
- reply_to_map[i].recipient_type,
- recipients);
+
+   /* We add the addresses if we are replying to all or we have not yet 
found
+* a non-user address. We have to keep parsing to make sure we do find 
the
+* correct from address for the user, but we pass a NULL message
+*/
+   if ((reply_to_all) || (g_mime_message_get_all_recipients (reply) == 
NULL))
+   addr = add_recipients_for_string (reply, config,
+ reply_to_map[i].recipient_type,
+ recipients);
+   else
+addr = add_recipients_for_string (NULL, config,
+  reply_to_map[i].recipient_type,
+  recipients);
+
if (from_addr == NULL)
from_addr = addr;
 }
@@ -453,7 +466,7 @@ 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, int reply_to_all)
 {
 GMimeMessage *reply;
 notmuch_messages_t *messages;
@@ -484,7 +497,7 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t 
*config, notmuch_query_
g_mime_message_set_subject (reply, subject);
}

-   from_addr = add_recipients_from_message (reply, config, message);
+   from_addr = add_recipients_from_message (reply, config, message, 
reply_to_all);

if (from_addr == NULL)
from_addr = guess_from_received_header (config, message);
@@ -531,7 +544,7 @@ 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, int reply_to_all)
 {
 GMimeMessage *reply;
 notmuch_messages_t *messages;
@@ -571,7 +584,7 @@ notmuch_reply_format_headers_only(void *ctx, 
notmuch_config_t *config, notmuch_q
g_mime_object_set_header (GMIME_OBJECT (reply),
  "References", references);

-   (void)add_recipients_from_message (reply, config, message);
+   (void)add_recipients_from_message (reply, config, message, 
reply_to_all);

reply_headers = g_mime_object_to_string (GMIME_OBJECT (reply));
printf ("%s", reply_headers);
@@ -593,7 +606,8 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
 notmuch_query_t *query;
 char *opt, *query_string;
 int i, ret = 0;
-int 

[PATCH v2 0/3] Implement reply to sender

2011-05-27 Thread Mark Walters
Many thanks for the rapid response: I have modified the
patches as suggested and this version includes the
necessary documentation changes. I have also modified the
emacs portion to apply to current master.

Best wishes

Mark


These patches implement a reply to sender function.

On the command line this is done via a new option
to notmuch-reply: --reply-to=(sender|all) with all being
the default (as suggested).

In emacs it is bound to the key R. (Note it does not touch the
reply to thread command from notmuch-search: it is unclear to me
what reply to sender would mean there.)

Mark Walters (3):
  Adds the option "--reply-to" to notmuch reply.
  Documentation changes for --reply-to= option to notmuch reply.
  Emacs changes for reply to sender

 emacs/notmuch-mua.el  |   10 ++
 emacs/notmuch-show.el |8 +++-
 emacs/notmuch.el  |2 +-
 notmuch-reply.c   |   46 +++---
 notmuch.1 |   13 +
 notmuch.c |   10 ++
 6 files changed, 72 insertions(+), 17 deletions(-)

-- 
1.7.2.5



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

2011-05-27 Thread Daniel Kahn Gillmor
On 05/26/2011 06:04 PM, Carl Worth wrote:
> 2. The hello screen is now lying a bit by saying "all tags".
> 
>Perhaps if the user has the notmuch-hello-hide-tags variable set to
>non-nil the text might change somewhat? I'm not sure to what exactly.

maybe "all non-hidden tags" ?

--dkg

-- next part --
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 1030 bytes
Desc: OpenPGP digital signature
URL: 



one-time-iterators

2011-05-27 Thread Patrick Totzke
Excerpts from Austin Clements's message of Thu May 26 22:43:02 +0100 2011:
> http://notmuch.198994.n3.nabble.com/notmuch-s-idea-of-concurrency-failing-an-invocation-tp2373468p2565731.html
ah, good old peterson :P thanks.

> > > Though, Patrick, that solution doesn't address your problem.? On the
> > > other hand, it's not clear to me what concurrent access semantics
> > > you're actually expecting.? I suspect you don't want the remaining
> > > iteration to reflect the changes, since your changes could equally
> > > well have affected earlier iteration results.?
> > That's right. 
> > > But if you want a
> > > consistent view of your query results, something's going to have to
> > > materialize that iterator, and it might as well be you (or Xapian
> > > would need more sophisticated concurrency control than it has).? But
> > > this shouldn't be expensive because all you need to materialize are
> > > the document ids; you shouldn't need to eagerly fetch the per-thread
> > > information.  
> > I thought so, but it seems that Query.search_threads() already
> > caches more than the id of each item. Which is as expected
> > because it is designed to return thread objects, not their ids.
> > As you can see above, this _is_ too expensive for me.
> 
> I'd forgotten that constructing threads on the C side was eager about
> the thread tags, author list and subject (which, without Istvan's
> proposed patch, even requires opening and parsing the message file).
> This is probably what's killing you.
> 
> Out of curiosity, what is your situation that you won't wind up paying
> the cost of this iteration one way or the other and that the latency
> of doing these tag changes matters?

I'm trying to implement a terminal interface for notmuch in python
that resembles sup.
For the search results view, i read an initial portion from a Threads iterator 
to fill my teminal window with threadline-widgets. Obviously, for a
large number of results I don't want to go through all of them.
The problem arises if you toggle a tag on the selected threadline and afterwards
continue to scroll down.

> > > Have you tried simply calling list() on your thread
> > > iterator to see how expensive it is?  My bet is that it's quite cheap,
> > > both memory-wise and CPU-wise.
> > Funny thing:
> >  q=Database().create_query('*')
> >  time tlist = list(q.search_threads())
> > raises a NotmuchError(STATUS.NOT_INITIALIZED) exception. For some reason
> > the list constructor must read mere than once from the iterator.
> > So this is not an option, but even if it worked, it would show
> > the same behaviour as my above test..
> 
> Interesting.  Looks like the Threads class implements __len__ and that
> its implementation exhausts the iterator.  Which isn't a great idea in
> itself, but it turns out that Python's implementation of list() calls
> __len__ if it's available (presumably to pre-size the list) before
> iterating over the object, so it exhausts the iterator before even
> using it.
> 
> That said, if list(q.search_threads()) did work, it wouldn't give you
> better performance than your experiment above.
> 
> > would it be very hard to implement a Query.search_thread_ids() ?
> > This name is a bit off because it had to be done on a lower level.
> 
> Lazily fetching the thread metadata on the C side would probably
> address your problem automatically.  But what are you doing that
> doesn't require any information about the threads you're manipulating?
Agreed. Unfortunately, there seems to be no way to get a list of thread
ids or a reliable iterator thereof by using the current python bindings.
It would be enough for me to have the ids because then I could
search for the few threads I actually need individually on demand.

Here is the branch in which I'm trying out these things. Sorry for the
messy code, its late :P
https://github.com/pazz/notmuch-gui/tree/toggletags

/p
-- next part --
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: 



[PATCH 1/2] emacs: Don't always prompt for the From address when replying

2011-05-27 Thread Thomas Jost
When replying, the From: address is already filled in by notmuch reply, so most
of the time there is no need to prompt the user for it.
---
Hi Jameson,

You're right, this is mostly annoying when replying to messages. Here's a fix.

Regards,
Thomas

 emacs/notmuch-mua.el |7 +--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 7c05a81..556d2bf 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -155,7 +155,10 @@ name and addresses configured in the notmuch configuration 
file.
   :type '(repeat string))
 
 (defcustom notmuch-always-prompt-for-sender nil
-  Always prompt for the From: address when composing a new message.
+  Always prompt for the From: address when composing or forwarding a message.
+
+This is not taken into account when replying to a message, because in that case
+the From: header is already filled in by notmuch.
   :group 'notmuch
   :type 'boolean)
 
@@ -203,7 +206,7 @@ the From: address first.
   Invoke the notmuch reply window.
   (interactive P)
   (let ((sender
-(when (or prompt-for-sender notmuch-always-prompt-for-sender)
+(when prompt-for-sender
   (notmuch-mua-prompt-for-sender
 (notmuch-mua-reply query-string sender)))
 
-- 
1.7.5.2

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


[PATCH 2/2] emacs: Cleaner interface when prompting for sender address

2011-05-27 Thread Thomas Jost
Most of the time, every entry in the list of identities has the same user name
part. It can then be filled in automatically, and the user can only be prompted
for the email address, which makes the interface much cleaner.
---
Hi Jameson,

Once again, a very good suggestion. I had doubts at first (because I sometimes
send mails using a nickname or on behalf of a group using that group's name),
but then I noticed I already had only one name in notmuch-identities :) So
here's a patch.

It handle 3 different cases:
- notmuch-identities is not set -- only one name
- notmuch-identities set with only one name
- notmuch-identities set with several different names

I tried to make it as compact and readable as possible, so the first two cases
are handled by a single call to ido-completing-read. But there is probably still
room for improvements: reviews, comments and suggestions are welcome.

Regards,
Thomas

 emacs/notmuch-mua.el |   33 +++--
 1 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 556d2bf..274c5da 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -162,20 +162,33 @@ the From: header is already filled in by notmuch.
   :group 'notmuch
   :type 'boolean)
 
-(defun notmuch-mua-sender-collection ()
-  (if notmuch-identities
-  notmuch-identities
-(mapcar (lambda (address)
- (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
+  (let (name addresses one-name-only)
+;; If notmuch-identities is non-nil, check if there is a fixed user name.
+(if notmuch-identities
+   (let ((components (mapcar 'mail-extract-address-components 
notmuch-identities)))
+ (setq name  (caar components)
+   addresses (mapcar 'cadr components)
+   one-name-only (eval
+  (cons 'and
+(mapcar (lambda (identity)
+  (string-equal name (car 
identity)))
+components)
+  ;; If notmuch-identities is nil, use values from the notmuch 
configuration file.
+  (setq name  (notmuch-user-name)
+   addresses (cons (notmuch-user-primary-email) 
(notmuch-user-other-email))
+   one-name-only t))
+;; Now prompt the user, either for an email address only or for a full 
identity.
+(if one-name-only
+   (let ((address
+  (ido-completing-read (concat Sender address for  name : ) 
addresses
+   nil nil nil 'notmuch-mua-sender-history 
(car addresses
+ (concat name   address ))
+  (ido-completing-read Send mail From:  notmuch-identities
+  nil nil nil 'notmuch-mua-sender-history (car 
notmuch-identities)
 
 (defun notmuch-mua-new-mail (optional prompt-for-sender)
   Invoke the notmuch mail composition window.
-- 
1.7.5.2

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


normalizing part numbering across PGP/MIME processing

2011-05-27 Thread Jameson Graef Rollins
Ok.  So I very much hope this patch series satisfies those who were
bothered by the part renumbering that was happening when PGP/MIME
parts were processed.  For signed messages we no longer modify the
parts at all, so numbering always remains constant, and for encrypted
messages the numbering will only change if the encrypted message is
itself multipart.  We'll have to live with the encrypted multipart
renumbering until we have a more sophisticated part numbering scheme.
However, that's a separate issue that can hopefully be dealt with
after the full crypto functionality is pulled.

jamie.

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


[PATCH 3/4] emacs: Do not attempt to render arbitrary application parts.

2011-05-27 Thread Jameson Graef Rollins
We probably shouldn't have been doing this anyway, but we do it here
specifically because we don't want the content of the
application/pgp-encrypted parts to be displayed and cluttering the
message show.
---
 emacs/notmuch-show.el |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 2f6be59..aa6ddd1 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -524,6 +524,11 @@ current buffer, if possible.
nil))
  nil
 
+(defun notmuch-show-insert-part-application/* (msg part content-type nth depth 
declared-type
+)
+  ;; do not render random application parts
+  (notmuch-show-insert-part-header nth content-type declared-type (plist-get 
part :filename)))
+
 (defun notmuch-show-insert-part-*/* (msg part content-type nth depth 
declared-type)
   ;; This handler _must_ succeed - it is the handler of last resort.
   (notmuch-show-insert-part-header nth content-type declared-type (plist-get 
part :filename))
-- 
1.7.4.4

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


[PATCH 2/4] Render all parts of multipart/encrypted when decrypting.

2011-05-27 Thread Jameson Graef Rollins
The primary goal here is to keep the decrypted output as similarly
structured as undecrypted output as possible.  Now, when decrypting
parts, only the original encrypted part is replaced by the it's
decrypted content.  If this part isn't itself a multipart, then all
part numbering should remain consistent during decryption.

The only draw back here is that the useless application/pgp-encrypted
sub-part of the multipart/encrypted part is also emitted.  But this
part can be easily ignored by clients.
---
 show-message.c |   22 --
 test/crypto|   39 +++
 2 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/show-message.c b/show-message.c
index 849c686..7a4bbc2 100644
--- a/show-message.c
+++ b/show-message.c
@@ -34,6 +34,7 @@ show_message_part (GMimeObject *part,
   notmuch_show_params_t *params,
   int first)
 {
+GMimeObject *decryptedpart = NULL;
 int selected;
 state-part_count += 1;
 
@@ -67,7 +68,7 @@ show_message_part (GMimeObject *part,
 g_mime_multipart_get_count (multipart));
} else {
GMimeMultipartEncrypted *encrypteddata = 
GMIME_MULTIPART_ENCRYPTED (part);
-   GMimeObject *decryptedpart = g_mime_multipart_encrypted_decrypt 
(encrypteddata, params-cryptoctx, err);
+   decryptedpart = g_mime_multipart_encrypted_decrypt 
(encrypteddata, params-cryptoctx, err);
if (decryptedpart) {
if ((selected || state-in_zone)  format-part_encstatus)
format-part_encstatus (1);
@@ -76,8 +77,6 @@ show_message_part (GMimeObject *part,
fprintf (stderr, Failed to verify signed part: %s\n, 
(err ? err-message : no error explanation given));
if ((selected || state-in_zone)  format-part_sigstatus)
format-part_sigstatus (sigvalidity);
-   /* swap the part with the decrypted part */
-   part = decryptedpart;
} else {
fprintf (stderr, Failed to decrypt part: %s\n, (err ? 
err-message : no error explanation given));
if ((selected || state-in_zone)  format-part_encstatus)
@@ -125,9 +124,20 @@ show_message_part (GMimeObject *part,
if (selected)
state-in_zone = 1;
 
-   for (i = 0; i  g_mime_multipart_get_count (multipart); i++) {
-   show_message_part (g_mime_multipart_get_part (multipart, i),
-  state, format, params, i == 0);
+   if (decryptedpart) {
+   /* We emit the useless application/pgp-encrypted version
+* part here only to keep the emitted output as consistent
+* as possible between decrypted output and the
+* unprocessed multipart/mime. For some strange reason,
+* the actual encrypted data is the second part of the
+* multipart. */
+   show_message_part (g_mime_multipart_get_part (multipart, 0), state, 
format, params, TRUE);
+   show_message_part (decryptedpart, state, format, params, FALSE);
+   } else {
+   for (i = 0; i  g_mime_multipart_get_count (multipart); i++) {
+   show_message_part (g_mime_multipart_get_part (multipart, i),
+  state, format, params, i == 0);
+   }
}
 
if (selected)
diff --git a/test/crypto b/test/crypto
index ef35c55..6ce51d9 100755
--- a/test/crypto
+++ b/test/crypto
@@ -160,15 +160,20 @@ To: test_su...@notmuchmail.org
 Date: 01 Jan 2000 12:00:00 -
 header}
 body{
-part{ ID: 1, Content-type: multipart/mixed
-part{ ID: 2, Content-type: text/plain
+part{ ID: 1, Content-type: multipart/encrypted
+part{ ID: 2, Content-type: application/pgp-encrypted
+Non-text part: application/pgp-encrypted
+part}
+part{ ID: 3, Content-type: multipart/mixed
+part{ ID: 4, Content-type: text/plain
 This is a test encrypted message.
 part}
-attachment{ ID: 3, Content-type: application/octet-stream
+attachment{ ID: 5, Content-type: application/octet-stream
 Attachment: TESTATTACHMENT (application/octet-stream)
 Non-text part: application/octet-stream
 attachment}
 part}
+part}
 body}
 message}'
 test_expect_equal \
@@ -194,33 +199,37 @@ expected='[[[{id: X,
  body: [{id: 1,
  encstatus: [{status: good}],
  sigstatus: [],
- content-type: multipart/mixed,
+ content-type: multipart/encrypted,
  content: [{id: 2,
+ content-type: application/pgp-encrypted},
+ {id: 3,
+ content-type: multipart/mixed,
+ content: [{id: 4,
  content-type: text/plain,
  content: This is a test encrypted message.\n},
- {id: 3,
+ {id: 5,
  content-type: application/octet-stream,
- filename: TESTATTACHMENT}]}]},
+ filename: TESTATTACHMENT}]}]}]},
  ['
 test_expect_equal \
 $output \
 $expected
 
-test_begin_subtest decryption, --format=json, --part=2
-output=$(notmuch show 

[PATCH 1/4] Do not replace multipart/signed part with content part when doing verification.

2011-05-27 Thread Jameson Graef Rollins
Some folks have complained about the part renumbering that occurs when
the entire multipart/signed part is replaced with the part contents
after verification.  This is primarily because it incurs an additional
computational cost to retrieve individual parts, since verification
has to be performed again to ensure that part numbering is consistent.
This patch simply leaves the full multipart/signed part as is.

The emacs crypto test is also updated to reflect this change.
---
 show-message.c |2 --
 test/crypto|   24 
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/show-message.c b/show-message.c
index 37252b2..849c686 100644
--- a/show-message.c
+++ b/show-message.c
@@ -105,8 +105,6 @@ show_message_part (GMimeObject *part,
}
if ((selected || state-in_zone)  format-part_sigstatus)
format-part_sigstatus (sigvalidity);
-   /* extract only data part, and ignore signature part */
-   part = g_mime_multipart_get_part (multipart, 0);
if (sigvalidity)
g_mime_signature_validity_free (sigvalidity);
}
diff --git a/test/crypto b/test/crypto
index c5abcc3..ef35c55 100755
--- a/test/crypto
+++ b/test/crypto
@@ -57,8 +57,12 @@ expected='[[[{id: X,
  sigstatus: [{status: good,
  fingerprint: '$FINGERPRINT',
  created: 946728000}],
+ content-type: multipart/signed,
+ content: [{id: 2,
  content-type: text/plain,
- content: This is a test signed message.\n}]},
+ content: This is a test signed message.\n},
+ {id: 3,
+ content-type: application/pgp-signature}]}]},
  ['
 test_expect_equal \
 $output \
@@ -88,8 +92,12 @@ expected='[[[{id: X,
  fingerprint: '$FINGERPRINT',
  created: 946728000,
  userid:  Notmuch Test Suite test_su...@notmuchmail.org (INSECURE!)}],
+ content-type: multipart/signed,
+ content: [{id: 2,
  content-type: text/plain,
- content: This is a test signed message.\n}]},
+ content: This is a test signed message.\n},
+ {id: 3,
+ content-type: application/pgp-signature}]}]},
  ['
 test_expect_equal \
 $output \
@@ -117,8 +125,12 @@ expected='[[[{id: X,
  sigstatus: [{status: error,
  keyid: '$(echo $FINGERPRINT | cut -c 25-)',
  errors: 2}],
+ content-type: multipart/signed,
+ content: [{id: 2,
  content-type: text/plain,
- content: This is a test signed message.\n}]},
+ content: This is a test signed message.\n},
+ {id: 3,
+ content-type: application/pgp-signature}]}]},
  ['
 test_expect_equal \
 $output \
@@ -320,8 +332,12 @@ expected='[[[{id: X,
  sigstatus: [{status: error,
  keyid: 6D92612D94E46381,
  errors: 8}],
+ content-type: multipart/signed,
+ content: [{id: 2,
  content-type: text/plain,
- content: This is a test signed message.\n}]},
+ content: This is a test signed message.\n},
+ {id: 3,
+ content-type: application/pgp-signature}]}]},
  ['
 test_expect_equal \
 $output \
-- 
1.7.4.4

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


Re: [PATCH 1/2] emacs: Don't always prompt for the From address when replying

2011-05-27 Thread Jameson Graef Rollins
On Fri, 27 May 2011 11:14:59 +0200, Thomas Jost schno...@schnouki.net wrote:
 You're right, this is mostly annoying when replying to messages. Here's a fix.

Awesome.  Thanks, Thomas.  Tested and works great.

jamie.


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


Re: one-time-iterators

2011-05-27 Thread Patrick Totzke
Excerpts from Austin Clements's message of Fri May 27 03:41:44 +0100 2011:
Have you tried simply calling list() on your thread
iterator to see how expensive it is?  My bet is that it's quite cheap,
both memory-wise and CPU-wise.
   Funny thing:
    q=Database().create_query('*')
    time tlist = list(q.search_threads())
   raises a NotmuchError(STATUS.NOT_INITIALIZED) exception. For some reason
   the list constructor must read mere than once from the iterator.
   So this is not an option, but even if it worked, it would show
   the same behaviour as my above test..
 
  Interesting.  Looks like the Threads class implements __len__ and that
  its implementation exhausts the iterator.  Which isn't a great idea in
  itself, but it turns out that Python's implementation of list() calls
  __len__ if it's available (presumably to pre-size the list) before
  iterating over the object, so it exhausts the iterator before even
  using it.
 
  That said, if list(q.search_threads()) did work, it wouldn't give you
  better performance than your experiment above.
true. Nevertheless I think that list(q.search_threads())
should be equivalent to [t for t in q.search_threads()], which is
something to be fixed in the bindings. Should I file an issue somehow?
Or is enough to state this as a TODO here on the list?

   would it be very hard to implement a Query.search_thread_ids() ?
   This name is a bit off because it had to be done on a lower level.
 
  Lazily fetching the thread metadata on the C side would probably
  address your problem automatically.  But what are you doing that
  doesn't require any information about the threads you're manipulating?
  Agreed. Unfortunately, there seems to be no way to get a list of thread
  ids or a reliable iterator thereof by using the current python bindings.
  It would be enough for me to have the ids because then I could
  search for the few threads I actually need individually on demand.
 
 There's no way to do that from the C API either, so don't feel left
 out.  ]:--8)  It seems to me that the right solution to your problem
 is to make thread information lazy (effectively, everything gathered
 in lib/thread.cc:_thread_add_message).  Then you could probably
 materialize that iterator cheaply. 
Alright. I'll put this on my mental notmuch wish list and 
hope that someone will have addressed this before I run out of
ideas how to improve my UI and have time to look at this myself.
For now, I go with the [t.get_thread_id for t in q.search_threads()]
approach to cache the thread ids myself and live with the fact that
this takes time for large result sets.

 In fact, it's probably worth
 trying a hack where you put dummy information in the thread object
 from _thread_add_message and see how long it takes just to walk the
 iterator (unfortunately I don't think profiling will help much here
 because much of your time is probably spent waiting for I/O).
I don't think I understand what you mean by dummy info in a thread
object.

 I don't think there would be any downside to doing this for eager
 consumers like the CLI.
one should think so, yes.
/p


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


Re: normalizing part numbering across PGP/MIME processing

2011-05-27 Thread Daniel Kahn Gillmor
On Fri, 27 May 2011 03:27:35 -0700, Jameson Graef Rollins 
jroll...@finestructure.net wrote:
 Ok.  So I very much hope this patch series satisfies those who were
 bothered by the part renumbering that was happening when PGP/MIME
 parts were processed.  For signed messages we no longer modify the
 parts at all, so numbering always remains constant, and for encrypted
 messages the numbering will only change if the encrypted message is
 itself multipart.  We'll have to live with the encrypted multipart
 renumbering until we have a more sophisticated part numbering scheme.
 However, that's a separate issue that can hopefully be dealt with
 after the full crypto functionality is pulled.

These patches resolve my outstanding part-numbering concern with the
crypto verification business.  I recommend merging them to the mainline.

Then can we release 0.6 pretty please? :)

There's nothing stopping us from releasing 0.7 if there are more
features pending, but i'd really like to be able to say please run 0.6
or later to handle verifying cryptographic signatures.

 --dkg


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


[PATCH] emacs: User-defined sections in notmuch-hello

2011-05-27 Thread Daniel Schoepe
From the commit message:
 This patch allows the user to define various sections that will
 be displayed in notmuch-hello. I tried to keep the section
 description flexible, so it allows different queries for the
 tag buttons and the counts next to them, as well as hiding items
 with zero results.
  
 The sections are (hopefully) fully editable using customize.
  
 I have not yet rewritten the saved-searches portion using this
 mechanism, to avoid breaking the configurations of many users.

It contains a lot of code to make the whole thing play nice with
customize, but hey, at least it's (somewhat) user-friendly. :)

I'm also not sure if using plists to describe the sections was a
particularly (e)lispy way to do this, so comments are appreciated.

I'll also work on some tests for this functionality, (if no one
has big, structural complaints about the code).

Cheers,
Daniel

From bca5a58d7910b6d46a782db787dfe07e2fcf21e1 Mon Sep 17 00:00:00 2001
From: Daniel Schoepe daniel.scho...@googlemail.com
Date: Thu, 26 May 2011 23:03:22 +0200
Subject: [PATCH] emacs: User-defined sections in notmuch-hello

This patch allows the user to define various sections that will
be displayed in notmuch-hello. I tried to keep the section
description flexible, so it allows different queries for the
tag buttons and the counts next to them, as well as hiding items
with zero results.

The sections are (hopefully) fully editable using customize.

I have not yet rewritten the saved-searches portion using this
mechanism, to avoid breaking the configurations of many users.
---
 emacs/notmuch-hello.el |  328 ++--
 emacs/notmuch-lib.el   |   22 ++--
 2 files changed, 275 insertions(+), 75 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 916cda1..40333ae 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -55,24 +55,115 @@
   :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)
+(defvar notmuch-hello-section-all-tags
+  (list :title All tags:
+	:type 'eachtag)
+  Default section definition for the \all tags\ section.)
+
+(defvar notmuch-hello-section-unread-tags
+  (list :title All tags, unread only:
+	:type 'eachtag
+	:make-query tag:unread)
+  Show and count only unread messages for each tag.)
+
+(defvar notmuch-hello-hidden-sections nil
+  Sections that are hidden in notmuch-hello)
+
+(defvar notmuch-hello-first-run t
+  Internal variable for hiding sections with :hidden-on-startup)
+
+(define-widget 'notmuch-section-query-type 'lazy
+  Customize-type for query items
+  :tag Query item
+  :type '(list (string :tag Search title)
+	   (string :tag Query to use)
+	   (choice :tag Query for message count
+		   (const :tag Use previous query nil)
+		   (string :tag Different query
+
+(define-widget 'notmuch-section-make-query-type 'lazy
+  Customize-type for query functions
+  :tag Query function
+  :type '(choice (const :tag All messages with tag nil)
+		 (const :tag Only unread messages tag:unread)
+		 (string :tag Custom filter string)
+		 (function :tag Custom filter function)))
+
+(define-widget 'notmuch-section-type 'lazy
+  Customize-type for sections
+  :tag Custom section
+  :type
+  '(plist :options (((const :tag Title for this section :title)
+		 string)
+		((const :tag Type of this section :type)
+		 (choice (const :tag One item for each tag
+eachtag)
+			 (const :tag Custom list of searches
+query-list)))
+		((const :tag Function to generate a query, ignored if custom list
+			:make-query)
+		 notmuch-section-make-query)
+		((const :tag Function to generate counts, ignored if custom list
+			:make-count)
+		 notmuch-section-make-query)
+		((const :tag Function to create titles for tag entries, ignored if custom list
+			:make-title)
+		 (choice (const :tag The tag itself nil)
+			 (function :tag Custom function)))
+		((const :tag List of tags to hide, ignored if custom list
+			:hide-tags)
+		 (repeat (string :tag tag)))
+		((const :tag Search queries, only used if custom list
+			:items)
+		 (repeat 

[PATCH] emacs: Give mutlipart/{signed, encrypted} their own part handler.

2011-05-27 Thread Jameson Graef Rollins
This is the best way to make the displayed output for
decrypted/verified messages clearer.  The special sigstatus and
encstatus buttons are now displayed under the part header button.  The
part header button is also tweaked to provide information to user
about how to proces crypto.
---

This patch replaces the previous version of this patch (9d7a9e3a) that
was mistakenly not emitting the sigstatus button for decrypted signed
messages.

 emacs/notmuch-crypto.el |   12 
 emacs/notmuch-show.el   |   60 +++
 2 files changed, 56 insertions(+), 16 deletions(-)

diff --git a/emacs/notmuch-crypto.el b/emacs/notmuch-crypto.el
index 944452b..cb02840 100644
--- a/emacs/notmuch-crypto.el
+++ b/emacs/notmuch-crypto.el
@@ -46,7 +46,7 @@ search.
 (defun notmuch-crypto-insert-sigstatus-button (sigstatus from)
   (let* ((status (plist-get sigstatus :status))
 (help-msg nil)
-(label multipart/signed: signature not processed)
+(label Signature not processed)
 (face '(:background red :foreground black)))
 (cond
  ((string= status good)
@@ -82,17 +82,17 @@ search.
 (defun notmuch-crypto-insert-encstatus-button (encstatus)
   (let* ((status (plist-get encstatus :status))
 (help-msg nil)
-(label multipart/encrypted: decryption not attempted)
+(label Decryption not attempted)
 (face '(:background purple :foreground black)))
 (cond
  ((string= status good)
-  (setq label decryption successful))
+  (setq label Decryption successful))
  ((string= status bad)
-  (setq label decryption error))
+  (setq label Decryption error))
  (t
-  (setq label (concat unknown encstatus \ status \
+  (setq label (concat Unknown encstatus \ status \
 (insert-button
- (concat [ multipart/encrypted:  label  ])
+ (concat [  label  ])
  :type 'notmuch-crypto-status-button-type
  'help-echo help-msg
  'face face
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index aa6ddd1..6c498ab 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -446,6 +446,56 @@ current buffer, if possible.
   (indent-rigidly start (point) 1)))
   t)
 
+(defun notmuch-show-insert-part-multipart/signed (msg part content-type nth 
depth declared-type)
+  (let ((button (notmuch-show-insert-part-header nth declared-type 
content-type nil)))
+(button-put button 'face '(:foreground blue))
+;; add signature status button if sigstatus provided
+(if (plist-member part :sigstatus)
+   (let* ((headers (plist-get msg :headers))
+  (from (plist-get headers :From))
+  (sigstatus (car (plist-get part :sigstatus
+ (notmuch-crypto-insert-sigstatus-button sigstatus from))
+  ;; if we're not adding sigstatus, tell the user how they can get it
+  (button-put button 'help-echo Set notmuch-crypto-process-mime to 
process cryptographic mime parts.)))
+
+  (let ((inner-parts (plist-get part :content))
+   (start (point)))
+;; Show all of the parts.
+(mapc (lambda (inner-part)
+   (notmuch-show-insert-bodypart msg inner-part depth))
+ inner-parts)
+
+(when notmuch-show-indent-multipart
+  (indent-rigidly start (point) 1)))
+  t)
+
+(defun notmuch-show-insert-part-multipart/encrypted (msg part content-type nth 
depth declared-type)
+  (let ((button (notmuch-show-insert-part-header nth declared-type 
content-type nil)))
+(button-put button 'face '(:foreground blue))
+;; add encryption status button if encstatus specified
+(if (plist-member part :encstatus)
+   (let ((encstatus (car (plist-get part :encstatus
+ (notmuch-crypto-insert-encstatus-button encstatus)
+ ;; add signature status button if sigstatus specified
+ (if (plist-member part :sigstatus)
+ (let* ((headers (plist-get msg :headers))
+(from (plist-get headers :From))
+(sigstatus (car (plist-get part :sigstatus
+   (notmuch-crypto-insert-sigstatus-button sigstatus from
+  ;; if we're not adding encstatus, tell the user how they can get it
+  (button-put button 'help-echo Set notmuch-crypto-process-mime to 
process cryptographic mime parts.)))
+
+  (let ((inner-parts (plist-get part :content))
+   (start (point)))
+;; Show all of the parts.
+(mapc (lambda (inner-part)
+   (notmuch-show-insert-bodypart msg inner-part depth))
+ inner-parts)
+
+(when notmuch-show-indent-multipart
+  (indent-rigidly start (point) 1)))
+  t)
+
 (defun notmuch-show-insert-part-multipart/* (msg part content-type nth depth 
declared-type)
   (notmuch-show-insert-part-header nth declared-type content-type nil)
   (let ((inner-parts (plist-get part :content))
@@ -593,16 +643,6 @@ current buffer, if possible.
   Insert the body part PART at depth DEPTH in the current thread.
   (let ((content-type 

Re: one-time-iterators

2011-05-27 Thread Austin Clements
On Fri, May 27, 2011 at 2:04 PM, Patrick Totzke
patricktot...@googlemail.com wrote:
 Excerpts from Austin Clements's message of Fri May 27 03:41:44 +0100 2011:
Have you tried simply calling list() on your thread
iterator to see how expensive it is?  My bet is that it's quite cheap,
both memory-wise and CPU-wise.
   Funny thing:
    q=Database().create_query('*')
    time tlist = list(q.search_threads())
   raises a NotmuchError(STATUS.NOT_INITIALIZED) exception. For some reason
   the list constructor must read mere than once from the iterator.
   So this is not an option, but even if it worked, it would show
   the same behaviour as my above test..
 
  Interesting.  Looks like the Threads class implements __len__ and that
  its implementation exhausts the iterator.  Which isn't a great idea in
  itself, but it turns out that Python's implementation of list() calls
  __len__ if it's available (presumably to pre-size the list) before
  iterating over the object, so it exhausts the iterator before even
  using it.
 
  That said, if list(q.search_threads()) did work, it wouldn't give you
  better performance than your experiment above.
 true. Nevertheless I think that list(q.search_threads())
 should be equivalent to [t for t in q.search_threads()], which is
 something to be fixed in the bindings. Should I file an issue somehow?
 Or is enough to state this as a TODO here on the list?

Yes, they should be equivalent.

Sebastian was thinking about fixing the larger issue of generator
exhaustion, which would address this, though the performance would
depend on the cost of iterating twice.  This is why generators
shouldn't support __len__.  Unfortunately, it's probably hard to get
rid of at this point and I doubt there's a way to tell list() to
overlook the presence of a __len__ method.

   would it be very hard to implement a Query.search_thread_ids() ?
   This name is a bit off because it had to be done on a lower level.
 
  Lazily fetching the thread metadata on the C side would probably
  address your problem automatically.  But what are you doing that
  doesn't require any information about the threads you're manipulating?
  Agreed. Unfortunately, there seems to be no way to get a list of thread
  ids or a reliable iterator thereof by using the current python bindings.
  It would be enough for me to have the ids because then I could
  search for the few threads I actually need individually on demand.

 There's no way to do that from the C API either, so don't feel left
 out.  ]:--8)  It seems to me that the right solution to your problem
 is to make thread information lazy (effectively, everything gathered
 in lib/thread.cc:_thread_add_message).  Then you could probably
 materialize that iterator cheaply.
 Alright. I'll put this on my mental notmuch wish list and
 hope that someone will have addressed this before I run out of
 ideas how to improve my UI and have time to look at this myself.
 For now, I go with the [t.get_thread_id for t in q.search_threads()]
 approach to cache the thread ids myself and live with the fact that
 this takes time for large result sets.

 In fact, it's probably worth
 trying a hack where you put dummy information in the thread object
 from _thread_add_message and see how long it takes just to walk the
 iterator (unfortunately I don't think profiling will help much here
 because much of your time is probably spent waiting for I/O).
 I don't think I understand what you mean by dummy info in a thread
 object.

In _thread_add_message, rather than looking up the message's author,
subject, etc, just hard-code some dummy values.  Performance-wise,
this would simulate making the thread metadata lookup lazy, so you
could see if making this lazy would address your problem.
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] test: change #!/bin/bash to #!/usr/bin/env bash enhances portability

2011-05-27 Thread Carl Worth
On Wed,  1 Dec 2010 21:27:52 +0100, Joel Borggrén-Franck 
joel.borggren.fra...@gmail.com wrote:
 From: Joel Borggrén-Franck j...@codehouse.se
 
 Change #!/bin/bash at start of tests to #!/usr/bin/env bash. That way
 systems running on bash  4 can prepend bash = 4 to path before
 running the tests.

Thanks for the patch, Joel!

This issue recently came up again on IRC, so I dug out this patch,
applied, and pushed it.

-Carl

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


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


Re: [PATCH] emacs: User-defined sections in notmuch-hello

2011-05-27 Thread Daniel Schoepe
I forgot to run the test suite with the previous patch, which
revealed some minor formatting problems, updated patch in the
attachment.
From bca5a58d7910b6d46a782db787dfe07e2fcf21e1 Mon Sep 17 00:00:00 2001
From: Daniel Schoepe daniel.scho...@googlemail.com
Date: Thu, 26 May 2011 23:03:22 +0200
Subject: [PATCH] emacs: User-defined sections in notmuch-hello

This patch allows the user to define various sections that will
be displayed in notmuch-hello. I tried to keep the section
description flexible, so it allows different queries for the
tag buttons and the counts next to them, as well as hiding items
with zero results.

The sections are (hopefully) fully editable using customize.

I have not yet rewritten the saved-searches portion using this
mechanism, to avoid breaking the configurations of many users.
---
 emacs/notmuch-hello.el |  328 ++--
 emacs/notmuch-lib.el   |   22 ++--
 2 files changed, 275 insertions(+), 75 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 916cda1..40333ae 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -55,24 +55,115 @@
   :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)
+(defvar notmuch-hello-section-all-tags
+  (list :title All tags:
+	:type 'eachtag)
+  Default section definition for the \all tags\ section.)
+
+(defvar notmuch-hello-section-unread-tags
+  (list :title All tags, unread only:
+	:type 'eachtag
+	:make-query tag:unread)
+  Show and count only unread messages for each tag.)
+
+(defvar notmuch-hello-hidden-sections nil
+  Sections that are hidden in notmuch-hello)
+
+(defvar notmuch-hello-first-run t
+  Internal variable for hiding sections with :hidden-on-startup)
+
+(define-widget 'notmuch-section-query-type 'lazy
+  Customize-type for query items
+  :tag Query item
+  :type '(list (string :tag Search title)
+	   (string :tag Query to use)
+	   (choice :tag Query for message count
+		   (const :tag Use previous query nil)
+		   (string :tag Different query
+
+(define-widget 'notmuch-section-make-query-type 'lazy
+  Customize-type for query functions
+  :tag Query function
+  :type '(choice (const :tag All messages with tag nil)
+		 (const :tag Only unread messages tag:unread)
+		 (string :tag Custom filter string)
+		 (function :tag Custom filter function)))
+
+(define-widget 'notmuch-section-type 'lazy
+  Customize-type for sections
+  :tag Custom section
+  :type
+  '(plist :options (((const :tag Title for this section :title)
+		 string)
+		((const :tag Type of this section :type)
+		 (choice (const :tag One item for each tag
+eachtag)
+			 (const :tag Custom list of searches
+query-list)))
+		((const :tag Function to generate a query, ignored if custom list
+			:make-query)
+		 notmuch-section-make-query)
+		((const :tag Function to generate counts, ignored if custom list
+			:make-count)
+		 notmuch-section-make-query)
+		((const :tag Function to create titles for tag entries, ignored if custom list
+			:make-title)
+		 (choice (const :tag The tag itself nil)
+			 (function :tag Custom function)))
+		((const :tag List of tags to hide, ignored if custom list
+			:hide-tags)
+		 (repeat (string :tag tag)))
+		((const :tag Search queries, only used if custom list
+			:items)
+		 (repeat notmuch-section-query))
+		((const :tag Hide if there are no results :hide-empty)
+		 boolean)
+		((const :tag Where should this be positioned :position)
+		 (choice (const :tag Before the search input before)
+			 (const :tag After the search input after))
+
+(defcustom notmuch-hello-sections (list notmuch-hello-section-all-tags)
+  Sections to be displayed in notmuch-hello.
+
+This variable does not include the saved-searches section, which
+is handled separately.
+This variable should be a list of plists with the following
+possible properties:
+
+:title - The title of the section
+:type - Can be 'eachtag or 'query-list, If 'eachtag, generate one
+item for each tag, otherwise use a fixed set of items.
+The following 

Re: [PATCH] emacs: User-defined sections in notmuch-hello

2011-05-27 Thread Daniel Schoepe
Accidentally attached the old file again, sorry for the noise.
From cafc93e3364955cab70885fec740fee87bc3248e Mon Sep 17 00:00:00 2001
From: Daniel Schoepe daniel.scho...@googlemail.com
Date: Thu, 26 May 2011 23:03:22 +0200
Subject: [PATCH] emacs: User-defined sections in notmuch-hello

This patch allows the user to define various sections that will
be displayed in notmuch-hello. I tried to keep the section
description flexible, so it allows different queries for the
tag buttons and the counts next to them, as well as hiding items
with zero results.

The sections are (hopefully) fully editable using customize.

I have not yet rewritten the saved-searches portion using this
mechanism, to avoid breaking the configurations of many users.
---
 emacs/notmuch-hello.el |  333 
 emacs/notmuch-lib.el   |   22 +-
 test/emacs.expected-output/notmuch-hello   |2 +-
 .../notmuch-hello-no-saved-searches|2 +-
 .../emacs.expected-output/notmuch-hello-with-empty |2 +-
 5 files changed, 282 insertions(+), 79 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 916cda1..f014357 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -55,24 +55,115 @@
   :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)
+(defvar notmuch-hello-section-all-tags
+  (list :title All tags:
+	:type 'eachtag)
+  Default section definition for the \all tags\ section.)
+
+(defvar notmuch-hello-section-unread-tags
+  (list :title All tags, unread only:
+	:type 'eachtag
+	:make-query tag:unread)
+  Show and count only unread messages for each tag.)
+
+(defvar notmuch-hello-hidden-sections nil
+  Sections that are hidden in notmuch-hello)
+
+(defvar notmuch-hello-first-run t
+  Internal variable for hiding sections with :hidden-on-startup)
+
+(define-widget 'notmuch-section-query-type 'lazy
+  Customize-type for query items
+  :tag Query item
+  :type '(list (string :tag Search title)
+	   (string :tag Query to use)
+	   (choice :tag Query for message count
+		   (const :tag Use previous query nil)
+		   (string :tag Different query
+
+(define-widget 'notmuch-section-make-query-type 'lazy
+  Customize-type for query functions
+  :tag Query function
+  :type '(choice (const :tag All messages with tag nil)
+		 (const :tag Only unread messages tag:unread)
+		 (string :tag Custom filter string)
+		 (function :tag Custom filter function)))
+
+(define-widget 'notmuch-section-type 'lazy
+  Customize-type for sections
+  :tag Custom section
+  :type
+  '(plist :options (((const :tag Title for this section :title)
+		 string)
+		((const :tag Type of this section :type)
+		 (choice (const :tag One item for each tag
+eachtag)
+			 (const :tag Custom list of searches
+query-list)))
+		((const :tag Function to generate a query, ignored if custom list
+			:make-query)
+		 notmuch-section-make-query)
+		((const :tag Function to generate counts, ignored if custom list
+			:make-count)
+		 notmuch-section-make-query)
+		((const :tag Function to create titles for tag entries, ignored if custom list
+			:make-title)
+		 (choice (const :tag The tag itself nil)
+			 (function :tag Custom function)))
+		((const :tag List of tags to hide, ignored if custom list
+			:hide-tags)
+		 (repeat (string :tag tag)))
+		((const :tag Search queries, only used if custom list
+			:items)
+		 (repeat notmuch-section-query))
+		((const :tag Hide if there are no results :hide-empty)
+		 boolean)
+		((const :tag Where should this be positioned :position)
+		 (choice (const :tag Before the search input before)
+			 (const :tag After the search input after))
+
+(defcustom notmuch-hello-sections (list notmuch-hello-section-all-tags)
+  Sections to be displayed in notmuch-hello.
+
+This variable does not include the saved-searches section, which
+is handled separately.
+This variable should be a list of plists with the following
+possible properties:
+
+:title - The title of the section
+:type - Can 

Re: [PATCH] test: use `princ' instead of `message' calls in emacs tests

2011-05-27 Thread Carl Worth
On Tue, 10 May 2011 10:25:08 +0400, Dmitry Kurochkin 
dmitry.kuroch...@gmail.com wrote:
 The patch replaces all (message (buffer-string)) calls in emacs
 tests with (princ (buffer-string)).  This avoids accidentally
 interpreting '%' as format specifiers and makes code simpler
 because we do not need to capture stderr.
 
 Also, the patch works around an Emacs (23.3+1-1 on current Debian
 Unstable) segfault in Ensure that emacs doesn't drop results
 test.

Thanks so much for the fix! I hadn't noticed the segfault until the
recent additional include of test-lib.el, (which of course shouldn't
actually be changing anything), which seems to tickle the emacs bug a
little more frequently for me at least.

The segfault made it obvious that this was an emacs bug, but it was
annoying to hit. It will be nice to have this fix in place.

This change is pushed now.

-Carl

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


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


Re: [PATCH 2/2] Workaround for Emacs bug #8721.

2011-05-27 Thread Dmitry Kurochkin
This is an amended patch which uses `isearch-range-invisible' from Emacs
trunk r104393 (includes the second patch from #8721).

Regards,
  Dmitry
From d56f2c308c995639aad04f0e5388b52912e603b0 Mon Sep 17 00:00:00 2001
From: Dmitry Kurochkin dmitry.kuroch...@gmail.com
Date: Fri, 27 May 2011 01:35:09 +0400
Subject: [PATCH] Workaround for Emacs bug #8721.

The patch adds `notmuch-isearch-range-invisible' function which
is the same as `isearch-range-invisible' but with fixed Emacs bug
 #8721.  Advice added for `isearch-range-invisible' which calls
`notmuch-isearch-range-invisible' instead of the original
`isearch-range-invisible' when in `notmuch-show-mode'.
---
 emacs/notmuch-wash.el |   67 +
 1 files changed, 67 insertions(+), 0 deletions(-)

diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el
index 992fa8f..e046d62 100644
--- a/emacs/notmuch-wash.el
+++ b/emacs/notmuch-wash.el
@@ -298,4 +298,71 @@ for error.
 
 ;;
 
+;; Temporary workaround for Emacs bug #8721
+;; http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8721
+
+(defun notmuch-isearch-range-invisible (beg end)
+  Same as `isearch-range-invisible' but with fixed Emacs bug #8721.
+  (when (/= beg end)
+;; Check that invisibility runs up to END.
+(save-excursion
+  (goto-char beg)
+  (let (;; can-be-opened keeps track if we can open some overlays.
+	(can-be-opened (eq search-invisible 'open))
+	;; the list of overlays that could be opened
+	(crt-overlays nil))
+	(when (and can-be-opened isearch-hide-immediately)
+	  (isearch-close-unnecessary-overlays beg end))
+	;; If the following character is currently invisible,
+	;; skip all characters with that same `invisible' property value.
+	;; Do that over and over.
+	(while (and ( (point) end) (invisible-p (point)))
+	  (if (invisible-p (get-text-property (point) 'invisible))
+	  (progn
+		(goto-char (next-single-property-change (point) 'invisible
+			nil end))
+		;; if text is hidden by an `invisible' text property
+		;; we cannot open it at all.
+		(setq can-be-opened nil))
+	(when can-be-opened
+	  (let ((overlays (overlays-at (point)))
+		ov-list
+		o
+		invis-prop)
+		(while overlays
+		  (setq o (car overlays)
+			invis-prop (overlay-get o 'invisible))
+		  (if (invisible-p invis-prop)
+		  (if (overlay-get o 'isearch-open-invisible)
+			  (setq ov-list (cons o ov-list))
+			;; We found one overlay that cannot be
+			;; opened, that means the whole chunk
+			;; cannot be opened.
+			(setq can-be-opened nil)))
+		  (setq overlays (cdr overlays)))
+		(if can-be-opened
+		;; It makes sense to append to the open
+		;; overlays list only if we know that this is
+		;; t.
+		(setq crt-overlays (append ov-list crt-overlays)
+	(goto-char (next-overlay-change (point)
+	;; See if invisibility reaches up thru END.
+	(if (= (point) end)
+	(if (and can-be-opened (consp crt-overlays))
+		(progn
+		  (setq isearch-opened-overlays
+			(append isearch-opened-overlays crt-overlays))
+		  (mapc 'isearch-open-overlay-temporary crt-overlays)
+		  nil)
+	  (setq isearch-hidden t)))
+
+(defadvice isearch-range-invisible (around notmuch-isearch-range-invisible-advice activate)
+  Call `notmuch-isearch-range-invisible' instead of the original
+`isearch-range-invisible' when in `notmuch-show-mode' mode.
+  (if (eq major-mode 'notmuch-show-mode)
+  (setq ad-return-value (notmuch-isearch-range-invisible beg end))
+ad-do-it))
+
+;;
+
 (provide 'notmuch-wash)
-- 
1.7.5.1

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


Re: normalizing part numbering across PGP/MIME processing

2011-05-27 Thread Carl Worth
On Fri, 27 May 2011 03:27:35 -0700, Jameson Graef Rollins 
jroll...@finestructure.net wrote:
 Ok.  So I very much hope this patch series satisfies those who were
 bothered by the part renumbering that was happening when PGP/MIME
 parts were processed.  For signed messages we no longer modify the
 parts at all, so numbering always remains constant, and for encrypted
 messages the numbering will only change if the encrypted message is
 itself multipart.

That sounds much better to me. I think the remaining issues I have with
the patch series are very minor and can be applied after the fact. I'd
push the series right now except that I happen to have no network access
at the moment. [I'm queueing up this message for delivery, so if I'm on
top of things when I'm back in range, I'll push right away.]

So, well done, Jameson! You've been extremely patient as I sat on this
patch series for *so* long, and then made you rebuild it so many
times. I hope you think the rebuilds were at least worth it for the much
cleaner final state, (I know that the useless waiting wasn't worth it).

I promise you don't need to rebuild this branch anymore, nor keep asking
me to merge it. Go enjoy a good US-holiday weekend. You've earned it!

That said, here are the (minor) issues I have with the series:

  * More tests should be switched to the new text_expect_equal_file

This isn't a problem with the series---but will be a nice
fix. I think the current notmuch search --output=tags * is
broken due to a missing final newline---or at least has been
broken that way recently. So it will be nice to have this
support for testing a final newline.

  * The series duplicates some existing code into a new
emacs_deliver_message

The previously-existing code should be removed and replaced with
a call to the new function.

  * Should we set the crypto option to verify/decrypt by default?

That would certainly be convenient for me at least.

For people who don't want this, they can set the variable to
nil. But then they'll still have the following issue:

  * I'm not a fan of the M-RET option for decrypting a message

If someone is going to have encrypted messages not decrypted by
default, then they can currently decrypt by opening the message
with M-RET. But I think in common use, the user is likely to
only realize too late that they want to decrypt the message.

So what I'd love to see is a keybinding for decrypting a message
from the view of the message itself. (One natural place would be
by activating the button of the encrypted part---but a
keybinding to review with decryption would be fine too---likely
easier to code and easier to use.)

  * I can't actually get decryption to work for me. :-(

When I run notmuch show --decrypt on a message encrypted with
my public key I get a segfault within libgmime, specifically in
the g_mime_session_request_passwd function.

My first guess is that this is due to the fact that gpg-agent
can't be run on my system (Debian unstable):

$ gpg-agent
gpg-agent: symbol lookup error: /usr/lib/libassuan.so.0: undefined 
symbol: gpg_err_set_errno

I've got a Debian bug report queued up for this.

I also tried running the same notmuch show command without
gpg-agent installed. How is libgmime supposed to actually
request a password in a case like this?

Anyway, I know that not everyone has this same problem with the
series, so I'm not blocking it for this.

-Carl

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


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