emacs: Respecting message-cite-style

2023-03-15 Thread Keith Packard

When replying to mail, notmuch normally inserts the cited email using
'message-cite-original'. That function doesn't apply any citation style
settings from message-cite-style — message-yank-buffer does that before
(eventually) getting down to message-cite-original.

It seems that using message-yank-original "just works" for me as a
setting for notmuch-mua-cite-function, and now the settings from
message-cite-style do get applied.

With this, it would be easy to add gnus-style auto-selection of
message-cite-style based on header contents, so I can reply to work
email in 'outlook' style while replying to regular email in 'normal'
style.

-- 
-keith


signature.asc
Description: PGP signature
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH] Don't bother checking for mbox files

2016-03-09 Thread Keith Packard

Postfix adds mbox-style From lines when used in combination with
maildrop or .forward files. If they have another line starting with
'From ' in them, notmuch complains about them not being mail files.

If we assume the user hasn't screwed up and misconfigured their mail
system, then we can safely ignore whether the file started with an
mbox header and just parse it as a single-message file.

I can't see any harm in doing this; in the worst case, you'll have a
single 'message' which contains multiple emails now, while the
alternative is to miss mail entirely.

I could be convinced to add a config option to enable this behaviour,
but I'd really rather not.

Signed-off-by: Keith Packard <kei...@keithp.com>
---
 lib/message-file.c | 29 +
 1 file changed, 1 insertion(+), 28 deletions(-)

diff --git a/lib/message-file.c b/lib/message-file.c
index ee30520..f03e1db 100644
--- a/lib/message-file.c
+++ b/lib/message-file.c
@@ -98,22 +98,6 @@ _notmuch_message_file_close (notmuch_message_file_t *message)
 talloc_free (message);
 }
 
-static notmuch_bool_t
-_is_mbox (FILE *file)
-{
-char from_buf[5];
-notmuch_bool_t ret = FALSE;
-
-/* Is this mbox? */
-if (fread (from_buf, sizeof (from_buf), 1, file) == 1 &&
-   strncmp (from_buf, "From ", 5) == 0)
-   ret = TRUE;
-
-rewind (file);
-
-return ret;
-}
-
 notmuch_status_t
 _notmuch_message_file_parse (notmuch_message_file_t *message)
 {
@@ -121,13 +105,10 @@ _notmuch_message_file_parse (notmuch_message_file_t 
*message)
 GMimeParser *parser;
 notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
 static int initialized = 0;
-notmuch_bool_t is_mbox;
 
 if (message->message)
return NOTMUCH_STATUS_SUCCESS;
 
-is_mbox = _is_mbox (message->file);
-
 if (! initialized) {
g_mime_init (GMIME_ENABLE_RFC2047_WORKAROUNDS);
initialized = 1;
@@ -144,7 +125,7 @@ _notmuch_message_file_parse (notmuch_message_file_t 
*message)
 g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream), FALSE);
 
 parser = g_mime_parser_new_with_stream (stream);
-g_mime_parser_set_scan_from (parser, is_mbox);
+g_mime_parser_set_scan_from (parser, FALSE);
 
 message->message = g_mime_parser_construct_message (parser);
 if (! message->message) {
@@ -152,14 +133,6 @@ _notmuch_message_file_parse (notmuch_message_file_t 
*message)
goto DONE;
 }
 
-if (is_mbox && ! g_mime_parser_eos (parser)) {
-   /*
-* This is a multi-message mbox. (For historical reasons, we
-* do support single-message mboxes.)
-*/
-   status = NOTMUCH_STATUS_FILE_NOT_EMAIL;
-}
-
   DONE:
 g_object_unref (stream);
 g_object_unref (parser);
-- 
2.7.0


-- 
-keith


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


[PATCH] emacs: notmuch-hello: Add variable to control order or saved-search results

2014-02-07 Thread Keith Packard
Carl Worth  writes:

> This allows for the user to control the order that results are
> returned from saved-searches, (and independently from the order of all
> other searches which is controlled by notmuch-search-oldest-first).

After we lost this from notmuch, I added this to my .emacs, which made
my hello searches oldest first:

(defun notmuch-hello-widget-search (widget  ignore)
 (notmuch-search (widget-get widget
  :notmuch-search-terms)
 t))


-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 810 bytes
Desc: not available
URL: 



Re: [PATCH] emacs: notmuch-hello: Add variable to control order or saved-search results

2014-02-07 Thread Keith Packard
Carl Worth cwo...@cworth.org writes:

 This allows for the user to control the order that results are
 returned from saved-searches, (and independently from the order of all
 other searches which is controlled by notmuch-search-oldest-first).

After we lost this from notmuch, I added this to my .emacs, which made
my hello searches oldest first:

(defun notmuch-hello-widget-search (widget rest ignore)
 (notmuch-search (widget-get widget
  :notmuch-search-terms)
 t))


-- 
keith.pack...@intel.com


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


Missing inlined message/rfc822 bodies?

2011-07-18 Thread Keith Packard
On Mon, 18 Jul 2011 08:56:13 -0300, David Bremner  wrote:

> I'm curious if you're both solving the same problem.

I would assume so; my patch simply kludges around the problem with a
hack in the emacs code while jrollins is fixing the underlying gmime
interactions.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



Missing inlined message/rfc822 bodies?

2011-07-18 Thread Keith Packard

I wasn't seeing anything for an inlined message/rfc822 part (as with a
forwarded email message) and discovered that for some reason, the
message structure wasn't as expected. The following patch appears to
help me.

I'm still stuck trying to use the 'v' key to display attachments from
forwarded messages; it looks like mm-dissect-buffer isn't digging into
the attached message and pulling the embedded attachments out or something.

However, I can at least view the message and save the attachments now.

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index f96743b..402fb2c 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -519,6 +519,12 @@ current buffer, if possible."
 ;; message display.
 (insert "\n")

+;;
+;; I dunno, sometimes the message part is a single element list containing 
the plist
+;;
+(if (not inner-parts)
+  (setq inner-parts (plist-get (car message-part) :content)))
+
 ;; Show all of the parts.
 (mapc (lambda (inner-part)
(notmuch-show-insert-bodypart msg inner-part depth))


-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



Re: Missing inlined message/rfc822 bodies?

2011-07-18 Thread Keith Packard
On Mon, 18 Jul 2011 08:56:13 -0300, David Bremner da...@tethera.net wrote:

 I'm curious if you're both solving the same problem.

I would assume so; my patch simply kludges around the problem with a
hack in the emacs code while jrollins is fixing the underlying gmime
interactions.

-- 
keith.pack...@intel.com


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


branchs and tags and merges oh my!

2011-07-01 Thread Keith Packard
On Fri, 01 Jul 2011 18:37:27 -0300, David Bremner  wrote:

> 1) repeat the whole thing with a new release branch for 0.7 and end up
> with
> 
> --.--.--- master
>\  \   
> - 0.6  --- 0.7

That's the 'usual' plan followed by projects which use a central repository.

> 2) merge master onto the release branch
> 
> 
> ---..- master
> \\  /
>  -.. 0.7
> 0.6   now  freeze

This makes doing 'bug fix' stuff on top of 0.6 a bit more challenging.

As an alternative, you probably should have simply put non-release
patches on a separate 'feature branch' (probably residing in the feature
author's repository) which would then be merged onto master post-0.6, in
the 'merge window' plan. That's the usual plan followed by projects
using multiple repositories and time-based releases. With this model,
you simply release from master when the time comes.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



Printing mail

2010-11-09 Thread Keith Packard
On Wed, 10 Nov 2010 08:32:01 +0100, Sebastian Spaeth  
wrote:

> which gives me nice menu entries for previewing my printouts (defaults
> to 'gv' but can easily be set to use 'evince') and which provides the
> M-x pr-ps-buffer-preview command to invoke the print preview directly
> (unfortunately it still asks about the n-up scaling of pages).

Oh, but that doesn't print a message, it prints a buffer which may contain
other stuff, and may have some elided lines.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



Printing mail

2010-11-09 Thread Keith Packard
On Tue, 09 Nov 2010 17:16:48 +0100, Sebastian Spaeth  
wrote:

> M-x ps-print buffer doesn't look too bad here and even copes with the
> encoding better than the printout of your mail with muttprint had
> looked.

I like the header formatting. And, using evince provides a 'friendly'
print dialog. But, yeah, something that dealt with mail encodings and
attachments would be even nicer.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



Printing mail

2010-11-09 Thread Keith Packard

Print is dead. Or so they say

Here's a script I'm using with '|' to get mail printed. As you can see,
it previews the mail on-screen with 'evince', from which you use the
regular 'print' dialog.

#!/bin/sh
tmp=`mktemp`
muttprint -p "TO_FILE:$tmp"
evince $tmp
rm $tmp

Making this more secure would be nice.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



Printing mail

2010-11-09 Thread Keith Packard

Print is dead. Or so they say

Here's a script I'm using with '|' to get mail printed. As you can see,
it previews the mail on-screen with 'evince', from which you use the
regular 'print' dialog.

#!/bin/sh
tmp=`mktemp`
muttprint -p TO_FILE:$tmp
evince $tmp
rm $tmp

Making this more secure would be nice.

-- 
keith.pack...@intel.com


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


Re: Printing mail

2010-11-09 Thread Keith Packard
On Tue, 09 Nov 2010 17:16:48 +0100, Sebastian Spaeth sebast...@sspaeth.de 
wrote:

 M-x ps-print buffer doesn't look too bad here and even copes with the
 encoding better than the printout of your mail with muttprint had
 looked.

I like the header formatting. And, using evince provides a 'friendly'
print dialog. But, yeah, something that dealt with mail encodings and
attachments would be even nicer.

-- 
keith.pack...@intel.com


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


[PATCH] Customize saved search order separately from regular search order

2010-05-03 Thread Keith Packard
I use 'saved searches' as a folder mechanism and want them to be shown
oldest first. Otherwise, while searching for messages normally, I want
to see the most recent messages first. This patch makes these two
default search orders separate.

Signed-off-by: Keith Packard 
---
 emacs/notmuch-hello.el |7 ++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 6a1c56e..f44b1d3 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -37,6 +37,11 @@
   :type 'integer
   :group 'notmuch)

+(defcustom notmuch-saved-search-oldest-first t
+  "Whether saved searches should be oldest first."
+  :type 'boolean
+  :group 'notmuch)
+
 (defcustom notmuch-show-empty-saved-searches nil
   "Should saved searches with no messages be listed?"
   :type 'boolean
@@ -140,7 +145,7 @@ diagonal."
 (defun notmuch-hello-widget-search (widget  ignore)
   (notmuch-search (widget-get widget
  :notmuch-search-terms)
- notmuch-search-oldest-first
+ notmuch-saved-search-oldest-first
  nil nil #'notmuch-hello-search-continuation))

 (defun notmuch-saved-search-count (search)
-- 
1.7.0.4



[PATCH] Customize saved search order separately from regular search order

2010-05-03 Thread Keith Packard
I use 'saved searches' as a folder mechanism and want them to be shown
oldest first. Otherwise, while searching for messages normally, I want
to see the most recent messages first. This patch makes these two
default search orders separate.

Signed-off-by: Keith Packard kei...@keithp.com
---
 emacs/notmuch-hello.el |7 ++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 6a1c56e..f44b1d3 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -37,6 +37,11 @@
   :type 'integer
   :group 'notmuch)
 
+(defcustom notmuch-saved-search-oldest-first t
+  Whether saved searches should be oldest first.
+  :type 'boolean
+  :group 'notmuch)
+
 (defcustom notmuch-show-empty-saved-searches nil
   Should saved searches with no messages be listed?
   :type 'boolean
@@ -140,7 +145,7 @@ diagonal.
 (defun notmuch-hello-widget-search (widget rest ignore)
   (notmuch-search (widget-get widget
  :notmuch-search-terms)
- notmuch-search-oldest-first
+ notmuch-saved-search-oldest-first
  nil nil #'notmuch-hello-search-continuation))
 
 (defun notmuch-saved-search-count (search)
-- 
1.7.0.4

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


[notmuch] viewing text/html (inline or otherwise)

2010-02-09 Thread Keith Packard
On Tue, 09 Feb 2010 16:22:56 -0800, Carl Worth  wrote:

> I know that Keith is using a little script he wrote so that he can hit
> '|' on a message and pipe it to his script. The script then uses a
> utility, (munpack?) to extract all the various MIME parts to a temporary
> directory and then run a web broswer on that directory. Perhaps Keith
> would be so kind as to share that script with the community here.

It's not much of a script, I call it 'view-html'

#!/bin/sh
dir=`mktemp -d`
trap "rm -r $dir" 0
cat "$@" > "$dir"/msg
if munpack -C "$dir" -t < "$dir"/msg 2>&1 | grep 'Did not find'; then
sed -n '/[Hh][Tt][Mm][Ll]/,$p' "$dir"/msg > $dir/part1.html
rm "$dir"/msg
fi
for i in "$dir"/part*; do
if grep -q -i -e '' -e 'text/html' "$i"; then
iceweasel "$i" &
sleep 3
exit 0
fi
done

Note that if iceweasel isn't already running, it seems to shut down when
the script exits. I don't know why.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



Re: [notmuch] viewing text/html (inline or otherwise)

2010-02-09 Thread Keith Packard
On Tue, 09 Feb 2010 16:22:56 -0800, Carl Worth cwo...@cworth.org wrote:

 I know that Keith is using a little script he wrote so that he can hit
 '|' on a message and pipe it to his script. The script then uses a
 utility, (munpack?) to extract all the various MIME parts to a temporary
 directory and then run a web broswer on that directory. Perhaps Keith
 would be so kind as to share that script with the community here.

It's not much of a script, I call it 'view-html'

#!/bin/sh
dir=`mktemp -d`
trap rm -r $dir 0
cat $@  $dir/msg
if munpack -C $dir -t  $dir/msg 21 | grep 'Did not find'; then
sed -n '/[Hh][Tt][Mm][Ll]/,$p' $dir/msg  $dir/part1.html
rm $dir/msg
fi
for i in $dir/part*; do
if grep -q -i -e 'html' -e 'text/html' $i; then
iceweasel $i 
sleep 3
exit 0
fi
done

Note that if iceweasel isn't already running, it seems to shut down when
the script exits. I don't know why.

-- 
keith.pack...@intel.com


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


[notmuch] [PATCH] Make the date parser nicer

2010-01-26 Thread Keith Packard
On Tue, 26 Jan 2010 12:50:41 +0100, "Sebastian Spaeth"  wrote:
> On Mon, 25 Jan 2010 22:36:35 -0800, Keith Packard  
> wrote:
> > Here's some code which further improves date parsing by allowing lots of
> > date formats, including things like "today", "thisweek", ISO and US date
> > formats and month names. You can separate two dates with .. to make a
> > range, or you can just use the default range ("lastmonth" is everything
> > From the 1st of the previous month to the 1st of the current month).
> > 
> > I think this fits nicely with your code.
> 
> It fit nicely indeed. I have just integrated your date parser into my
> code and sent it as a series of 4 patches based on current cworth
> master. (commits 2565fc6 and 96e11c3 will not compile on their own)

Very cool. Oh, if you've got commits that don't compile on their own,
you should squash them together (or fix it in some other way). Makes
bisecting easier in the future.

Also, cworth is on vacation this week, so we won't be seeing any
merging to master...

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20100126/228d26b3/attachment.pgp>


Re: [notmuch] [PATCH] Make the date parser nicer

2010-01-26 Thread Keith Packard
On Tue, 26 Jan 2010 12:50:41 +0100, Sebastian Spaeth sebast...@sspaeth.de 
wrote:
 On Mon, 25 Jan 2010 22:36:35 -0800, Keith Packard kei...@keithp.com wrote:
  Here's some code which further improves date parsing by allowing lots of
  date formats, including things like today, thisweek, ISO and US date
  formats and month names. You can separate two dates with .. to make a
  range, or you can just use the default range (lastmonth is everything
  From the 1st of the previous month to the 1st of the current month).
  
  I think this fits nicely with your code.
 
 It fit nicely indeed. I have just integrated your date parser into my
 code and sent it as a series of 4 patches based on current cworth
 master. (commits 2565fc6 and 96e11c3 will not compile on their own)

Very cool. Oh, if you've got commits that don't compile on their own,
you should squash them together (or fix it in some other way). Makes
bisecting easier in the future.

Also, cworth is on vacation this week, so we won't be seeing any
merging to master...

-- 
keith.pack...@intel.com


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


[notmuch] [PATCH] Make the date parser nicer

2010-01-25 Thread Keith Packard
On Fri, 22 Jan 2010 16:26:11 +0100, Sebastian Spaeth  
wrote:
> Currently we have to enter mail dates as timestamps. This approach
> does 2 things: it requires the prefix 'date:' and it allows timestamps
> to be specified as , MM or MMDD. So a notmuch show
> date:2005..20060512 will find all mails from 2005-01-01 until
> 2006-05-12. The code is probably not in a proper location yet and
> needs to be shoved around by someone more knowledgable than me. My C++
> skills are somewhat,... lacking...

Here's some code which further improves date parsing by allowing lots of
date formats, including things like "today", "thisweek", ISO and US date
formats and month names. You can separate two dates with .. to make a
range, or you can just use the default range ("lastmonth" is everything


[PATCH] Add date.c

2010-01-25 Thread Keith Packard
---
 lib/date.c |  455 
 1 files changed, 455 insertions(+), 0 deletions(-)
 create mode 100644 lib/date.c

diff --git a/lib/date.c b/lib/date.c
new file mode 100644
index 000..611ae15
--- /dev/null
+++ b/lib/date.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright ? 2009 Keith Packard 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "notmuch.h"
+#include 
+#include 
+#include 
+#include 
+
+#define DAY(24 * 60 * 60)
+
+static void
+today(struct tm *result, time_t after) {
+time_t t;
+
+if (after)
+   t = after;
+else
+   time();
+localtime_r(, result);
+result->tm_sec = result->tm_min = result->tm_hour = 0;
+}
+
+static int parse_today(const char *text, time_t *first, time_t *last, time_t 
after) {
+if (strcasecmp(text, "today") == 0) {
+   struct tm n;
+   today(, 0);
+   *first = mktime();
+   *last = *first + DAY;
+   return 0;
+}
+return 1;
+}
+
+static int parse_yesterday(const char *text, time_t *first, time_t *last, 
time_t after) {
+if (strcasecmp(text, "yesterday") == 0) {
+   struct tm n;
+   today(, 0);
+   *last = mktime();
+   *first = *last - DAY;
+   return 0;
+}
+return 1;
+}
+
+static int parse_thisweek(const char *text, time_t *first, time_t *last, 
time_t after) {
+if (strcasecmp(text, "thisweek") == 0) {
+   struct tm n;
+   today(, 0);
+   *first = mktime() - (n.tm_wday * DAY);
+   *last = *first + DAY * 7;
+   return 0;
+}
+return 1;
+}
+
+static int parse_lastweek(const char *text, time_t *first, time_t *last, 
time_t after) {
+if (strcasecmp(text, "lastweek") == 0) {
+   struct tm n;
+   today(, 0);
+   *last = mktime() - (n.tm_wday * DAY);
+   *first = *last - DAY * 7;
+   return 0;
+}
+return 1;
+}
+
+static int parse_thismonth(const char *text, time_t *first, time_t *last, 
time_t after) {
+if (strcasecmp(text, "thismonth") == 0) {
+   struct tm n;
+   today(, 0);
+   n.tm_mday = 1;
+   *first = mktime();
+   if (n.tm_mon++ == 12) {
+   n.tm_mon = 0;
+   n.tm_year++;
+   }
+   *last = mktime();
+   return 0;
+}
+return 1;
+}
+
+static int parse_lastmonth(const char *text, time_t *first, time_t *last, 
time_t after) {
+if (strcasecmp(text, "lastmonth") == 0) {
+   struct tm n;
+   today(, 0);
+   n.tm_mday = 1;
+   if (n.tm_mon == 0) {
+   n.tm_year--;
+   n.tm_mon = 11;
+   } else
+   n.tm_mon--;
+   *first = mktime();
+   if (n.tm_mon++ == 12) {
+   n.tm_mon = 0;
+   n.tm_year++;
+   }
+   *last = mktime();
+   return 0;
+}
+return 1;
+}
+
+static const char *months[12][2] = {
+{ "January", "Jan" },
+{ "February", "Feb" },
+{ "March", "Mar" },
+{ "April", "Apr" },
+{ "May", "May" },
+{ "June", "Jun" },
+{ "July", "Jul" },
+{ "August", "Aug" },
+{ "September", "Sep" },
+{ "October", "Oct" },
+{ "November", "Nov" },
+{ "December", "Dec" },
+};
+
+static int year(const char *text, int *y) {
+char *end;
+*y = strtol(text, , 10);
+if (end == text)
+   return 1;
+if (*end != '\0')
+   return 1;
+if (*y < 1970 || *y > 2038)
+   return 1;
+*y -= 1900;
+return 0;
+}
+
+static int month(const char *text, int *m) {
+char *end;
+int i;
+for (i = 0; i < 12; i++) {
+   if (strcasecmp(text, months[i][0]) == 0 ||
+   strcasecmp(text, months[i][1]) == 0)
+   {
+   *m = i;
+   return 0;
+   }
+}
+*m = strtol(text, , 10);
+if (end == text)
+   return 1;
+if (*end != '\0')
+   return 1;
+if (*m < 1 || *m > 12)
+   return 1;
+*m -= 1;
+return 0;
+}
+
+static int day(const char *text, int *d) {
+char *end;
+*d = strtol(text, , 10);
+if (end 

[notmuch] [PATCH 3/3] Allow folders with no messages to be elided from list.

2009-12-26 Thread Keith Packard
This makes it easier to see folders with messages.
Eliding empty folders is togged with the 'e' binding.

Signed-off-by: Keith Packard 
---
 lib/Makefile.local |1 +
 lib/notmuch.h  |   11 +++
 lib/query.cc   |   41 +
 notmuch-new.c  |1 +
 notmuch.el |   29 -
 5 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/lib/Makefile.local b/lib/Makefile.local
index a7562c9..e42f533 100644
--- a/lib/Makefile.local
+++ b/lib/Makefile.local
@@ -2,6 +2,7 @@ dir=lib
 extra_cflags += -I$(dir)

 libnotmuch_c_srcs =\
+   $(dir)/date.c   \
$(dir)/libsha1.c\
$(dir)/message-file.c   \
$(dir)/messages.c   \
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 60834fb..f24da18 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -94,6 +94,7 @@ typedef enum _notmuch_status {
 NOTMUCH_STATUS_NULL_POINTER,
 NOTMUCH_STATUS_TAG_TOO_LONG,
 NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW,
+NOTMUCH_STATUS_INVALID_DATE,

 NOTMUCH_STATUS_LAST_STATUS
 } notmuch_status_t;
@@ -929,6 +930,16 @@ notmuch_tags_advance (notmuch_tags_t *tags);
 void
 notmuch_tags_destroy (notmuch_tags_t *tags);

+/* Convert a string into a time range
+ *
+ * This parses the provided string, providing two time values
+ * representing the begining and end of the period. It
+ * returns NOTMUCH_STATUS_INVALID_DATE if the string could not be
+ * parsed, otherwise it return NOTMUCH_STATUS_SUCCESS
+ */
+notmuch_status_t
+notmuch_date(const char *text, time_t *first, time_t *last);
+
 NOTMUCH_END_DECLS

 #endif
diff --git a/lib/query.cc b/lib/query.cc
index 9106b92..f511146 100644
--- a/lib/query.cc
+++ b/lib/query.cc
@@ -47,6 +47,47 @@ struct _notmuch_threads {
 const char *thread_id;
 };

+static char *
+notmuch_query_extract_word(notmuch_query_t *query, char *leader)
+{
+   char*token = strstr(query->query_string, leader);
+   int len = strlen(leader);
+   char*space;
+   char*word;
+   char*query_string;
+
+   if (!token)
+   return NULL;
+   space = strchr(token, ' ');
+   if (!space)
+   space = token + strlen(token);
+   word = talloc_strndup(query, token + len, space - token - len);
+   query_string = talloc(query, strlen(query->query_string) - (space - 
token));
+   strncpy(query_string, query->query_string, token - query->query_string);
+   strcat(query_string, space);
+   query->query_string = query_string;
+   return word;
+}
+
+static notmuch_status_t
+notmuch_query_edit(notmuch_query_t *query)
+{
+   char*before, *after;
+   time_t  before_first, before_last, after_first, after_last;
+   
+   /* edit date range */
+   before = notmuch_query_extract_word(query, "before:");
+   if (notmuch_date(before, _first, _last) != 
NOTMUCH_STATUS_SUCCESS)
+   before = NULL;
+   after = notmuch_query_extract_word(query, "after:");
+   if (notmuch_date(after, _first, _last) != 
NOTMUCH_STATUS_SUCCESS)
+   after = NULL;
+
+   if (before && after) {
+   
+   }
+}
+
 notmuch_query_t *
 notmuch_query_create (notmuch_database_t *notmuch,
  const char *query_string)
diff --git a/notmuch-new.c b/notmuch-new.c
index 9d20616..3974b28 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -264,6 +264,7 @@ add_files_recursive (notmuch_database_t *notmuch,
case NOTMUCH_STATUS_TAG_TOO_LONG:
case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
case NOTMUCH_STATUS_LAST_STATUS:
+   case NOTMUCH_STATUS_INVALID_DATE:
INTERNAL_ERROR ("add_message returned unexpected value: 
%d",  status);
goto DONE;
}
diff --git a/notmuch.el b/notmuch.el
index c02adc6..73917e7 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -1379,6 +1379,7 @@ current search results AND that are tagged with the given 
tag."
 (define-key map "x" 'kill-this-buffer)
 (define-key map "q" 'kill-this-buffer)
 (define-key map "m" 'message-mail)
+(define-key map "e" 'notmuch-folder-show-empty-toggle)
 (define-key map ">" 'notmuch-folder-last)
 (define-key map "<" 'notmuch-folder-first)
 (define-key map "=" 'notmuch-folder)
@@ -1455,14 +1456,32 @@ Currently available key bindings:
   (goto-char (point-max))
   (forward-line -1))

+(defun notmuch-folder-count (search)
+  (car (process-lines notmuch-command "count" search)))
+
+(setq notmuch-folder-show-empty t)
+
+(defun notmuch-folder-show-empty-toggle ()
+  "Toggle the listing of empty folders"
+  (interactive)
+  (setq notmuch-folder-show-empty (not notmuch-folder-show-empty))
+  (notmuch-folder))
+
 (defun not

[notmuch] [PATCH 2/3] Look at whitespace to separate folder name from count

2009-12-26 Thread Keith Packard
This allows folder names to contain any non-blank characters

Signed-off-by: Keith Packard 
---
 notmuch.el |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 3dbb64a..c02adc6 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -1469,8 +1469,8 @@ Currently available key bindings:
   (save-excursion
 (beginning-of-line)
 (let ((beg (point)))
-  (forward-word)
-  (filter-buffer-substring beg (point)
+  (re-search-forward "\\([ \t]*[^ \t]+\\)")
+  (filter-buffer-substring (match-beginning 1) (match-end 1)

 (defun notmuch-folder-show-search ( folder)
   "Show a search window for the search related to the specified folder."
-- 
1.6.5.4



[notmuch] [PATCH 1/3] Add 'm' and ' ' bindings to notmuch-folder view

2009-12-26 Thread Keith Packard
This allows the user to compose new mail from the folder view, and
also to use  to show the current folder.

Signed-off-by: Keith Packard 
---
 notmuch.el |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 97914f2..3dbb64a 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -1378,12 +1378,14 @@ current search results AND that are tagged with the 
given tag."
 (define-key map "?" 'notmuch-help)
 (define-key map "x" 'kill-this-buffer)
 (define-key map "q" 'kill-this-buffer)
+(define-key map "m" 'message-mail)
 (define-key map ">" 'notmuch-folder-last)
 (define-key map "<" 'notmuch-folder-first)
 (define-key map "=" 'notmuch-folder)
 (define-key map "s" 'notmuch-search)
 (define-key map [mouse-1] 'notmuch-folder-show-search)
 (define-key map (kbd "RET") 'notmuch-folder-show-search)
+(define-key map " " 'notmuch-folder-show-search)
 (define-key map "p" 'notmuch-folder-previous)
 (define-key map "n" 'notmuch-folder-next)
 map)
-- 
1.6.5.4



[notmuch] [PATCH 3/3] Allow folders with no messages to be elided from list.

2009-12-26 Thread Keith Packard
This makes it easier to see folders with messages.
Eliding empty folders is togged with the 'e' binding.

Signed-off-by: Keith Packard kei...@keithp.com
---
 lib/Makefile.local |1 +
 lib/notmuch.h  |   11 +++
 lib/query.cc   |   41 +
 notmuch-new.c  |1 +
 notmuch.el |   29 -
 5 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/lib/Makefile.local b/lib/Makefile.local
index a7562c9..e42f533 100644
--- a/lib/Makefile.local
+++ b/lib/Makefile.local
@@ -2,6 +2,7 @@ dir=lib
 extra_cflags += -I$(dir)
 
 libnotmuch_c_srcs =\
+   $(dir)/date.c   \
$(dir)/libsha1.c\
$(dir)/message-file.c   \
$(dir)/messages.c   \
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 60834fb..f24da18 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -94,6 +94,7 @@ typedef enum _notmuch_status {
 NOTMUCH_STATUS_NULL_POINTER,
 NOTMUCH_STATUS_TAG_TOO_LONG,
 NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW,
+NOTMUCH_STATUS_INVALID_DATE,
 
 NOTMUCH_STATUS_LAST_STATUS
 } notmuch_status_t;
@@ -929,6 +930,16 @@ notmuch_tags_advance (notmuch_tags_t *tags);
 void
 notmuch_tags_destroy (notmuch_tags_t *tags);
 
+/* Convert a string into a time range
+ *
+ * This parses the provided string, providing two time values
+ * representing the begining and end of the period. It
+ * returns NOTMUCH_STATUS_INVALID_DATE if the string could not be
+ * parsed, otherwise it return NOTMUCH_STATUS_SUCCESS
+ */
+notmuch_status_t
+notmuch_date(const char *text, time_t *first, time_t *last);
+
 NOTMUCH_END_DECLS
 
 #endif
diff --git a/lib/query.cc b/lib/query.cc
index 9106b92..f511146 100644
--- a/lib/query.cc
+++ b/lib/query.cc
@@ -47,6 +47,47 @@ struct _notmuch_threads {
 const char *thread_id;
 };
 
+static char *
+notmuch_query_extract_word(notmuch_query_t *query, char *leader)
+{
+   char*token = strstr(query-query_string, leader);
+   int len = strlen(leader);
+   char*space;
+   char*word;
+   char*query_string;
+
+   if (!token)
+   return NULL;
+   space = strchr(token, ' ');
+   if (!space)
+   space = token + strlen(token);
+   word = talloc_strndup(query, token + len, space - token - len);
+   query_string = talloc(query, strlen(query-query_string) - (space - 
token));
+   strncpy(query_string, query-query_string, token - query-query_string);
+   strcat(query_string, space);
+   query-query_string = query_string;
+   return word;
+}
+
+static notmuch_status_t
+notmuch_query_edit(notmuch_query_t *query)
+{
+   char*before, *after;
+   time_t  before_first, before_last, after_first, after_last;
+   
+   /* edit date range */
+   before = notmuch_query_extract_word(query, before:);
+   if (notmuch_date(before, before_first, before_last) != 
NOTMUCH_STATUS_SUCCESS)
+   before = NULL;
+   after = notmuch_query_extract_word(query, after:);
+   if (notmuch_date(after, after_first, after_last) != 
NOTMUCH_STATUS_SUCCESS)
+   after = NULL;
+
+   if (before  after) {
+   
+   }
+}
+
 notmuch_query_t *
 notmuch_query_create (notmuch_database_t *notmuch,
  const char *query_string)
diff --git a/notmuch-new.c b/notmuch-new.c
index 9d20616..3974b28 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -264,6 +264,7 @@ add_files_recursive (notmuch_database_t *notmuch,
case NOTMUCH_STATUS_TAG_TOO_LONG:
case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
case NOTMUCH_STATUS_LAST_STATUS:
+   case NOTMUCH_STATUS_INVALID_DATE:
INTERNAL_ERROR (add_message returned unexpected value: 
%d,  status);
goto DONE;
}
diff --git a/notmuch.el b/notmuch.el
index c02adc6..73917e7 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -1379,6 +1379,7 @@ current search results AND that are tagged with the given 
tag.
 (define-key map x 'kill-this-buffer)
 (define-key map q 'kill-this-buffer)
 (define-key map m 'message-mail)
+(define-key map e 'notmuch-folder-show-empty-toggle)
 (define-key map  'notmuch-folder-last)
 (define-key map  'notmuch-folder-first)
 (define-key map = 'notmuch-folder)
@@ -1455,14 +1456,32 @@ Currently available key bindings:
   (goto-char (point-max))
   (forward-line -1))
 
+(defun notmuch-folder-count (search)
+  (car (process-lines notmuch-command count search)))
+
+(setq notmuch-folder-show-empty t)
+
+(defun notmuch-folder-show-empty-toggle ()
+  Toggle the listing of empty folders
+  (interactive)
+  (setq notmuch-folder-show-empty (not notmuch-folder-show-empty))
+  (notmuch-folder))
+
 (defun notmuch-folder-add (folders)
   (if folders
-  (let ((name (car (car folders)))
+  (let* ((name (car (car folders)))
(inhibit-read-only t

[notmuch] keeping a copy of sent mail locally

2009-12-19 Thread Keith Packard
On Sun, 20 Dec 2009 15:29:15 +1100, Alex Ghitza  wrote:

> Good.  So we can put this in notmuch.el and Keith will get everybody's
> sent mail. :)

That seems sub-optimal, at least for me...

> It looks like we need a way to get the primary email address from the
> config file.

We actually want to let the user *select* an email address from the
config file, and then automagically set the bcc: flag as
appropriate. Without that, I'd end up bcc'ing all of my mail through my
home address, which would end up sending work email unencrypted to my
house. Sub-optimal

> (setq user-full-name "Alex Ghitza")
> (setq user-mail-address "aghitza at gmail.com")

You can set everything in the message-mail argument list:

(message-mail nil nil '(("bcc" "keith.packard at intel.com") ("from" "Keith 
Packard ")))

Alternatively, we can hack up message mode so that when the From address
is set (using completion from the notmuch config), the Bcc line is copied.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20091219/4241bcf9/attachment.pgp>


[notmuch] keeping a copy of sent mail locally

2009-12-19 Thread Keith Packard
On Sat, 19 Dec 2009 18:37:12 -0800, Carl Worth  wrote:

> So we need to figure out how to configure (or hook) that
> to insert the Bcc, and then we can fix notmuch.el to do this without any
> user configuration.

Just call:

(message-mail nil nil '(("bcc" "keithp at keithp.com")))

instead of (message-mail)

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



Re: [notmuch] keeping a copy of sent mail locally

2009-12-19 Thread Keith Packard
On Sun, 20 Dec 2009 15:29:15 +1100, Alex Ghitza aghi...@gmail.com wrote:

 Good.  So we can put this in notmuch.el and Keith will get everybody's
 sent mail. :)

That seems sub-optimal, at least for me...

 It looks like we need a way to get the primary email address from the
 config file.

We actually want to let the user *select* an email address from the
config file, and then automagically set the bcc: flag as
appropriate. Without that, I'd end up bcc'ing all of my mail through my
home address, which would end up sending work email unencrypted to my
house. Sub-optimal

 (setq user-full-name Alex Ghitza)
 (setq user-mail-address aghi...@gmail.com)

You can set everything in the message-mail argument list:

(message-mail nil nil '((bcc keith.pack...@intel.com) (from Keith 
Packard keith.pack...@intel.com)))

Alternatively, we can hack up message mode so that when the From address
is set (using completion from the notmuch config), the Bcc line is copied.

-- 
keith.pack...@intel.com


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


[notmuch] [PATCH] More portable and easier to read regex in notmuch-search-operate-all

2009-11-28 Thread Keith Packard
On Sat, 28 Nov 2009 20:51:13 +0100, Jed Brown  wrote:
> The former one worked in 23.1.50.1 but not in 23.1.1.
> 
> Signed-off-by: Jed Brown 

Tested-by: Keith Packard 

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20091128/e5bdc970/attachment.pgp>


[notmuch] _notmuch_message_create_for_message_id makes extra call to notmuch_database_find_message

2009-11-27 Thread Keith Packard
On Fri, 27 Nov 2009 04:46:54 -0800, Carl Worth  wrote:

> Did the "if" statement immediately afterwards just look like error
> checking? It's not:

Yes, it did (I think my brain may have auto-inserted a '!' there).

Ok, having read the code a bit more carefully, this does look correct.

I have to say that _notmuch_message_create is a bit of a tricky name; as
it doesn't create a message so much as load a message from the database.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



Re: [notmuch] _notmuch_message_create_for_message_id makes extra call to notmuch_database_find_message

2009-11-27 Thread Keith Packard
On Fri, 27 Nov 2009 04:46:54 -0800, Carl Worth cwo...@cworth.org wrote:

 Did the if statement immediately afterwards just look like error
 checking? It's not:

Yes, it did (I think my brain may have auto-inserted a '!' there).

Ok, having read the code a bit more carefully, this does look correct.

I have to say that _notmuch_message_create is a bit of a tricky name; as
it doesn't create a message so much as load a message from the database.

-- 
keith.pack...@intel.com


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


[notmuch] OpenPGP support

2009-11-26 Thread Keith Packard
On Thu, 26 Nov 2009 10:41:36 -0800, Carl Worth  wrote:

> I'm not sure how to make sure that I also get that when doing a reply
> within notmuch. Keith, I think you worked this out, right? What did you
> do?

; sign messages by default
(defun my-notmuch-message-mode-hook()
  (if (buffer-modified-p)
  (mml-secure-message-sign)))

(add-hook 'message-mode-hook 'my-notmuch-message-mode-hook)
(add-hook 'message-setup-hook 'my-notmuch-message-mode-hook)

The message-setup-hook is called for new messages, the message-mode-hook
is called for both; the hack is to check for the reply case by looking
to see if the buffer has been modified as the message mode hook gets
called on an empty buffer in the new message case.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] notmuch 'index' mode.

2009-11-24 Thread Keith Packard
On Tue, 24 Nov 2009 13:14:07 +0100, Jan Janak  wrote:

> I like this. I think this is much cleaner than the "virtual tag"
> approach.

A disadvantage I see is that you would not see this 'virtual tags' in
the list of tags on each message. And, we'd have to put the virtual tags
in the .config file or the command line would become a lot less
useful. Speaking of which, we should put the folders in the .config file
in any case, and provide command line syntax to use them.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] notmuch 'index' mode.

2009-11-23 Thread Keith Packard
On Mon, 23 Nov 2009 19:16:54 -0800, Carl Worth  wrote:

> So what next for the user? We've got lots of empty space in the folder
> view, so I think what I'd like is to provide some suggestions on search
> strings to try, and then to make it obvious how to associate a name with
> a search string. And at that point, I'd like that name to be added to
> the folder view.

Right, associate a name for the search from the *search* view instead of
the folder view. Then it's just a matter of using that command and
typing a name. At that point, you get the new folder (or named search)
added to the main window. That's a great plan.

> Then tags become something that are just for manual manipulation. What
> do you think?

So you wouldn't generally end up using tags? And each time you wanted to
view a folder you'd really get a new search result? I can see some
benefits if you're using time-range based searches (show me all the mail


[notmuch] _notmuch_message_create_for_message_id makes extra call to notmuch_database_find_message

2009-11-23 Thread Keith Packard

Looking at _notmuch_message_create_for_message_id, the first thing it
does is call notmuch_database_find_message, but the returned 'message'
is never used. I haven't tried, but I suspect this call could just be
removed.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] [PATCH] Make search filters handle disjunctive queries.

2009-11-23 Thread Keith Packard
On Mon, 23 Nov 2009 19:07:23 +0100, Jed Brown  wrote:

> notmuch-search-filter accepts now accepts an arbitrary query and will
> group if necessary so that we get
> 
>   tag:inbox AND (gravy OR biscuits)
> 
> notmuch-search-filter-tag now handles multiple terms.  All terms in the
> query except AND and OR are interpreted as tags.

Remember to split patches which do more than one thing into separate
commits.

> +  (let ((grouped-query (if (string-match-p notmuch-search-disjunctive-regexp 
> query) (concat "( " query " )") query)))
> +(notmuch-search (concat notmuch-search-query-string " and " 
> grouped-query) notmuch-search-oldest-first)))

Is there some reason not to just always add the parens?

> +  (let ((tagged-query (replace-regexp-in-string 
> notmuch-search-valid-term-regexp
> + (lambda (match) ; Prepend 
> `tag:' to all except boolean operators
> +   (if (string-match-p 
> notmuch-search-boolean-operator-regexp match)
> +   match (concat "tag:" 
> match)))
> + query)))

This seems useful; how does it deal with the tag completion stuff?

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] [PATCH] ANSI escapes in "new" only when output is a tty

2009-11-22 Thread Keith Packard
On Mon, 23 Nov 2009 06:12:09 +0100, Carl Worth  wrote:

> So that's totally broken and we should come up with a way to fix it.

Tracking directory mtime instead of just looking at the read-only bit
would let us skip directories that haven't seen any change in content.

Tracking directory contents would let us easily detect name changes
(add/remove/rename).

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags

2009-11-22 Thread Keith Packard
On Mon, 23 Nov 2009 07:31:04 +0100, Carl Worth  wrote:

> OK. You win. That looks pretty good to me.

So we need to do the 'mark all that have been seen read' change, then we
can do the rest of this switch. Not sure how to make that work, as we
need to know what has been displayed, and you can display bits of the
window in lots of different ways (even using the mouse!)

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] notmuch 'index' mode.

2009-11-22 Thread Keith Packard
On Mon, 23 Nov 2009 07:06:06 +0100, Carl Worth  wrote:
> On Fri, 20 Nov 2009 23:35:29 -0800, Keith Packard  
> wrote:
> > I posted a patch adding an 'index' mode to notmuch and though I'd
> > explain my idea. Most mail systems provide a 'folder view' mode which
> > displays the set of folders and a count of messages in each folder. I
> > used this myself as the first sort of which messages I want to read.
> 
> I've just pushed this set of patches out now.
> 
> I like it quite a bit. Here are some thoughts:
> 
>   * The mode documentation really needs to walk the user through how to
> setup a custom set of folders.

You can use the standard emacs customization interface, although it's
not exactly well documented there. Additional docs are clearly
indicated.

>   * It's not opening my "to-me" folder for some reason. (I thought it
> was the '-' at first, but "xorg-board" is working fine). I can debug
> this later.

It shouldn't work on xorg-board either -- it just skips forward one
'word' and assumes it's gotten the folder name. Lame programming, I
know. Should be easy to fix.

>   * The presentation is impressively spartan[*]. :-)

What more do you need? Pretty fonts? Icons? A pony?

> If we spruce this up a bit, I think we'll want to make this the default
> view of "M-x notmuch".

Let's figure out what we want it to look like then. I suggest that we
use some font tricks (bold/regular) to highlight folders with
un-archived mail. I'd also like to be able to create a hierarchy.

> Oh, and instead of just documenting how to set a variable in .emacs we
> should just provide commands to add/remove folders.

That seems doable; it really only takes two text fields after all.

> I think the number of threads matching the search is the only
> interesting number actually. Otherwise, you just end up printing a bunch
> of big numbers that the user doesn't need for anything.

Threads or messages? Threads are more expensive to compute, and when the
number is zero, it means the same thing. But, it is surprising to see a
huge number in the folder view and then get only a handful of threads in
the search view. Perhaps if the count is small enough we can go through
and actually figure out how many threads are involved.

> So maybe the user configures a search template to use for each automatic
> tag or so?

Ack! I suggest that the simpler approach of just duplicating the search
field will work fine in practice. Otherwise, you're talking miles of UI
goo, and constantly confused users. Really, you can use emacs to edit
these things if you get too many.

> It's only when I get my search results down below a particular
> threshold that I decide I want to read everything linearly.

I have started doing this sometimes too. But, I still skim things like
the mesa list and only read a few by clicking through and 'x'ing back.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20091122/9db66e2b/attachment-0001.pgp>


[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags

2009-11-22 Thread Keith Packard
On Mon, 23 Nov 2009 04:03:12 +0100, Carl Worth  wrote:

> I agree that "normal" should be easier too. So I just need to win you
> over to my notion of "normal", (and teach you of the ways of the magic
> space bar).

As I mentioned, I rarely read mail in a linear fashion; I don't want it
to show me another message, I want to see the index again. I'm torn over
whether I just want the index to always be visible; having the full
screen available to view a single thread is awfully nice. It seems like
a 'I'm done, go back to the index' is just what is needed here.

> [*] We should perhaps fix 'a' to remove the "unread" tag from any
> messages that _are_ wholly visible in the current window. It's really
> only when an entire thread fits this one, and I *did* read it, that I
> end up reaching for the 'A' binding.

yes, that does make a lot of sense, and do precisely the same for the
'x' key, leaving 'q' the way to get out of a message without changing
it at all.

> If we did that, then we could make 'a' do archive-go-to-next-message
> and 'A' do archive-return-to-search-view. What would you think about
> that?

I'd take 'x' for 'return to search view; otherwise you're going to wear
out my pinky reaching for the shift key. That leaves us with three
commands:

'a': advance to next message, archiving current thread, marking read
messages. ('A' forces all messages in thread to be marked as read)

'x': exit to search view, archiving current thread, marking read
messages. ('X' forces all messages in thread to be marked as read)

'q': quit back to search view, leaving thread tags unmodified.

There's a slightly weird asymmetry here -- there's no way to advance to
the next thread and not mark messages.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags

2009-11-22 Thread Keith Packard
On Mon, 23 Nov 2009 00:19:29 +0100, Carl Worth  wrote:

> I'm starting to come around to this patch, Keith. :-)

I'll keep posting it then :-)

> I think one thing we're going to really need is a better help message
> for presenting the keybindings. The function names are all really
> confusing, (the "notmuch-show" prefix doesn't help). So what I'd really
> like is something that displays the keybinding and the first line of the
> documentation of a function, rather than the function name itself.

That's a fine plan. It 'shouldn't' be too hard to implement either.

Btw, I'm thinking that it might be useful to create some 'global'
notmuch keybindings and then create per-view bindings that also expose
the global bindings. That way, things like 'm' to create a new mail
would work consistently in each view. Note that this idea is
inconsistent with the following though...

> Except that the patch also reverses the current behavior of "a" and
> "A". That should be a separate patch anyway, but I'm also not sure that
> I like it. I like that the command that takes the extra effort of
> pressing shift is the command that does *more*, (removing both "unread"
> and "inbox"), rather than the command that does *less*.

I was trying to make the 'normal' action easier; for me, if I'm looking
at a message, then the normal action is to mark it read and archived,
but when I'm looking only at the subject line in the search window, the
normal action is just to mark it archived (having not actually read the
message).

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] [PATCH 1/2] lib/message: Add function to get maildir flags.

2009-11-21 Thread Keith Packard
On Sun, 22 Nov 2009 01:11:00 +0100, Stefan Schmidt  wrote:

> +const char *
> +notmuch_message_get_flags (notmuch_message_t *message)

This function should interpret the flags that it finds and return a
suitable set of notmuch tags. I'd suggest that 'unread' messages get
both 'unread' and 'inbox' tags, as Maildir doesn't distinguish between
'don't show this to be by default again please' and 'I've read this
message'. It seems best to hide the maildir-specific details inside the
library instead of exposing them.

Also, we have only the 'unread' tag; we don't have a 'read' tag, which
would simply be the inverse of 'unread'.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] Asynchronous tagging

2009-11-21 Thread Keith Packard
On Sat, 21 Nov 2009 23:46:44 +0100, Carl Worth  wrote:

> So some investigation is needed to see how important that optimization
> is, and if it's important to see whether there's another way to keep the
> performance while being able to support renames. (Or alternately,
> allowing the user to configure an option saying, "I need to support
> renames even if that means that notmuch new is a bit slower.").

I'd suggest that the best way to make this more efficient would be to
capture directory contents (along with the directory mtime) and use that
to detect changes. If we assume that mail messages are never changed, we
could use that to avoid stat'ing files in directories too.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] [PATCH] Permit opening the notmuch database in read-only mode.

2009-11-21 Thread Keith Packard
On Sat, 21 Nov 2009 19:54:25 +, Chris Wilson  
wrote:

> +typedef enum {
> +NOTMUCH_DATABASE_MODE_READONLY = 0,
> +NOTMUCH_DATABASE_MODE_WRITABLE
> +} notmuch_database_mode_t;

Wondering if MODE_READWRITE would be more descriptive?

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] [PATCH] Add notmuch-folder mode to provide an overview of search matches

2009-11-21 Thread Keith Packard
Folder mode takes a (user-configurable) list of search patterns and
produces a list of those patterns and the count of messages that they
match. When an entry in this list is selected, a search window with
the defined search is opened.  The set of folders is defined as a
list, each element contains the name of the folder and the query string
to count.

Signed-off-by: Keith Packard 
---
 notmuch.el |   81 
 1 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 4f369de..7cab3c1 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -1046,4 +1046,85 @@ current search results AND that are tagged with the 
given tag."

 (setq mail-user-agent 'message-user-agent)

+(defvar notmuch-folder-mode-map
+  (let ((map (make-sparse-keymap)))
+(define-key map "n" 'next-line)
+(define-key map "p" 'previous-line)
+(define-key map "x" 'kill-this-buffer)
+(define-key map "q" 'kill-this-buffer)
+(define-key map "s" 'notmuch-search)
+(define-key map (kbd "RET") 'notmuch-folder-show-search)
+(define-key map "<" 'beginning-of-buffer)
+(define-key map "=" 'notmuch-folder)
+(define-key map "?" 'describe-mode)
+(define-key map [mouse-1] 'notmuch-folder-show-search)
+map)
+  "Keymap for \"notmuch folder\" buffers.")
+
+(fset 'notmuch-folder-mode-map notmuch-folder-mode-map)
+
+(defcustom notmuch-folders (quote (("inbox" . "tag:inbox") ("unread" . 
"tag:unread")))
+  "List of searches for the notmuch folder view"
+  :type '(alist :key-type (string) :value-type (string))
+  :group 'notmuch)
+  
+(defun notmuch-folder-mode ()
+  "Major mode for showing notmuch 'folders'.
+
+This buffer contains a list of messages counts returned by a
+customizable set of searches of your email archives. Each line
+in the buffer shows the search terms and the resulting message count.
+
+Pressing RET on any line opens a search window containing the
+results for the search terms in that line.
+
+\\{notmuch-folder-mode-map}"
+  (interactive)
+  (kill-all-local-variables)
+  (use-local-map 'notmuch-folder-mode-map)
+  (setq truncate-lines t)
+  (hl-line-mode 1)
+  (setq major-mode 'notmuch-folder-mode
+   mode-name "notmuch-folder")
+  (setq buffer-read-only t))
+
+(defun notmuch-folder-add (folders)
+  (if folders
+  (let ((name (car (car folders)))
+   (inhibit-read-only t)
+   (search (cdr (car folders
+   (insert name)
+   (indent-to 16 1)
+   (call-process notmuch-command nil t nil "count" search)
+   (notmuch-folder-add (cdr folders)
+
+(defun notmuch-folder-find-name ()
+  (save-excursion
+(beginning-of-line)
+(let ((beg (point)))
+  (forward-word)
+  (filter-buffer-substring beg (point)
+
+(defun notmuch-folder-show-search ( folder)
+  "Show a search window for the search related to the specified folder."
+  (interactive)
+  (if (null folder)
+  (setq folder (notmuch-folder-find-name)))
+  (let ((search (assoc folder notmuch-folders)))
+(if search
+   (notmuch-search (cdr search) t
+
+(defun notmuch-folder ()
+  "Show the notmuch folder view and update the displayed counts."
+  (interactive)
+  (let ((buffer (get-buffer-create "*notmuch-folders*")))
+(switch-to-buffer buffer)
+(let ((inhibit-read-only t)
+ (n (line-number-at-pos)))
+  (erase-buffer)
+  (notmuch-folder-mode)
+  (notmuch-folder-add notmuch-folders)
+  (goto-char (point-min))
+  (goto-line n
+
 (provide 'notmuch)
-- 
1.6.5.2



[notmuch] notmuch 'index' mode.

2009-11-20 Thread Keith Packard

I posted a patch adding an 'index' mode to notmuch and though I'd
explain my idea. Most mail systems provide a 'folder view' mode which
displays the set of folders and a count of messages in each folder. I
used this myself as the first sort of which messages I want to read.

Notmuch doesn't have folders, but it does have tags, so I thought I'd
take advantage of that, along with the quick searching ability in Xapian
to construct something much like the folder view.

In 'index' mode, notmuch shows a list of 'folders', each of which is
defined by a Xapian query. The new 'notmuch count' command is used to
figure out how many messages matching the query are in the
database. When you hit 'enter' (or click the mouse) on any line, it
executes the search for real using the notmuch-search command.

Here's the set of indexes I'm using right now (oddly, it looks a lot
like the set of tags I auto-configure in my notmuch-poll script).

(setq notmuch-indexes '(("inbox" . "tag:inbox")
("me" . "tag:inbox AND tag:me")
("announce" . "tag:inbox AND tag:announce")
("bugs" . "tag:inbox AND tag:bugs")
("cairo" . "tag:inbox AND tag:cairo")
("debian" . "tag:inbox AND tag:debian");
("hackers" . "tag:inbox AND tag:hackers")
("intel" . "tag:inbox AND tag:intel")
("mesa" . "tag:inbox AND tag:mesa")
("notmuch" . "tag:inbox AND tag:notmuch")
("oes" . "tag:inbox AND tag:oes")
("rockets" . "tag:inbox AND tag:rockets")
("x" . "tag:inbox AND tag:x")
("xorg-board" . "tag:inbox AND tag:xorg-board")
("xpatches" . "tag:inbox AND tag:x AND tag:patch")))

And here's what I see in the *notmuch-index* buffer:

inbox   3
me  3
announce0
bugs0
cairo   0
debian  0
hackers 0
intel   0
mesa0
notmuch 0
oes 0
rockets 0
x   0
xorg-board  0
xpatches0

This is all pretty simple, and it does much of what I want. However, one
could always get more :-)

One missing piece here is that the searches don't have a
total/unread count. Because the 'notmuch count' command is so fast
(notmuch count the returns 532891 on my machine, and takes 0.240
seconds), we really could count the number of messages matching a single
tag and then *also* count the number of messages matching that tag and
the inbox tag.

Another missing piece is that these should be shared with the
notmuch-poll script, probably via the .notmuch-config file. I do like
that I can have some entries here that aren't in my notmuch-poll script.

It might be nice to make this hierarchical as I used to do with
evolution's vfolder stuff -- an 'intel' folder with an 'intel/unread'
sub-folder. That would be done with simple conjunctions of tags, but
providing some structure on the screen might be nice.

I'm also wondering if we should elide, or at least change the appearance,
of lines which match zero messages.

I'd also like to be able to get the system to display my mail in three
panes -- one with the index, one with the current search and the last
with the current thread. Getting those laid out on the screen correctly
and letting you get them back to that layout easily would make notmuch
look a lot more like other email clients, a form I've found fairly
functional as I do not generally read mail in a linear fashion.

-- 
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] [PATCH 3/3] Add notmuch-index mode to display message counts

2009-11-20 Thread Keith Packard
Index mode takes a (user-configurable) list of search patterns and
produces a list of those patterns and the count of messages that they
match. When an entry in this list is selected, a search window with
the defined search is opened.  The set of indexes is defined as a
list, each element contains the name of the index and the query string
to count.

This provides a view similar to a folder list in a more traditional
mail client.

Signed-off-by: Keith Packard 
---
 notmuch.el |   81 
 1 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 4f369de..454320e 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -1046,4 +1046,85 @@ current search results AND that are tagged with the 
given tag."

 (setq mail-user-agent 'message-user-agent)

+(defvar notmuch-index-mode-map
+  (let ((map (make-sparse-keymap)))
+(define-key map "n" 'next-line)
+(define-key map "p" 'previous-line)
+(define-key map "x" 'kill-this-buffer)
+(define-key map "q" 'kill-this-buffer)
+(define-key map "s" 'notmuch-search)
+(define-key map (kbd "RET") 'notmuch-index-show-search)
+(define-key map "<" 'beginning-of-buffer)
+(define-key map "=" 'notmuch-index)
+(define-key map "?" 'describe-mode)
+(define-key map [mouse-1] 'notmuch-index-show-search)
+map)
+  "Keymap for \"notmuch index\" buffers.")
+
+(fset 'notmuch-index-mode-map notmuch-index-mode-map)
+
+(defcustom notmuch-indexes (quote (("inbox" . "tag:inbox") ("unread" . 
"tag:unread")))
+  "List of searches for the notmuch index view"
+  :type '(alist :key-type (string) :value-type (string))
+  :group 'notmuch)
+  
+(defun notmuch-index-mode ()
+  "Major mode for showing index of notmuch tags.
+
+This buffer contains a list of messages counts returned by a
+customizable set of searches of your email archives. Each line
+in the buffer shows the search terms and the resulting message count.
+
+Pressing RET on any line opens a search window containing the search
+results for the search terms in that line.
+
+\\{notmuch-index-mode-map}"
+  (interactive)
+  (kill-all-local-variables)
+  (use-local-map 'notmuch-index-mode-map)
+  (setq truncate-lines t)
+  (hl-line-mode 1)
+  (setq major-mode 'notmuch-index-mode
+   mode-name "notmuch-index")
+  (setq buffer-read-only t))
+
+(defun notmuch-index-add (indexes)
+  (if indexes
+  (let ((name (car (car indexes)))
+   (inhibit-read-only t)
+   (search (cdr (car indexes
+   (insert name)
+   (indent-to 16 1)
+   (call-process notmuch-command nil t nil "count" search)
+   (notmuch-index-add (cdr indexes)
+
+(defun notmuch-index-find-name ()
+  (save-excursion
+(beginning-of-line)
+(let ((beg (point)))
+  (forward-word)
+  (filter-buffer-substring beg (point)
+
+(defun notmuch-index-show-search ( index)
+  "Show a search window for the search related to the specified index."
+  (interactive)
+  (if (null index)
+  (setq index (notmuch-index-find-name)))
+  (let ((search (assoc index notmuch-indexes)))
+(if search
+   (notmuch-search (cdr search) t
+
+(defun notmuch-index ()
+  "Show the message index and update the displayed counts."
+  (interactive)
+  (let ((buffer (get-buffer-create "*notmuch-index*")))
+(switch-to-buffer buffer)
+(let ((inhibit-read-only t)
+ (n (line-number-at-pos)))
+  (erase-buffer)
+  (notmuch-index-mode)
+  (notmuch-index-add notmuch-indexes)
+  (goto-char (point-min))
+  (goto-line n
+
 (provide 'notmuch)
-- 
1.6.5.2



[notmuch] [PATCH 2/3] Add 'notmuch count' command to show the count of matching messages

2009-11-20 Thread Keith Packard
Getting the count of matching threads or messages is a fairly
expensive operation. Xapian provides a very efficient mechanism that
returns an approximate value, so use that for this new command.

This returns the number of matching messages, not threads, as that is
cheap to compute.

Signed-off-by: Keith Packard 
---
 Makefile.local   |1 +
 lib/notmuch.h|8 
 lib/query.cc |   52 ++
 notmuch-client.h |3 +
 notmuch-count.c  |  109 ++
 notmuch.c|   11 +
 6 files changed, 184 insertions(+), 0 deletions(-)
 create mode 100644 notmuch-count.c

diff --git a/Makefile.local b/Makefile.local
index 3c99624..cbd75ce 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -5,6 +5,7 @@ emacs: notmuch.elc
 notmuch_client_srcs =  \
notmuch.c   \
notmuch-config.c\
+   notmuch-count.c \
notmuch-dump.c  \
notmuch-new.c   \
notmuch-reply.c \
diff --git a/lib/notmuch.h b/lib/notmuch.h
index cc713a3..937f3b6 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -459,6 +459,14 @@ notmuch_threads_advance (notmuch_threads_t *threads);
 void
 notmuch_threads_destroy (notmuch_threads_t *threads);

+/* Return an estimate of the number of messages matching a search
+ *
+ * This function performs a search and returns Xapian's best
+ * guess as to number of matching messages.
+ */
+unsigned
+notmuch_query_count_messages (notmuch_query_t *query);
+ 
 /* Get the thread ID of 'thread'.
  *
  * The returned string belongs to 'thread' and as such, should not be
diff --git a/lib/query.cc b/lib/query.cc
index ea521dd..dff9634 100644
--- a/lib/query.cc
+++ b/lib/query.cc
@@ -278,3 +278,55 @@ notmuch_threads_destroy (notmuch_threads_t *threads)
 {
 talloc_free (threads);
 }
+
+unsigned
+notmuch_query_count_messages (notmuch_query_t *query)
+{
+notmuch_database_t *notmuch = query->notmuch;
+const char *query_string = query->query_string;
+Xapian::doccount count;
+
+try {
+   Xapian::Enquire enquire (*notmuch->xapian_db);
+   Xapian::Query mail_query (talloc_asprintf (query, "%s%s",
+  _find_prefix ("type"),
+  "mail"));
+   Xapian::Query string_query, final_query;
+   Xapian::MSet mset;
+   unsigned int flags = (Xapian::QueryParser::FLAG_BOOLEAN |
+ Xapian::QueryParser::FLAG_PHRASE |
+ Xapian::QueryParser::FLAG_LOVEHATE |
+ Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE |
+ Xapian::QueryParser::FLAG_WILDCARD |
+ Xapian::QueryParser::FLAG_PURE_NOT);
+
+   if (strcmp (query_string, "") == 0) {
+   final_query = mail_query;
+   } else {
+   string_query = notmuch->query_parser->
+   parse_query (query_string, flags);
+   final_query = Xapian::Query (Xapian::Query::OP_AND,
+mail_query, string_query);
+   }
+
+   enquire.set_weighting_scheme(Xapian::BoolWeight());
+   enquire.set_docid_order(Xapian::Enquire::ASCENDING);
+
+#if DEBUG_QUERY
+   fprintf (stderr, "Final query is:\n%s\n", 
final_query.get_description().c_str());
+#endif
+
+   enquire.set_query (final_query);
+
+   mset = enquire.get_mset (0, notmuch->xapian_db->get_doccount ());
+
+   count = mset.get_matches_estimated();
+
+} catch (const Xapian::Error ) {
+   fprintf (stderr, "A Xapian exception occurred: %s\n",
+error.get_msg().c_str());
+   fprintf (stderr, "Query string was: %s\n", query->query_string);
+}
+
+return count;
+}
diff --git a/notmuch-client.h b/notmuch-client.h
index b65aa77..9884497 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -91,6 +91,9 @@ chomp_newline (char *str)
 }

 int
+notmuch_count_command (void *ctx, int argc, char *argv[]);
+
+int
 notmuch_dump_command (void *ctx, int argc, char *argv[]);

 int
diff --git a/notmuch-count.c b/notmuch-count.c
new file mode 100644
index 000..68e428f
--- /dev/null
+++ b/notmuch-count.c
@@ -0,0 +1,109 @@
+/* notmuch - Not much of an email program, (just index and search)
+ *
+ * Copyright ?? 2009 Carl Worth
+ * Copyright ?? 2009 Keith Packard
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * G

[notmuch] [PATCH 1/3] Make mouse-1 click in search view show thread

2009-11-20 Thread Keith Packard
Selecting text in the search view isn't all that useful, so instead,
make mouse-1 clicks actually show the thread you click on. It's almost
like direct manipulation or something.

Signed-off-by: Keith Packard 
---
 notmuch.el |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index feb84ad..4f369de 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -783,6 +783,7 @@ thread from that buffer can be show when done with this 
one)."
 (define-key map "t" 'notmuch-search-filter-by-tag)
 (define-key map "x" 'kill-this-buffer)
 (define-key map (kbd "RET") 'notmuch-search-show-thread)
+(define-key map [mouse-1] 'notmuch-search-show-thread)
 (define-key map "+" 'notmuch-search-add-tag)
 (define-key map "-" 'notmuch-search-remove-tag)
 (define-key map "<" 'beginning-of-buffer)
-- 
1.6.5.2



[notmuch] [PATCH] Insert signature into replies

2009-11-20 Thread Keith Packard
When you compose a new message, message mode carefully inserts your
mail signature at the bottom of the message; as notmuch constructs the
reply all by itself, this doesn't happen then. Use the message mode
function 'message-insert-signature' to add that to reply buffers.

Signed-off-by: Keith Packard 
---
 notmuch.el |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index bed6a25..feb84ad 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -308,6 +308,7 @@ buffer."
 (defun notmuch-reply (query-string)
   (switch-to-buffer (generate-new-buffer "notmuch-draft"))
   (call-process notmuch-command nil t nil "reply" query-string)
+  (message-insert-signature)
   (goto-char (point-min))
   (if (re-search-forward "^$" nil t)
   (progn
-- 
1.6.5.2



[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags

2009-11-20 Thread Keith Packard
When closing a thread view, mark the thread as archived by removing
the "inbox" tag, and for the 'x' variant, the "unread" tag as well,
then kill the buffer and update the search window view as well.

This makes 'x' much the same as 'a', but instead of taking you to the
next message, it takes you back to the search window instead.

Signed-off-by: Keith Packard 
---
 notmuch.el |   86 ++-
 1 files changed, 67 insertions(+), 19 deletions(-)

This adds new functionality without removing any; without this patch,
the 'x' and 'q' commands do the same thing,  killing the buffer
without clearing any tags. With this patch, the 'x' command clears the
inbox and unread tags from the current message and returns to the
search index view, while the existing 'q' command continues to provide
old behaviour.

diff --git a/notmuch.el b/notmuch.el
index cd3780f..544f281 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -31,8 +31,8 @@
 ; Will be much preferable to switch to direct manipulation for
 ; toggling visibility of these components. Probably using
 ; overlays-at to query and manipulate the current overlay.
-(define-key map "a" 'notmuch-show-archive-thread)
-(define-key map "A" 'notmuch-show-mark-read-then-archive-thread)
+(define-key map "a" 'notmuch-show-mark-read-archive-thread-next-thread)
+(define-key map "A" 'notmuch-show-archive-thread-next-thread)
 (define-key map "b" 'notmuch-show-toggle-body-read-visible)
 (define-key map "c" 'notmuch-show-toggle-citations-visible)
 (define-key map "h" 'notmuch-show-toggle-headers-visible)
@@ -47,7 +47,8 @@
 (define-key map "s" 'notmuch-show-toggle-signatures-visible)
 (define-key map "v" 'notmuch-show-view-all-mime-parts)
 (define-key map "w" 'notmuch-show-view-raw-message)
-(define-key map "x" 'kill-this-buffer)
+(define-key map "x" 'notmuch-show-mark-read-archive-thread-kill-buffer)
+(define-key map "X" 'notmuch-show-archive-thread-kill-buffer)
 (define-key map "+" 'notmuch-show-add-tag)
 (define-key map "-" 'notmuch-show-remove-tag)
 (define-key map (kbd "DEL") 'notmuch-show-rewind)
@@ -193,7 +194,33 @@ Unlike builtin `next-line' this version accepts no 
arguments."
 (cons (notmuch-show-get-message-id) nil)))
  (notmuch-show-set-tags (sort (set-difference tags toremove :test 
'string=) 'string<))

-(defun notmuch-show-archive-thread-maybe-mark-read (markread)
+(defun notmuch-show-next-thread (markread)
+  (let ((parent-buffer notmuch-show-parent-buffer))
+(kill-this-buffer)
+(if parent-buffer
+   (progn
+ (switch-to-buffer parent-buffer)
+ (forward-line)
+ (notmuch-search-show-thread)
+  
+(defun notmuch-delete-tags (to-remove from)
+  (if to-remove
+  (delete (car to-remove) (notmuch-delete-tags (cdr to-remove) from))
+from))
+
+(defun notmuch-kill-message-buffer (markread)
+  (let ((parent-buffer notmuch-show-parent-buffer))
+(kill-this-buffer)
+(if parent-buffer
+   (progn
+ (switch-to-buffer parent-buffer)
+ (let ((tags (notmuch-search-get-tags)))
+   (setq tags (delete "inbox" tags))
+   (if markread (setq tags (delete "unread" tags)))
+   (notmuch-search-set-tags tags))
+ (forward-line)
+
+(defun notmuch-show-archive-thread-maybe-mark-read (markread shownext)
   (save-excursion
 (goto-char (point-min))
 (while (not (eobp))
@@ -204,15 +231,9 @@ Unlike builtin `next-line' this version accepts no 
arguments."
  (forward-char))
   (if (not (re-search-forward notmuch-show-message-begin-regexp nil t))
  (goto-char (point-max)
-  (let ((parent-buffer notmuch-show-parent-buffer))
-(kill-this-buffer)
-(if parent-buffer
-   (progn
- (switch-to-buffer parent-buffer)
- (forward-line)
- (notmuch-search-show-thread)
+  (if shownext (notmuch-show-next-thread markread) 
(notmuch-kill-message-buffer markread)))

-(defun notmuch-show-mark-read-then-archive-thread ()
+(defun notmuch-show-mark-read-archive-thread-next-thread ()
   "Remove \"unread\" tag from each message, then archive and show next thread.

 Archive each message currently shown by removing the \"unread\"
@@ -225,9 +246,22 @@ being delivered to the same thread. It does not archive the
 entire thread, but only the messages shown in the current
 buffer."
   (interactive)
-  (notmuch-show-archive-thread-maybe-mark-read t))
+  (notmuch-show-archive-thread-maybe-mark-read t t))
+
+(defun notmuch-show-mark-read-archive-thread-kill-buffer ()
+  "Remove \"unread\" tag from each message, then archive and kill the buffer.
+
+Archive each

[notmuch] [PATCH] notmuch: improve installation of emacs mode

2009-11-19 Thread Keith Packard

On Thu, 19 Nov 2009 00:18:50 -0600, "Jeffrey C. Ollie"  
wrote:
> 1) Don't hardcode the installation directory, instead use emacs'
>pkg-config module.
> 
> 2) Install a byte compiled version of the emacs mode.

yes, both of these seem reasonable

> 3) Install the emacs mode in emacs' site-start directory so that it
>gets loaded automatically.

I'd say anyone using notmuch should just use (require 'notmuch) instead;
that way you don't abuse people not using this system. This is similar
to most other package usage with emacs...

--
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] [PATCH -V3] notmuch: Add search mode hook

2009-11-19 Thread Keith Packard
On Thu, 19 Nov 2009 11:40:54 +0530, "Aneesh Kumar K.V"  wrote:
> This patch add notmuch-search-hook that gets run when we
> after displaying search results

Looks good.

> Signed-off-by: Aneesh Kumar K.V 
Reviewed-by: Keith Packard 

--
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20091119/8536ad3e/attachment.pgp>


[notmuch] [PATCH] notmuch: Add search mode hook

2009-11-18 Thread Keith Packard
On Thu, 19 Nov 2009 10:25:37 +0530, "Aneesh Kumar K.V"  wrote:

> This patch add notmuch-search-mode-hook and rename
> notmuch-show-hook to notmuch-show-mode-hook. This
> also runs notmuch-show-mode-hook when we enable
> notmuch-show-mode

I'm not sure we want to run the hooks that early; I can easily imagine
hooks that want to be run after the message has been loaded.

--
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] [PATCH] Handle rename of message file

2009-11-18 Thread Keith Packard
On Thu, 19 Nov 2009 08:11:12 +0600, Mikhail Gusarov  wrote:
> 
> Twas brillig at 18:06:09 18.11.2009 UTC-08 when keithp at keithp.com did gyre 
> and gimble:
> 
>  KP> Checking for new files is easy; notmuch already does that, and so
>  KP> handling renames doesn't seem all that difficult.
> 
> Except rename does not change mtime of file, and so it won't be picked
> up by 'notmuch new'.

Yeah, good point -- notmuch new doesn't make sure each file it finds is
already in the database. Again, some kind of inotify-based daemon would
make that efficient, while starting up that daemon could take some time
while the database was searched for new or missing files.

Alternatively, we could record the contents of the directory after
scanning it and then use that to track file changes. It seems like the
current database just doesn't have enough information to make this
tractable.

--
keith.packard at intel.com

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



[notmuch] [PATCH] Handle rename of message file

2009-11-18 Thread Keith Packard
On Thu, 19 Nov 2009 02:08:15 +0100, Carl Worth  wrote:

> I'd love to hear more from you on any experiments/ideas you have in this
> area. It would be a really nice feature to have, (particularly for
> people who are experimenting with notmuch while still using some other
> primary email program that keeps fiddling with the filenames).

Checking for new files is easy; notmuch already does that, and so
handling renames doesn't seem all that difficult. The hard part to me is
detecting deleted messages; about the only thing I can imagine being at
all efficient is to use inotify in a daemon. Starting that daemon up
would entail scanning the database for all messages in a particular
directory and then looking for those files to see if they were still
around. Ick.

--
keith.packard at intel.com




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



[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags

2009-11-18 Thread Keith Packard
On Thu, 19 Nov 2009 01:25:34 +0100, Carl Worth  wrote:
> On Wed, 18 Nov 2009 09:45:01 -0800, Keith Packard  
> wrote:
> > On Wed, 18 Nov 2009 02:19:26 -0800, Carl Worth  wrote:
> > You can use kill-buffer directly (C-X k); adding a new special binding
> > for that command seems unnecessary to me.
> 
> Well, that's "Control, X, K, Enter", so quite a bit harder than just
> 'x'. :-)

I'd forgotten about the 'q' binding, which used to be the same as 'x'
and is now different. Similar to how fdisk differentiates between
'q'uit without saving changes and 'w'rite table to disk and exit.

> But fine, I could move my convenience for "kill buffer" to just 'k'.

You've got 'q' already :-)

> I think I'd like to see a better mapping for "archive and kill buffer"
> to a key other than 'x'. Any ideas?

I'm up for almost anything; but I'd have to retrain my fingers to use it
instead of 'x' :-)

> 1. Before I go into "read a bunch of messages with spacebar" mode I
>first arrange for filtered search results that I know I want to read
>all together.

I generally do the same, but don't read mail in time sequence. One of
the reasons I like the threaded reading mode is that I don't *have* to
read mail in time sequence as I can review a thread and see the time
ordering of the messages within that.

> 2. When I archive a thread with 'a', I'm not necessarily always planning
>to read the next message (just because notmuch is presenting it to
>me). And if not, I'll just press 'x' right away.

Right, if you use the 'a' key to flip to a new message, you probably
don't want to use 'x' on the final (and still essentially ignored)
message.

>Of course, for this I need an "archive all" binding that
>doesn't exist yet. And I also really need to fix the Xapian bug so
>that archiving 100 threads doesn't take *forever* like it does
>currently.

yes, please! I'd even be willing to wait at this point...

--
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20091118/46d9c4b0/attachment.pgp>


[notmuch] [PATCH] Make reply/show/tag all require at least one search term

2009-11-18 Thread Keith Packard
In particular, notmuch tag -inbox "" tended to take a long time to
run, happened if you hit 'a' on a blank line in the search view and
probably didn't have the desired effect.

Signed-off-by: Keith Packard 
---
 notmuch-reply.c |   13 +
 notmuch-show.c  |   13 +
 notmuch-tag.c   |8 
 3 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index 4a4a782..31e2c87 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -196,16 +196,21 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
 if (config == NULL)
return 1;

-notmuch = notmuch_database_open (notmuch_config_get_database_path 
(config));
-if (notmuch == NULL)
-   return 1;
-
 query_string = query_string_from_args (ctx, argc, argv);
 if (query_string == NULL) {
fprintf (stderr, "Out of memory\n");
return 1;
 }

+if (*query_string == '\0') {
+   fprintf (stderr, "Error: notmuch reply requires at least one search 
term.\n");
+   return 1;
+}
+
+notmuch = notmuch_database_open (notmuch_config_get_database_path 
(config));
+if (notmuch == NULL)
+   return 1;
+
 query = notmuch_query_create (notmuch, query_string);
 if (query == NULL) {
fprintf (stderr, "Out of memory\n");
diff --git a/notmuch-show.c b/notmuch-show.c
index 59a58c2..c0c3ca3 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -196,16 +196,21 @@ notmuch_show_command (void *ctx, unused (int argc), 
unused (char *argv[]))
 if (config == NULL)
return 1;

-notmuch = notmuch_database_open (notmuch_config_get_database_path 
(config));
-if (notmuch == NULL)
-   return 1;
-
 query_string = query_string_from_args (ctx, argc, argv);
 if (query_string == NULL) {
fprintf (stderr, "Out of memory\n");
return 1;
 }

+if (*query_string == '\0') {
+   fprintf (stderr, "Error: notmuch show requires at least one search 
term.\n");
+   return 1;
+}
+
+notmuch = notmuch_database_open (notmuch_config_get_database_path 
(config));
+if (notmuch == NULL)
+   return 1;
+
 query = notmuch_query_create (notmuch, query_string);
 if (query == NULL) {
fprintf (stderr, "Out of memory\n");
diff --git a/notmuch-tag.c b/notmuch-tag.c
index 7d92ec4..12ab86c 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -83,8 +83,10 @@ notmuch_tag_command (void *ctx, unused (int argc), unused 
(char *argv[]))
return 1;
 }

-if (i == argc) {
-   fprintf (stderr, "Error: 'notmuch tag' requires at least one search 
term.\n");
+query_string = query_string_from_args (ctx, argc - i, [i]);
+
+if (*query_string == '\0') {
+   fprintf (stderr, "Error: notmuch tag requires at least one search 
term.\n");
return 1;
 }

@@ -96,8 +98,6 @@ notmuch_tag_command (void *ctx, unused (int argc), unused 
(char *argv[]))
 if (notmuch == NULL)
return 1;

-query_string = query_string_from_args (ctx, argc - i, [i]);
-
 query = notmuch_query_create (notmuch, query_string);
 if (query == NULL) {
fprintf (stderr, "Out of memory.\n");
-- 
1.6.5.2



[notmuch] [PATCH] notmuch: Add tag archive when archiving the mails

2009-11-18 Thread Keith Packard
On Wed, 18 Nov 2009 13:50:58 -0600, Jeffrey Ollie  wrote:

> That resulted in an error for me:
> 
> $ notmuch search not tag:inbox
> A Xapian exception occurred: Syntax:  NOT 
> A Xapian exception occurred: Syntax:  NOT 

Yeah, NOT isn't a unary operator in xapian; it's a binary operator that
means 'AND NOT'. The Xapian docs say that if you set the FLAG_PURE_NOT
flag, you'll get the unary behaviour, but I haven't tried that.

--
keith.packard at intel.com
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: 



[notmuch] [PATCH] Have git ignore etags file

2009-11-18 Thread Keith Packard
---
 .gitignore |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore
index d277c5a..367caa6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+TAGS
 .deps
 notmuch
 notmuch.1.gz
-- 
1.6.5.2



[notmuch] [PATCH] Limit reverse searches to 100 threads.

2009-11-18 Thread Keith Packard
Yes, this is a lame default, but it serves my purposes.

Signed-off-by: Keith Packard 
---
 notmuch.el |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 4498200..91ed073 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -945,7 +945,7 @@ This function advances point to the next line when 
finished."
   (save-excursion
(if oldest-first
(call-process "notmuch" nil t nil "search" query)
- (call-process "notmuch" nil t nil "search" "--reverse" query))
+ (call-process "notmuch" nil t nil "search" "--max-threads=100" 
"--reverse" query))
(notmuch-search-markup-thread-ids)


-- 
1.6.5.2



[notmuch] [PATCH] Filter out carriage-returns in show and reply output.

2009-11-18 Thread Keith Packard
Thanks, windows mail clients.

Signed-off-by: Keith Packard 
---
 gmime-filter-reply.c |7 ---
 notmuch-show.c   |   21 +++--
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/gmime-filter-reply.c b/gmime-filter-reply.c
index 3e298e1..b269db4 100644
--- a/gmime-filter-reply.c
+++ b/gmime-filter-reply.c
@@ -130,8 +130,9 @@ filter_filter (GMimeFilter *filter, char *inbuf, size_t 
inlen, size_t prespace,
reply->saw_nl = TRUE;
else
reply->saw_nl = FALSE;
-
-   *outptr++ = *inptr++;
+   if (*inptr != '\r')
+   *outptr++ = *inptr;
+   inptr++;
}
} else {
g_mime_filter_set_size (filter, inlen + 1, FALSE);
@@ -150,7 +151,7 @@ filter_filter (GMimeFilter *filter, char *inbuf, size_t 
inlen, size_t prespace,
else
*outptr++ = *inptr;
reply->saw_angle = FALSE;
-   } else {
+   } else if (*inptr != '\r') {
if (*inptr == '\n')
reply->saw_nl = TRUE;
*outptr++ = *inptr;
diff --git a/notmuch-show.c b/notmuch-show.c
index 7749dbc..4c377e1 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -99,14 +99,23 @@ show_part (GMimeObject *part, int *part_count)
 if (g_mime_content_type_is_type (content_type, "text", "*") &&
!g_mime_content_type_is_type (content_type, "text", "html"))
 {
-   GMimeStream *stream = g_mime_stream_file_new (stdout);
-   g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream), FALSE);
+   GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
+   GMimeStream *stream_filter = NULL;
+   
+   if (stream_stdout) {
+   g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), 
FALSE);
+   stream_filter = g_mime_stream_filter_new(stream_stdout);
+   g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
+g_mime_filter_crlf_new(FALSE, FALSE));
+   }

wrapper = g_mime_part_get_content_object (GMIME_PART (part));
-   if (wrapper && stream)
-   g_mime_data_wrapper_write_to_stream (wrapper, stream);
-   if (stream)
-   g_object_unref(stream);
+   if (wrapper && stream_filter)
+   g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
+   if (stream_filter)
+   g_object_unref(stream_filter);
+   if (stream_stdout)
+   g_object_unref(stream_stdout);
 }
 else
 {
-- 
1.6.5.2



[notmuch] [PATCH] notmuch: Add tag archive when archiving the mails

2009-11-18 Thread Keith Packard

> This enables us to search for archived mails later

I think you can just use 'not tag:inbox' as 'archived' really just means
'doesn't have the inbox tag'.

--
keith.packard at intel.com


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



[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags

2009-11-18 Thread Keith Packard
On Wed, 18 Nov 2009 02:19:26 -0800, Carl Worth  wrote:

> I don't like this---but that's because I use 'x' precisely *because* it
> preserves these tags.

You can use kill-buffer directly (C-X k); adding a new special binding
for that command seems unnecessary to me.

> Otherwise, you might as well just remove inbox and unread as soon as the
> message is presented to the user. And that's a bug in a lot of other
> email programs that I'm unwilling to replicate.

My mail flow doesn't involve moving directly from one message to the
next; I go back to the index after reviewing each one; there isn't a way
to mark a buffer as read/archived and *not* view another message

--
keith.packard at intel.com

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



[notmuch] [PATCH] We use the message mail system for new mail, let emacs know.

2009-11-18 Thread Keith Packard
This makes things like the goto-address system bring up the right
message composition window.

Signed-off-by: Keith Packard 
---
 notmuch.el |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index c95cb43..4498200 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -1008,4 +1008,6 @@ current search results AND that are tagged with the given 
tag."
   (interactive)
   (notmuch-search "tag:inbox" t))

+(setq mail-user-agent 'message-user-agent)
+
 (provide 'notmuch)
-- 
1.6.5.2



[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap

2009-11-18 Thread Keith Packard
I created the notmuch-show-hook precisely so I could add these two
options, but I suspect most people will want them, so I just made them
the default. If you don't want them, you can use remove-hook to get
rid of this.

Signed-off-by: Keith Packard 
---
 notmuch.el |8 
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 1bb1294..c95cb43 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -698,6 +698,14 @@ view, (remove the \"inbox\" tag from each), with either
   :options '(goto-address)
   :group 'notmuch)

+; Make show mode a bit prettier, highlighting URLs and using word wrap
+
+(defun notmuch-show-pretty-hook ()
+  (goto-address-mode 1)
+  (visual-line-mode))
+
+(add-hook 'notmuch-show-hook 'notmuch-show-pretty-hook)
+
 (defun notmuch-show (thread-id  parent-buffer)
   "Run \"notmuch show\" with the given thread ID and display results.

-- 
1.6.5.2



[notmuch] archive

2009-11-17 Thread Keith Packard
On Tue, 17 Nov 2009 18:21:38 -0500, Aron Griffis  wrote:

> Just subscribed, I'd like to catch up on the previous postings,
> but the archive link seems to be bogus?

Yeah, the archive appears broken and will need to wait until Carl
arrives in Barcelona to get fixed.

--
keith.packard at intel.com




[notmuch] Introducing myself

2009-11-17 Thread Keith Packard
On Wed, 18 Nov 2009 00:20:59 +0100, Adrian Perez de Castro  wrote:

> Some time ago I thought
> about doing something like Not Much and in fact I played a bit with the
> Python+Xapian and the Python+Whoosh combinations, because I find relaxing
> to code things in Python when I am not working and also it is installed
> by default on most distribution. I got to have some mailboxes indexed and
> basic searching working a couple of months ago.

Sup certainly started a lot of people thinking...

> Also, I would like to share one idea I had in mind, that you might find
> interesting: One thing I have found very annoying is having to re-tag my
> mail when the indexes get b0rked (it happened a couple of times to me while
> using Sup), so I was planning to mails as read/unread and adding the tags
> not just to the index, but to the mail text itself, e.g. by adding a
> "X-Tags" header field or by reusing the "Keywords" one.

Easier than that, notmuch (and sup too), provide a 'dump' command which
just lists all of the message IDs and their associated tags. Makes
saving tags easy and doesn't involve rewriting messages. I do this once
a day just before my computer is backed up to an external drive.

If the index is destroyed, you can reindex the messages and then reapply
all of the tags with 'notmuch restore'.

--
keith.packard at intel.com



[notmuch] New to the list

2009-11-17 Thread Keith Packard
On Tue, 17 Nov 2009 23:57:18 +0100, Israel Herraiz  wrote:

> "Not much" sounds interesting, and I wonder whether it could be
> integrated with the views of Sup (inbox, threads, etc). So I have
> subscribed to the list to keep an eye on what's going on here.

We've tried to clone much of the sup UI inside emacs, including the
inbox and threaded message presentation. Of course, we had to "improve"
it a bit, as much due to the differences between curses and emacs as due
to personal preferences...

-keith


[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags

2009-11-17 Thread Keith Packard
When closing a thread view, mark the thread as archived by removing
the "inbox" tag, and for the 'x' variant, the "unread" tag as well,
then kill the buffer and update the search window view as well.

This makes 'x' much the same as 'a', but instead of taking you to the
next message, it takes you back to the search window instead.

Signed-off-by: Keith Packard 
---
 notmuch.el |   86 ++-
 1 files changed, 67 insertions(+), 19 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 638d49d..7b0d72c 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -31,8 +31,8 @@
 ; Will be much preferable to switch to direct manipulation for
 ; toggling visibility of these components. Probably using
 ; overlays-at to query and manipulate the current overlay.
-(define-key map "a" 'notmuch-show-archive-thread)
-(define-key map "A" 'notmuch-show-mark-read-then-archive-thread)
+(define-key map "a" 'notmuch-show-mark-read-archive-thread-next-thread)
+(define-key map "A" 'notmuch-show-archive-thread-next-thread)
 (define-key map "b" 'notmuch-show-toggle-body-read-visible)
 (define-key map "c" 'notmuch-show-toggle-citations-visible)
 (define-key map "h" 'notmuch-show-toggle-headers-visible)
@@ -47,7 +47,8 @@
 (define-key map "s" 'notmuch-show-toggle-signatures-visible)
 (define-key map "v" 'notmuch-show-view-all-mime-parts)
 (define-key map "w" 'notmuch-show-view-raw-message)
-(define-key map "x" 'kill-this-buffer)
+(define-key map "x" 'notmuch-show-mark-read-archive-thread-kill-buffer)
+(define-key map "X" 'notmuch-show-archive-thread-kill-buffer)
 (define-key map "+" 'notmuch-show-add-tag)
 (define-key map "-" 'notmuch-show-remove-tag)
 (define-key map (kbd "DEL") 'notmuch-show-rewind)
@@ -183,7 +184,33 @@ Unlike builtin `next-line' this version accepts no 
arguments."
 (cons (notmuch-show-get-message-id) nil)))
  (notmuch-show-set-tags (sort (set-difference tags toremove :test 
'string=) 'string<))

-(defun notmuch-show-archive-thread-maybe-mark-read (markread)
+(defun notmuch-show-next-thread (markread)
+  (let ((parent-buffer notmuch-show-parent-buffer))
+(kill-this-buffer)
+(if parent-buffer
+   (progn
+ (switch-to-buffer parent-buffer)
+ (forward-line)
+ (notmuch-search-show-thread)
+  
+(defun notmuch-delete-tags (to-remove from)
+  (if to-remove
+  (delete (car to-remove) (notmuch-delete-tags (cdr to-remove) from))
+from))
+
+(defun notmuch-kill-message-buffer (markread)
+  (let ((parent-buffer notmuch-show-parent-buffer))
+(kill-this-buffer)
+(if parent-buffer
+   (progn
+ (switch-to-buffer parent-buffer)
+ (let ((tags (notmuch-search-get-tags)))
+   (setq tags (delete "inbox" tags))
+   (if markread (setq tags (delete "unread" tags)))
+   (notmuch-search-set-tags tags))
+ (forward-line)
+
+(defun notmuch-show-archive-thread-maybe-mark-read (markread shownext)
   (save-excursion
 (goto-char (point-min))
 (while (not (eobp))
@@ -194,15 +221,9 @@ Unlike builtin `next-line' this version accepts no 
arguments."
  (forward-char))
   (if (not (re-search-forward notmuch-show-message-begin-regexp nil t))
  (goto-char (point-max)
-  (let ((parent-buffer notmuch-show-parent-buffer))
-(kill-this-buffer)
-(if parent-buffer
-   (progn
- (switch-to-buffer parent-buffer)
- (forward-line)
- (notmuch-search-show-thread)
+  (if shownext (notmuch-show-next-thread markread) 
(notmuch-kill-message-buffer markread)))

-(defun notmuch-show-mark-read-then-archive-thread ()
+(defun notmuch-show-mark-read-archive-thread-next-thread ()
   "Remove \"unread\" tag from each message, then archive and show next thread.

 Archive each message currrently shown by removing the \"unread\"
@@ -215,9 +236,22 @@ being delivered to the same thread. It does not archive the
 entire thread, but only the messages shown in the current
 buffer."
   (interactive)
-  (notmuch-show-archive-thread-maybe-mark-read t))
+  (notmuch-show-archive-thread-maybe-mark-read t t))
+
+(defun notmuch-show-mark-read-archive-thread-kill-buffer ()
+  "Remove \"unread\" tag from each message, then archive and kill the buffer.
+
+Archive each message currrently shown by removing the \"unread\"
+and \"inbox\" tag from each. Then kill this buffer.
+
+Note: This command is safe from any race condition of new messages
+being delivered to the same thread. It does not archive the
+entire thread, but only the messages shown in the current
+buffer."
+  (interactive)
+  (notmu

[notmuch] Working with Maildir storage?

2009-11-17 Thread Keith Packard
On Tue, 17 Nov 2009 15:33:01 -0500, Lars Kellogg-Stedman  wrote:
> > See the patch just posted here.

I've also pushed a slightly more complicated (and complete) fix to my
private notmuch repository

git://keithp.com/git/notmuch

> Is the list archived anywhere?

Oops. Looks like Carl's mail server is broken. He's traveling to
Barcelona today and so it won't get fixed for a while.

Thanks to everyone for trying out notmuch!

-keith


[notmuch] [PATCH 1/2] Close message file after parsing message headers

2009-11-17 Thread Keith Packard
On Tue, 17 Nov 2009 09:13:27 -0800, Carl Worth  wrote:

> I didn't apply Keith's fix yet, because I think I'd rather just fix the
> indexer to store the In-Reply-To header in a separate term prefix from
> the term used for the References header[*]. That will then let us lookup
> the in-reply-to value later for thread constructions without having to
> open the original email file at all.

Threading the message also involves displaying the from and to contents,
which requires opening the message file. The alternative to the fix I
provided is to just parse all of the message headers when first opening
the message; it could then be immediately closed and the hash referred
to for all header data. Given the choice, just having the caller say
when it has finished with a message is probably a reasonable option...

-keith