[Stefano Zacchiroli] Bug#628018: [PATCH] mutt-notmuch in notmuch contrib
authorDavid Bremner <bremner@unb.ca>
Mon, 26 Mar 2012 10:32:12 +0000 (07:32 +2100)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:45:44 +0000 (09:45 -0800)
07/033432c64acc66e8eeb92598cd439ee3d79e8d [new file with mode: 0644]

diff --git a/07/033432c64acc66e8eeb92598cd439ee3d79e8d b/07/033432c64acc66e8eeb92598cd439ee3d79e8d
new file mode 100644 (file)
index 0000000..af3cb68
--- /dev/null
@@ -0,0 +1,857 @@
+Return-Path: <bremner@unb.ca>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+       by olra.theworths.org (Postfix) with ESMTP id 20675431FAF\r
+       for <notmuch@notmuchmail.org>; Mon, 26 Mar 2012 03:32:23 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]\r
+       autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+       by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+       with ESMTP id kOKsp0-mdRHT for <notmuch@notmuchmail.org>;\r
+       Mon, 26 Mar 2012 03:32:21 -0700 (PDT)\r
+Received: from tesseract.cs.unb.ca (tesseract.cs.unb.ca [131.202.240.238])\r
+       (using TLSv1 with cipher AES256-SHA (256/256 bits))\r
+       (No client certificate requested)\r
+       by olra.theworths.org (Postfix) with ESMTPS id C4563431FAE\r
+       for <notmuch@notmuchmail.org>; Mon, 26 Mar 2012 03:32:20 -0700 (PDT)\r
+Received: from fctnnbsc30w-142166230117.dhcp-dynamic.fibreop.nb.bellaliant.net\r
+       ([142.166.230.117] helo=zancas.localnet)\r
+       by tesseract.cs.unb.ca with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32)\r
+       (Exim 4.72) (envelope-from <bremner@unb.ca>)\r
+       id 1SC7Dm-00085e-7r; Mon, 26 Mar 2012 07:32:19 -0300\r
+Received: from bremner by zancas.localnet with local (Exim 4.77)\r
+       (envelope-from <bremner@unb.ca>)\r
+       id 1SC7Dg-000586-Qv; Mon, 26 Mar 2012 07:32:12 -0300\r
+From: David Bremner <bremner@unb.ca>\r
+To: notmuch@notmuchmail.org\r
+Subject: [Stefano Zacchiroli] Bug#628018: [PATCH] mutt-notmuch in notmuch\r
+       contrib\r
+User-Agent: Notmuch/0.12 (http://notmuchmail.org) Emacs/23.3.1\r
+       (x86_64-pc-linux-gnu)\r
+Date: Mon, 26 Mar 2012 07:32:12 -0300\r
+Message-ID: <87haxbr6tv.fsf@zancas.localnet>\r
+MIME-Version: 1.0\r
+Content-Type: multipart/mixed; boundary="=-=-="\r
+X-Spam_bar: -\r
+Cc: Stefano Zacchiroli <zack@debian.org>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+       <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Mon, 26 Mar 2012 10:32:23 -0000\r
+\r
+--=-=-=\r
+\r
+\r
+Hi, this will probably eventually make it to the list, but until then,\r
+here is a forwarded version. Please keep Stefano in CC, I don't think he's\r
+subscribed.\r
+\r
+\r
+--=-=-=\r
+Content-Type: message/rfc822\r
+Content-Disposition: inline\r
+Content-Transfer-Encoding: 8bit\r
+\r
+Return-path: <bounces+20120325-bremner=debian.org@packages.qa.debian.org>\r
+Envelope-to: david@tethera.net\r
+Delivery-date: Sun, 25 Mar 2012 11:29:53 -0300\r
+Received: from yantan.tethera.net ([67.202.105.224])\r
+       by tesseract.cs.unb.ca with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32)\r
+       (Exim 4.72)\r
+       (envelope-from <bounces+20120325-bremner=debian.org@packages.qa.debian.org>)\r
+       id 1SBoS6-0007Ps-Gz\r
+       for david@tethera.net; Sun, 25 Mar 2012 11:29:53 -0300\r
+Received: from quantz.debian.org ([206.12.19.122])\r
+       by yantan.tethera.net with esmtp (Exim 4.72)\r
+       (envelope-from <bounces+20120325-bremner=debian.org@packages.qa.debian.org>)\r
+       id 1SBoS5-0001U1-C0\r
+       for david@tethera.net; Sun, 25 Mar 2012 11:29:49 -0300\r
+Received: from qa by quantz.debian.org with local (Exim 4.72)\r
+       (envelope-from <bounces+20120325-bremner=debian.org@packages.qa.debian.org>)\r
+       id 1SBoS4-0005Po-Gi\r
+       for david@tethera.net; Sun, 25 Mar 2012 14:29:48 +0000\r
+Received: from busoni.debian.org ([140.211.15.34])     from C=NA,ST=NA,\r
+ L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=busoni.debian.org,\r
+ EMAIL=hostmaster@busoni.debian.org (verified) by quantz.debian.org with\r
+ esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32)       (Exim 4.72)     (envelope-from\r
+ <debbugs@busoni.debian.org>)  id 1SBoS4-0005PY-4y     for\r
+ notmuch@packages.qa.debian.org; Sun, 25 Mar 2012 14:29:48 +0000\r
+Received: from debbugs by busoni.debian.org with local (Exim 4.72)\r
+ (envelope-from <debbugs@busoni.debian.org>)   id 1SBoS2-0003w7-D7; Sun,\r
+ 25 Mar 2012 14:29:47 +0000\r
+X-Loop: owner@bugs.debian.org\r
+Subject: Bug#628018: [PATCH] mutt-notmuch in notmuch contrib\r
+Reply-To: Stefano Zacchiroli <zack@debian.org>, 628018-quiet@bugs.debian.org\r
+Resent-From: Stefano Zacchiroli <zack@debian.org>\r
+Resent-To: \r
+Resent-Date: Sun, 25 Mar 2012 14:29:45 +0000\r
+Resent-Message-ID: <handler.628018.Q628018.13326841347285@bugs.debian.org>\r
+X-Loop: owner@bugs.debian.org\r
+X-Debian-PR-Message: followup 628018\r
+X-Debian-PR-Package: notmuch\r
+X-Debian-PR-Keywords: \r
+X-Debian-PR-Source: notmuch\r
+Received: via spool by 628018-quiet@bugs.debian.org\r
+ id=Q628018.13326841347285          (code Q ref 628018); Sun,\r
+ 25 Mar 2012 14:29:45 +0000\r
+Received: (at 628018-quiet) by bugs.debian.org; 25 Mar 2012 14:02:14 +0000\r
+X-Spam-Checker-Version: SpamAssassin 3.3.1-bugs.debian.org_2005_01_02\r
+       (2010-03-16) on busoni.debian.org\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-8.4 required=4.0\r
+ tests=BAYES_00,FOURLA,FROMDEVELOPER,\r
+       IMPRONONCABLE_2,MONEY,MURPHY_DRUGS_REL8,PGPSIGNATURE,STOCKLIKE autolearn=ham\r
+       version=3.3.1-bugs.debian.org_2005_01_02\r
+X-Spam-Bayes: score:0.0000 Tokens: new, 148; hammy, 151; neutral, 665;\r
+ spammy,       0. spammytokens: hammytokens:0.000-+--H*c:pgp-sha256,\r
+ 0.000-+--manpage,     0.000-+--H*u:1.5.21, 0.000-+--H*UA:1.5.21,\r
+ 0.000-+--H*u:2010-09-15\r
+Received: from upsilon.hackadomia.org ([91.121.245.170])       by\r
+ busoni.debian.org with esmtp (Exim 4.72)      (envelope-from <zack@upsilon.cc>)\r
+ id 1SBo15-0001rp-N4   for 628018-quiet@bugs.debian.org; Sun, 25 Mar 2012\r
+ 14:02:05 +0000\r
+Received: from usha.takhisis.invalid\r
+ (did75-22-78-236-196-47.fbx.proxad.net [78.236.196.47])       by\r
+ upsilon.hackadomia.org (Postfix) with ESMTPSA id 41A3A1012D;  Sun,\r
+ 25 Mar 2012 16:01:52 +0200 (CEST)\r
+Received: by usha.takhisis.invalid (Postfix, from userid 1000) id\r
+ B01B5681E70; Sun, 25 Mar 2012 16:01:51 +0200 (CEST)\r
+Date: Sun, 25 Mar 2012 16:01:51 +0200\r
+From: Stefano Zacchiroli <zack@debian.org>\r
+To: notmuch@notmuchmail.org\r
+CC: 628018-quiet@bugs.debian.org, David Bremner <bremner@debian.org>,\r
+ Ben Boeckel <mathstuf@gmail.com>\r
+Message-ID: <20120325140151.GA12546@upsilon.cc>\r
+References: <87iphszuv1.fsf@zancas.localnet>\r
+MIME-Version: 1.0\r
+Content-Type: multipart/signed; micalg=pgp-sha256;\r
+ protocol="application/pgp-signature";\r
+ boundary="CdrF4e02JqNVZeln"\r
+Content-Disposition: inline\r
+In-Reply-To: <87iphszuv1.fsf@zancas.localnet>\r
+User-Agent: Mutt/1.5.21 (2010-09-15)\r
+Delivered-To: notmuch@packages.qa.debian.org\r
+Precedence: list\r
+X-Loop: notmuch@packages.qa.debian.org\r
+X-Debian: PTS\r
+X-Debian-Package: notmuch\r
+X-PTS-Package: notmuch\r
+X-PTS-Keyword: bts\r
+List-Unsubscribe: <mailto:pts@qa.debian.org?body=unsubscribe%20notmuch>\r
+Resent-Sender: Debian QA <qa@quantz.debian.org>\r
+X-Spam-Score: 0.0\r
+X-Spam_bar: /\r
+\r
+\r
+--CdrF4e02JqNVZeln\r
+Content-Type: multipart/mixed; boundary="M9NhX3UHpAaciwkO"\r
+Content-Disposition: inline\r
+\r
+\r
+--M9NhX3UHpAaciwkO\r
+Content-Type: text/plain; charset=iso-8859-1\r
+Content-Disposition: inline\r
+Content-Transfer-Encoding: quoted-printable\r
+\r
+[ please Cc:-me on follow-ups, as I'm not subscribed to the\r
+  notmuch@notmuchmail.org mailing list ]\r
+\r
+On Sun, Mar 25, 2012 at 10:13:38AM -0300, David Bremner wrote:\r
+> In the mean time, we at least have a contrib directory, and I think\r
+> mutt-notmuch would be welcome there. Could you (or somebody) make a\r
+> reasonable size patch series that adds it to contrib/mutt-notmuch\r
+> against current master. The patch series should be sent to the\r
+> upstream mailing list notmuch@notmuchmail.org for review.\r
+\r
+Hi David, thanks for the tip.\r
+\r
+Dear notmuch list, please find attached a proposed patch that add a new\r
+contrib utility called mutt-notmuch for integration with Mutt. Its full\r
+rationale can be found in the contained README. Background for this\r
+submission, including previous discussions to ship mutt-notmuch as part\r
+of notmuch, can be found at\r
+http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=3D628018\r
+\r
+I welcome your comments on how to adapt the patch to your preferences\r
+for contrib/, err, contributions.\r
+\r
+> On the debian side your patch series could also include the necessary\r
+> changes to make a new binary package.\r
+\r
+I'll be pleased to do so when/if mutt-notmuch is accepted in contrib/,\r
+just out of general laziness for potentially useless work :-)\r
+\r
+Thanks,\r
+Cheers.\r
+--=20\r
+Stefano Zacchiroli     zack@{upsilon.cc,pps.jussieu.fr,debian.org} . o .\r
+Ma=EEtre de conf=E9rences   ......   http://upsilon.cc/zack   ......   . . o\r
+Debian Project Leader    .......   @zack on identi.ca   .......    o o o\r
+=AB the first rule of tautology club is the first rule of tautology club =BB\r
+\r
+--M9NhX3UHpAaciwkO\r
+Content-Type: text/x-diff; charset=iso-8859-1\r
+Content-Disposition: attachment; filename="0001-contrib-new-utility-mutt-notmuch-for-Mutt-integratio.patch"\r
+Content-Transfer-Encoding: quoted-printable\r
+\r
+=46rom 8f5be32912920c2c5eca7084885c0e2498540311 Mon Sep 17 00:00:00 2001\r
+=46rom: Stefano Zacchiroli <zack@upsilon.cc>\r
+Date: Sun, 25 Mar 2012 15:55:44 +0200\r
+Subject: [PATCH] contrib: new utility mutt-notmuch for Mutt integration\r
+\r
+---\r
+ contrib/mutt-notmuch/Makefile       |   12 ++\r
+ contrib/mutt-notmuch/README         |   58 +++++++++\r
+ contrib/mutt-notmuch/mutt-notmuch   |  234 +++++++++++++++++++++++++++++++=\r
+++++\r
+ contrib/mutt-notmuch/mutt-notmuch.1 |  210 +++++++++++++++++++++++++++++++\r
+ 4 files changed, 514 insertions(+), 0 deletions(-)\r
+ create mode 100644 contrib/mutt-notmuch/Makefile\r
+ create mode 100644 contrib/mutt-notmuch/README\r
+ create mode 100755 contrib/mutt-notmuch/mutt-notmuch\r
+ create mode 100644 contrib/mutt-notmuch/mutt-notmuch.1\r
+\r
+diff --git a/contrib/mutt-notmuch/Makefile b/contrib/mutt-notmuch/Makefile\r
+new file mode 100644\r
+index 0000000..b78953d\r
+--- /dev/null\r
++++ b/contrib/mutt-notmuch/Makefile\r
+@@ -0,0 +1,12 @@\r
++NAME =3D mutt-notmuch\r
++\r
++all: $(NAME) $(NAME).1\r
++\r
++$(NAME).1: $(NAME)\r
++      pod2man $< > $@\r
++\r
++README.html: README\r
++      markdown $< > $@\r
++\r
++clean:\r
++      rm -f mutt-notmuch.1 README.html\r
+diff --git a/contrib/mutt-notmuch/README b/contrib/mutt-notmuch/README\r
+new file mode 100644\r
+index 0000000..e72aa91\r
+--- /dev/null\r
++++ b/contrib/mutt-notmuch/README\r
+@@ -0,0 +1,58 @@\r
++mutt-notmuch: Notmuch (of a) helper for Mutt\r
++=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=\r
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\r
++\r
++mutt-notmuch provide integration among the [Mutt] [1] mail user agent and =\r
+the\r
++[Notmuch] [2] mail indexer.\r
++\r
++mutt-notmuch offer two basic integration features. The first one is the ab=\r
+ility\r
++of stating a **search query interactively** and then jump to a fresh Maild=\r
+ir\r
++containing its search results only. The second one is the ability to\r
++**reconstruct threads on the fly** starting from the currently highlighted\r
++mail, which comes handy when a thread has been split across different mail=\r
+dirs,\r
++archived, or the like.\r
++\r
++mutt-notmuch enables to trigger mail searches via a Mutt macro (F8 being my\r
++choice) and reconstruct threads via another (F9). Check the manpage for the\r
++2-liner configuration snippet for your ~/.muttrc.\r
++\r
++A [blog style introduction] [3] to mutt-notmuch is available and includes =\r
+some\r
++more rationale for its existence.\r
++\r
++Arguably, some of the logics of mutt-notmuch could disappear by adding sup=\r
+port\r
++for a --output=3Dsymlinks flag to notmuch.\r
++\r
++\r
++[1]: http://www.mutt.org/\r
++[2]: http://notmuchmail.org/\r
++[3]: http://upsilon.cc/~zack/blog/posts/2011/01/how_to_use_Notmuch_with_Mu=\r
+tt/\r
++\r
++\r
++Requirements\r
++------------\r
++\r
++To *run* mutt-notmuch you will need Perl with the following libraries:\r
++\r
++- Mail::Box <http://search.cpan.org/~markov/Mail-Box/>\r
++  (Debian package: libmail-box-perl)\r
++- Mail::Internet <http://search.cpan.org/~markov/MailTools/>\r
++  (Debian package: libmailtools-perl)\r
++- String::ShellQuote <http://search.cpan.org/~rosch/String-ShellQuote/Shel=\r
+lQuote.pm>\r
++  (Debian package: libstring-shellquote-perl)\r
++- Term::ReadLine <http://search.cpan.org/~hayashi/Term-ReadLine-Gnu/>\r
++  (Debian package: libterm-readline-gnu-perl)\r
++\r
++To *build* mutt-notmuch documentation you will need:\r
++\r
++- pod2man (coming with Perl) to generate the manpage\r
++- markdown to generate README.html out of this file\r
++\r
++\r
++License\r
++-------\r
++\r
++mutt-notmuch is copyright (C) 2011-2012 Stefano Zacchiroli <zack@upsilon.c=\r
+c>.\r
++\r
++mutt-notmuch is released under the terms of the GNU General Public License\r
++(GPL), version 3 or above. A copy of the license is available online at\r
++<http://www.gnu.org/licenses/>.\r
++\r
+diff --git a/contrib/mutt-notmuch/mutt-notmuch b/contrib/mutt-notmuch/mutt-=\r
+notmuch\r
+new file mode 100755\r
+index 0000000..31cb539\r
+--- /dev/null\r
++++ b/contrib/mutt-notmuch/mutt-notmuch\r
+@@ -0,0 +1,234 @@\r
++#!/usr/bin/perl -w\r
++#\r
++# mutt-notmuch - notmuch (of a) helper for Mutt\r
++#\r
++# Copyright: =A9 2011-2012 Stefano Zacchiroli <zack@upsilon.cc>=20\r
++# License: GNU General Public License (GPL), version 3 or above\r
++#\r
++# See the bottom of this file for more documentation.\r
++# A manpage can be obtained by running "pod2man mutt-notmuch > mutt-notmuc=\r
+h.1"\r
++\r
++use strict;\r
++use warnings;\r
++\r
++use File::Path;\r
++use Getopt::Long qw(:config no_getopt_compat);\r
++use Mail::Internet;\r
++use Mail::Box::Maildir;\r
++use Pod::Usage;\r
++use String::ShellQuote;\r
++use Term::ReadLine;\r
++\r
++\r
++# create an empty maildir (if missing) or empty an existing maildir"\r
++sub empty_maildir($) {\r
++    my ($maildir) =3D (@_);\r
++    rmtree($maildir) if (-d $maildir);\r
++    my $folder =3D new Mail::Box::Maildir(folder =3D> $maildir,\r
++                                      create =3D> 1);\r
++    $folder->close();\r
++}\r
++\r
++# search($maildir, $query)\r
++# search mails according to $query with notmuch; store results in $maildir\r
++sub search($$) {\r
++    my ($maildir, $query) =3D @_;\r
++    $query =3D shell_quote($query);\r
++\r
++    empty_maildir($maildir);\r
++    system("notmuch search --output=3Dfiles $query"\r
++         . " | sed -e 's: :\\\\ :g'"\r
++         . " | xargs --no-run-if-empty ln -s -t $maildir/cur/");\r
++}\r
++\r
++sub prompt($$) {\r
++    my ($text, $default) =3D @_;\r
++    my $query =3D "";\r
++    my $term =3D Term::ReadLine->new( "mutt-notmuch" );\r
++    $term->ornaments( 0 );\r
++    $term->unbind_key( ord( "\t" ) );\r
++    $term->MinLine( 3 );\r
++    if ($ENV{MUTT_NOTMUCH_HISTFILE} && -r "$ENV{MUTT_NOTMUCH_HISTFILE}") {\r
++      $term->ReadHistory("$ENV{MUTT_NOTMUCH_HISTFILE}");\r
++    } elsif (-r "$ENV{HOME}/.mutt-notmuch.history") {\r
++      $term->ReadHistory("$ENV{HOME}/.mutt-notmuch.history");\r
++    }\r
++    while (1) {\r
++      chomp($query =3D $term->readline($text, $default));\r
++      if ($query eq "?") {\r
++          system("man", "notmuch");\r
++      } else {\r
++       if (!$ENV{MUTT_NOTMUCH_HISTFILE} ||\r
++           !$term->WriteHistory("$ENV{MUTT_NOTMUCH_HISTFILE}")) {\r
++         $term->WriteHistory("$ENV{HOME}/.mutt-notmuch.history");\r
++       }\r
++          return $query;\r
++      }\r
++    }\r
++}\r
++\r
++sub get_message_id() {\r
++    my $mail =3D Mail::Internet->new(\*STDIN);\r
++    $mail->head->get("message-id") =3D~ /^<(.*)>$/;   # get message-id\r
++    return $1;\r
++}\r
++\r
++sub search_action($$@) {\r
++    my ($interactive, $results_dir, @params) =3D @_;\r
++\r
++    if (! $interactive) {\r
++      search($results_dir, join(' ', @params));\r
++    } else {\r
++      my $query =3D prompt("search ('?' for man): ", join(' ', @params));\r
++      if ($query ne "") {\r
++          search($results_dir,$query);\r
++      }\r
++    }\r
++}\r
++\r
++sub thread_action(@) {\r
++    my ($results_dir, @params) =3D @_;\r
++    my $mid =3D get_message_id();\r
++    my $tid =3D `notmuch search --output=3Dthreads id:$mid`;# get thread id\r
++    chomp($tid);\r
++\r
++    search($results_dir, $tid);\r
++}\r
++\r
++sub tag_action(@) {\r
++    my $mid =3D get_message_id();\r
++\r
++    system("notmuch tag "\r
++         . shell_quote(join(' ', @_))\r
++         . " id:$mid");\r
++}\r
++\r
++sub die_usage() {\r
++    my %podflags =3D ( "verbose" =3D> 1,\r
++                  "exitval" =3D> 2 );\r
++    pod2usage(%podflags);\r
++}\r
++\r
++sub main() {\r
++    my $results_dir =3D "$ENV{HOME}/.cache/mutt_results";\r
++    my $interactive =3D 0;\r
++    my $help_needed =3D 0;\r
++\r
++    my $getopt =3D GetOptions(\r
++      "h|help" =3D> \$help_needed,\r
++      "o|output-dir=3Ds" =3D> \$results_dir,\r
++      "p|prompt" =3D> \$interactive);\r
++    if (! $getopt || $#ARGV < 0) { die_usage() };\r
++    my ($action, @params) =3D ($ARGV[0], @ARGV[1..$#ARGV]);\r
++\r
++    foreach my $param (@params) {\r
++      $param =3D~ s/folder:=3D/folder:/g;\r
++    }\r
++\r
++    if ($help_needed) {\r
++      die_usage();\r
++    } elsif ($action eq "search" && $#ARGV =3D=3D 0 && ! $interactive) {\r
++      print STDERR "Error: no search term provided\n\n";\r
++      die_usage();\r
++    } elsif ($action eq "search") {\r
++      search_action($interactive, $results_dir, @params);\r
++    } elsif ($action eq "thread") {\r
++      thread_action($results_dir, @params);\r
++    } elsif ($action eq "tag") {\r
++      tag_action(@params);\r
++    } else {\r
++      die_usage();\r
++    }\r
++}\r
++\r
++main();\r
++\r
++__END__\r
++\r
++=3Dhead1 NAME\r
++\r
++mutt-notmuch - notmuch (of a) helper for Mutt\r
++\r
++=3Dhead1 SYNOPSIS\r
++\r
++=3Dover\r
++\r
++=3Ditem B<mutt-notmuch> [I<OPTION>]... search [I<SEARCH-TERM>]...\r
++\r
++=3Ditem B<mutt-notmuch> [I<OPTION>]... thread < I<MAIL>\r
++\r
++=3Ditem B<mutt-notmuch> [I<OPTION>]... tag [I<TAGS>]... < I<MAIL>\r
++\r
++=3Dback\r
++\r
++=3Dhead1 DESCRIPTION\r
++\r
++mutt-notmuch is a frontend to the notmuch mail indexer capable of populati=\r
+ng\r
++maildir with search results.\r
++\r
++=3Dhead1 OPTIONS\r
++\r
++=3Dover 4\r
++\r
++=3Ditem -o DIR\r
++\r
++=3Ditem --output-dir DIR\r
++\r
++Store search results as (symlink) messages under maildir DIR. Beware: DIR =\r
+will\r
++be overwritten. (Default: F<~/.cache/mutt_results/>)\r
++\r
++=3Ditem -p\r
++\r
++=3Ditem --prompt\r
++\r
++Instead of using command line search terms, prompt the user for them (only=\r
+ for\r
++"search").\r
++\r
++=3Ditem -h\r
++\r
++=3Ditem --help\r
++\r
++Show usage information and exit.\r
++\r
++=3Dback\r
++\r
++=3Dhead1 INTEGRATION WITH MUTT\r
++\r
++mutt-notmuch can be used to integrate notmuch with the Mutt mail user agent\r
++(unsurprisingly, given the name). To that end, you should define the follo=\r
+wing\r
++macros in your F<~/.muttrc> (replacing F<~/bin/mutt-notmuch> for the actual\r
++location of mutt-notmuch on your system):\r
++\r
++    macro index <F8> \\r
++          "<enter-command>unset wait_key<enter><shell-escape>~/bin/mutt-no=\r
+tmuch --prompt search<enter><change-folder-readonly>~/.cache/mutt_results<e=\r
+nter>" \\r
++          "search mail (using notmuch)"\r
++    macro index <F9> \\r
++          "<enter-command>unset wait_key<enter><pipe-message>~/bin/mutt-no=\r
+tmuch thread<enter><change-folder-readonly>~/.cache/mutt_results<enter><ent=\r
+er-command>set wait_key<enter>" \\r
++          "search and reconstruct owning thread (using notmuch)"\r
++    macro index <F6> \\r
++          "<enter-command>unset wait_key<enter><pipe-message>~/bin/mutt-no=\r
+tmuch tag -inbox<enter>" \\r
++          "remove message from inbox (using notmuch)"\r
++\r
++The first macro (activated by <F8>) will prompt the user for notmuch search\r
++terms and then jump to a temporary maildir showing search results. The sec=\r
+ond\r
++macro (activated by <F9>) will reconstruct the thread corresponding to the\r
++current mail and show it as search results. The third macro (activated by =\r
+<F6>)\r
++removes the tag C<inbox> from the current message; by changing C<-inbox> t=\r
+his\r
++macro may be customised to add or remove tags appropriate to the users not=\r
+much\r
++work-flow.\r
++\r
++To keep notmuch index current you should then periodically run C<notmuch\r
++new>. Depending on your local mail setup, you might want to do that via cr=\r
+on,\r
++as a hook triggered by mail retrieval, etc.\r
++\r
++=3Dhead1 SEE ALSO\r
++\r
++mutt(1), notmuch(1)\r
++\r
++=3Dhead1 AUTHOR\r
++\r
++Copyright: (C) 2011-2012 Stefano Zacchiroli <zack@upsilon.cc>\r
++\r
++License: GNU General Public License (GPL), version 3 or higher\r
++\r
++=3Dcut\r
+diff --git a/contrib/mutt-notmuch/mutt-notmuch.1 b/contrib/mutt-notmuch/mut=\r
+t-notmuch.1\r
+new file mode 100644\r
+index 0000000..fe5e653\r
+--- /dev/null\r
++++ b/contrib/mutt-notmuch/mutt-notmuch.1\r
+@@ -0,0 +1,210 @@\r
++.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16)\r
++.\"\r
++.\" Standard preamble:\r
++.\" =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=\r
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=\r
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\r
++.de Sp \" Vertical space (when we can't use .PP)\r
++.if t .sp .5v\r
++.if n .sp\r
++..\r
++.de Vb \" Begin verbatim text\r
++.ft CW\r
++.nf\r
++.ne \\$1\r
++..\r
++.de Ve \" End verbatim text\r
++.ft R\r
++.fi\r
++..\r
++.\" Set up some character translations and predefined strings.  \*(-- will\r
++.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left\r
++.\" double quote, and \*(R" will give a right double quote.  \*(C+ will\r
++.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and\r
++.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,\r
++.\" nothing in troff, for use with C<>.\r
++.tr \(*W-\r
++.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'\r
++.ie n \{\\r
++.    ds -- \(*W-\r
++.    ds PI pi\r
++.    if (\n(.H=3D4u)&(1m=3D24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo =\r
+10 pitch\r
++.    if (\n(.H=3D4u)&(1m=3D20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo =\r
+12 pitch\r
++.    ds L" ""\r
++.    ds R" ""\r
++.    ds C` ""\r
++.    ds C' ""\r
++'br\}\r
++.el\{\\r
++.    ds -- \|\(em\|\r
++.    ds PI \(*p\r
++.    ds L" ``\r
++.    ds R" ''\r
++'br\}\r
++.\"\r
++.\" Escape single quotes in literal strings from groff's Unicode transform.\r
++.ie \n(.g .ds Aq \(aq\r
++.el       .ds Aq '\r
++.\"\r
++.\" If the F register is turned on, we'll generate index entries on stderr=\r
+ for\r
++.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index\r
++.\" entries marked with X<> in POD.  Of course, you'll have to process the\r
++.\" output yourself in some meaningful fashion.\r
++.ie \nF \{\\r
++.    de IX\r
++.    tm Index:\\$1\t\\n%\t"\\$2"\r
++..\r
++.    nr % 0\r
++.    rr F\r
++.\}\r
++.el \{\\r
++.    de IX\r
++..\r
++.\}\r
++.\"\r
++.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).\r
++.\" Fear.  Run.  Save yourself.  No user-serviceable parts.\r
++.    \" fudge factors for nroff and troff\r
++.if n \{\\r
++.    ds #H 0\r
++.    ds #V .8m\r
++.    ds #F .3m\r
++.    ds #[ \f1\r
++.    ds #] \fP\r
++.\}\r
++.if t \{\\r
++.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)\r
++.    ds #V .6m\r
++.    ds #F 0\r
++.    ds #[ \&\r
++.    ds #] \&\r
++.\}\r
++.    \" simple accents for nroff and troff\r
++.if n \{\\r
++.    ds ' \&\r
++.    ds ` \&\r
++.    ds ^ \&\r
++.    ds , \&\r
++.    ds ~ ~\r
++.    ds /\r
++.\}\r
++.if t \{\\r
++.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"\r
++.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'\r
++.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'\r
++.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'\r
++.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'\r
++.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'\r
++.\}\r
++.    \" troff and (daisy-wheel) nroff accents\r
++.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h=\r
+'|\\n:u'\v'\*(#V'\r
++.ds 8 \h'\*(#H'\(*b\h'-\*(#H'\r
++.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\=\r
+\n:u'\*(#]\r
++.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'\r
++.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'\r
++.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]\r
++.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]\r
++.ds ae a\h'-(\w'a'u*4/10)'e\r
++.ds Ae A\h'-(\w'A'u*4/10)'E\r
++.    \" corrections for vroff\r
++.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'\r
++.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'\r
++.    \" for low resolution devices (crt and lpr)\r
++.if \n(.H>23 .if \n(.V>19 \\r
++\{\\r
++.    ds : e\r
++.    ds 8 ss\r
++.    ds o a\r
++.    ds d- d\h'-1'\(ga\r
++.    ds D- D\h'-1'\(hy\r
++.    ds th \o'bp'\r
++.    ds Th \o'LP'\r
++.    ds ae ae\r
++.    ds Ae AE\r
++.\}\r
++.rm #[ #] #H #V #F C\r
++.\" =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=\r
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=\r
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\r
++.\"\r
++.IX Title "MUTT-NOTMUCH 1"\r
++.TH MUTT-NOTMUCH 1 "2012-03-25" "perl v5.14.2" "User Contributed Perl Docu=\r
+mentation"\r
++.\" For nroff, turn off justification.  Always turn off hyphenation; it ma=\r
+kes\r
++.\" way too many mistakes in technical documents.\r
++.if n .ad l\r
++.nh\r
++.SH "NAME"\r
++mutt\-notmuch \- notmuch (of a) helper for Mutt\r
++.SH "SYNOPSIS"\r
++.IX Header "SYNOPSIS"\r
++.IP "\fBmutt-notmuch\fR [\fI\s-1OPTION\s0\fR]... search [\fISEARCH-TERM\fR=\r
+]..." 4\r
++.IX Item "mutt-notmuch [OPTION]... search [SEARCH-TERM]..."\r
++.PD 0\r
++.IP "\fBmutt-notmuch\fR [\fI\s-1OPTION\s0\fR]... thread < \fI\s-1MAIL\s0\f=\r
+R" 4\r
++.IX Item "mutt-notmuch [OPTION]... thread < MAIL"\r
++.IP "\fBmutt-notmuch\fR [\fI\s-1OPTION\s0\fR]... tag [\fI\s-1TAGS\s0\fR]..=\r
+=2E < \fI\s-1MAIL\s0\fR" 4\r
++.IX Item "mutt-notmuch [OPTION]... tag [TAGS]... < MAIL"\r
++.PD\r
++.SH "DESCRIPTION"\r
++.IX Header "DESCRIPTION"\r
++mutt-notmuch is a frontend to the notmuch mail indexer capable of populati=\r
+ng\r
++maildir with search results.\r
++.SH "OPTIONS"\r
++.IX Header "OPTIONS"\r
++.IP "\-o \s-1DIR\s0" 4\r
++.IX Item "-o DIR"\r
++.PD 0\r
++.IP "\-\-output\-dir \s-1DIR\s0" 4\r
++.IX Item "--output-dir DIR"\r
++.PD\r
++Store search results as (symlink) messages under maildir \s-1DIR\s0. Bewar=\r
+e: \s-1DIR\s0 will\r
++be overwritten. (Default: \fI~/.cache/mutt_results/\fR)\r
++.IP "\-p" 4\r
++.IX Item "-p"\r
++.PD 0\r
++.IP "\-\-prompt" 4\r
++.IX Item "--prompt"\r
++.PD\r
++Instead of using command line search terms, prompt the user for them (only=\r
+ for\r
++\&\*(L"search\*(R").\r
++.IP "\-h" 4\r
++.IX Item "-h"\r
++.PD 0\r
++.IP "\-\-help" 4\r
++.IX Item "--help"\r
++.PD\r
++Show usage information and exit.\r
++.SH "INTEGRATION WITH MUTT"\r
++.IX Header "INTEGRATION WITH MUTT"\r
++mutt-notmuch can be used to integrate notmuch with the Mutt mail user agent\r
++(unsurprisingly, given the name). To that end, you should define the follo=\r
+wing\r
++macros in your \fI~/.muttrc\fR (replacing \fI~/bin/mutt\-notmuch\fR for th=\r
+e actual\r
++location of mutt-notmuch on your system):\r
++.PP\r
++.Vb 9\r
++\&    macro index <F8> \e\r
++\&          "<enter\-command>unset wait_key<enter><shell\-escape>~/bin/mut=\r
+t\-notmuch \-\-prompt search<enter><change\-folder\-readonly>~/.cache/mutt_=\r
+results<enter>" \e\r
++\&          "search mail (using notmuch)"\r
++\&    macro index <F9> \e\r
++\&          "<enter\-command>unset wait_key<enter><pipe\-message>~/bin/mut=\r
+t\-notmuch thread<enter><change\-folder\-readonly>~/.cache/mutt_results<ent=\r
+er><enter\-command>set wait_key<enter>" \e\r
++\&          "search and reconstruct owning thread (using notmuch)"\r
++\&    macro index <F6> \e\r
++\&          "<enter\-command>unset wait_key<enter><pipe\-message>~/bin/mut=\r
+t\-notmuch tag \-inbox<enter>" \e\r
++\&          "remove message from inbox (using notmuch)"\r
++.Ve\r
++.PP\r
++The first macro (activated by <F8>) will prompt the user for notmuch search\r
++terms and then jump to a temporary maildir showing search results. The sec=\r
+ond\r
++macro (activated by <F9>) will reconstruct the thread corresponding to the\r
++current mail and show it as search results. The third macro (activated by =\r
+<F6>)\r
++removes the tag \f(CW\*(C`inbox\*(C'\fR from the current message; by chang=\r
+ing \f(CW\*(C`\-inbox\*(C'\fR this\r
++macro may be customised to add or remove tags appropriate to the users not=\r
+much\r
++work-flow.\r
++.PP\r
++To keep notmuch index current you should then periodically run \f(CW\*(C`n=\r
+otmuch\r
++new\*(C'\fR. Depending on your local mail setup, you might want to do that=\r
+ via cron,\r
++as a hook triggered by mail retrieval, etc.\r
++.SH "SEE ALSO"\r
++.IX Header "SEE ALSO"\r
++\&\fImutt\fR\|(1), \fInotmuch\fR\|(1)\r
++.SH "AUTHOR"\r
++.IX Header "AUTHOR"\r
++Copyright: (C) 2011\-2012 Stefano Zacchiroli <zack@upsilon.cc>\r
++.PP\r
++License: \s-1GNU\s0 General Public License (\s-1GPL\s0), version 3 or high=\r
+er\r
+--=20\r
+1.7.9.1\r
+\r
+\r
+--M9NhX3UHpAaciwkO--\r
+\r
+--CdrF4e02JqNVZeln\r
+Content-Type: application/pgp-signature; name="signature.asc"\r
+Content-Description: Digital signature\r
+\r
+-----BEGIN PGP SIGNATURE-----\r
+Version: GnuPG v1.4.12 (GNU/Linux)\r
+\r
+iQIVAwUBT28lTJwxUDxthmOWAQi4HBAAhTUufin73Rp4vQKKJWQPorfz/ytWL4kd\r
+rM2i+gsL+onUGjpiLWhqAl/50qtiJzYoq4OyauRaqc3lHedlv63I+9l5RZwdaosP\r
+dYClOnqyJizyfEuFqEXIU+39lmY92HhQuaFV+s2hHJjpVdk14+majInT5VDHykw0\r
+gP9YiqEbiki22mLX8nNrSEqQ6nNjgj9602airLn5HCWHUA3VfsB6fOMbzAswFjch\r
+FmuVfs5w8JtCvYvzThMTXjg2cfi1EHuWqElu+F61O8zZBb8fMHPTj+0VHwLyeWx6\r
+iynn/wT7bm+t0unUuxfA89VjrACxuznCPJfRYDBi+GVu100jO+fG0JHmnYFvnVXb\r
+pIHFG1DW/L8QuwkFUbA+dX5B/TrF0F71fFVUvur65qO2aSSZexsIPXIwhec4Xg2l\r
+Bqt2qNzN47p4y/cbacBn452bxr8NcMBgDyEnFcd0U99Xhgl8G7G20IFeasJEqbZn\r
+GiHm4gICNs4Rgho3D/vVI7tmi/XU8K/bZ9D2hQBB4AN8N7+WElzSQCX1koa3EWuc\r
+JHuEfeJbEwdrDa5QYg/+3ZyE0T9KXEElPTV94dKAm/wZ9RCzysH3X2aL+9bXaSzs\r
+Hh3iJsZjwn9PtJn7ofoKVRYW3DOTdNnkzjlJHEvSy9NsEOYmnNGKcD0d/8M0OdEk\r
+R9alqj5Lw5o=\r
+=y9sK\r
+-----END PGP SIGNATURE-----\r
+\r
+--CdrF4e02JqNVZeln--\r
+\r
+\r
+\r
+\r
+--=-=-=--\r