mutt-notmuch blog post
authorStefano Zacchiroli <zack@upsilon.cc>
Thu, 3 Feb 2011 18:05:25 +0000 (19:05 +0100)
committerStefano Zacchiroli <zack@upsilon.cc>
Thu, 3 Feb 2011 18:05:25 +0000 (19:05 +0100)
blog/posts/2009/10/mail_indexing_for_mutt.mdwn
blog/posts/2011/01/how_to_use_Notmuch_with_Mutt.mdwn [new file with mode: 0644]
blog/posts/2011/01/how_to_use_Notmuch_with_Mutt/mutt-notmuch [new file with mode: 0755]
blog/posts/2011/01/how_to_use_Notmuch_with_Mutt/mutt-notmuch.1 [new file with mode: 0644]
blog/posts/2011/01/how_to_use_Notmuch_with_Mutt/mutt-notmuch.1.html [new file with mode: 0644]
hacking/software.mdwn

index f1e8b70..5cdf0d6 100644 (file)
@@ -79,4 +79,9 @@ be a <acronym title="Mail User Agent">MUA</acronym>, whereas I'm perfectly fine
 with Mutt, I just need from time to time to integrate it with other components
 of my daily work flow.
 
+**Update:** (30/01/2011) I've now tried Notmuch and switched to it without
+looking back. I've written about it in a
+[[separate post|2011/01/how_to_use_Notmuch_with_Mutt]], including tips on how
+to integrate Notmuch with Mutt.
+
 [[!tag lang/english planet-debian mutt gtd]]
diff --git a/blog/posts/2011/01/how_to_use_Notmuch_with_Mutt.mdwn b/blog/posts/2011/01/how_to_use_Notmuch_with_Mutt.mdwn
new file mode 100644 (file)
index 0000000..6c820da
--- /dev/null
@@ -0,0 +1,62 @@
+# Mutt mail indexing on steroids!
+
+I've been using external mail indexing with [Mutt](http://www.mutt.org) for
+quite a while now. Before now I haven't given
+[Notmuch](http://notmuchmail.org/) a try, as it seemed *too much* experimental
+at the time of my initial
+[[review of mail indexing tools|2009/10/mail_indexing_for_mutt]].
+
+As there is nothing better than a long oversea flight to perpetrate new hacks,
+I've now not only tested it, but also **switched to Notmuch** without looking
+back at [maildir-utils](http://code.google.com/p/mu0/) for a split second.
+
+Getting started with Notmuch is trivial:
+
+* Notmuch is [[!debpkgsid packaged]] in Debian (and maintained by upstream
+  author, thanks!)
+* `notmuch setup` asks a few questions about the user and then prepare a
+  template `~/.notmuch-config`, which is good enough to start
+* `notmuch new` does a first run of indexing (which might take a while,
+  depending on the size of your maildirs)
+
+Some performance figures: (1) the size of the index is a bit larger than the
+size of the mails (on my laptop: 535 Mb of index vs 375 Mb of mails stored in
+60 maildirs); (2) even if the underlying indexing engine is the same (Xapian)
+as maildir-utils, Notmuch is much faster. With my setup it is so fast that I've
+added it as a hook triggered by offlineimap at the end of each synchronization:
+
+        zack@usha:~$ grep -B 1 hook .offlineimaprc
+        [Account Upsilon]
+        postsynchook = notmuch new
+
+With the big round of new mail downloaded in the morning, it hardly takes more
+than a few seconds to update Notmuch index, while with other periodic downloads
+Notmuch almost invariably reports "... in almost no time" (i.e. less than 1
+second).
+
+## Integrating Notmuch with Mutt
+
+The basic integration I want between Mutt and a mail indexer is the ability of
+stating a **search query** interactively and then jump to a **fresh Maildir
+containing search results** only. Additionally, given that Notmuch has neat
+**thread reconstruction** abilities, I also want to be able to reconstruct on
+the fly the thread corresponding to the currently highlighted mail: it comes
+handy when a thread has been split across different maildirs, archived, or the
+like.
+
+To that end, I've cooked up a little helper, called [[mutt-notmuch]], that
+enables to trigger mail searches via a Mutt macro (F8 being my choice) and
+reconstruct threads via another (F9). Check the [[manpage|mutt-notmuch.1.html]]
+for the 2-liner configuration snippet for your `~/.muttrc`.
+
+Arguably, some of the logics of mutt-notmuch could disappear by adding support
+for a `--output=symlinks` flag to Notmuch. A bug report requesting that is
+pending: too bad oversea flights are not as good for accessing the Internet as
+they are for perpetrating hacks!
+
+### Download
+
+* [[mutt-notmuch]] - Notmuch (of a) helper for Mutt
+* [[mutt-notmuch.1]] ([[html|mutt-notmuch.1.html]])- mutt-notmuch manpage
+
+[[!tag lang/english planet-debian mutt notmuch hack]]
diff --git a/blog/posts/2011/01/how_to_use_Notmuch_with_Mutt/mutt-notmuch b/blog/posts/2011/01/how_to_use_Notmuch_with_Mutt/mutt-notmuch
new file mode 100755 (executable)
index 0000000..e1fe909
--- /dev/null
@@ -0,0 +1,189 @@
+#!/usr/bin/perl -w
+#
+# mutt-notmuch - notmuch (of a) helper for Mutt
+#
+# Copyright: © 2011 Stefano Zacchiroli <zack@upsilon.cc> 
+# License: GNU General Public License (GPL), version 3 or above
+#
+# See the bottom of this file for more documentation.
+# A manpage can be obtained by running "pod2man mutt-notmuch > mutt-notmuch.1"
+
+use strict;
+use warnings;
+
+use File::Path;
+use Getopt::Long;
+use Mail::Internet;
+use Mail::Box::Maildir;
+use Pod::Usage;
+
+
+# create an empty maildir (if missing) or empty an existing maildir"
+sub empty_maildir($) {
+    my ($maildir) = (@_);
+    rmtree($maildir) if (-d $maildir);
+    my $folder = new Mail::Box::Maildir(folder => $maildir,
+                                       create => 1);
+    $folder->close();
+}
+
+# search($maildir, $query)
+# search mails according to $query with notmuch; store results in $maildir
+sub search($$) {
+    my ($maildir, $query) = @_;
+
+    empty_maildir($maildir);
+    system("notmuch search --output=files $query"
+          . " | xargs --no-run-if-empty ln -s -t $maildir/cur/");
+}
+
+sub search_action($$@) {
+    my ($interactive, $results_dir, @params) = @_;
+
+    if (! $interactive) {
+       search($results_dir, join(' ', @params));
+    } else {
+       my $query = "";
+       my $done = 0;
+       while (! $done) {
+           print "search ('?' for man): ";
+           chomp($query = <STDIN>);
+           if ($query eq "?") {
+               system("man notmuch");
+           } elsif ($query eq "") {
+               $done = 1;      # quit doing nothing
+           } else {
+               search($results_dir, $query);
+               $done = 1;
+           }
+       }
+    }
+}
+
+sub thread_action(@) {
+    my ($results_dir, @params) = @_;
+
+    my $mail = Mail::Internet->new(\*STDIN);
+    $mail->head->get('message-id') =~ /^<(.*)>$/;      # get message-id
+    my $mid = $1;
+    my $tid = `notmuch search --output=threads id:$mid`;# get thread id
+    chomp($tid);
+
+    search($results_dir, $tid);
+}
+
+sub die_usage() {
+    my %podflags = ( "verbose" => 1,
+                   "exitval" => 2 );
+    pod2usage(%podflags);
+}
+
+sub main() {
+    my $results_dir = "$ENV{HOME}/.cache/mutt_results";
+    my $interactive = 0;
+    my $help_needed = 0;
+
+    my $getopt = GetOptions(
+       "h|help" => \$help_needed,
+       "o|output-dir=s" => \$results_dir,
+       "p|prompt" => \$interactive);
+    if (! $getopt || $#ARGV < 0) { die_usage() };
+    my ($action, @params) = ($ARGV[0], @ARGV[1..$#ARGV]);
+
+    if ($help_needed) {
+       die_usage();
+    } elsif ($action eq "search" && $#ARGV == 0 && ! $interactive) {
+       print STDERR "Error: no search term provided\n\n";
+       die_usage();
+    } elsif ($action eq "search") {
+       search_action($interactive, $results_dir, @params);
+    } elsif ($action eq "thread") {
+       thread_action($results_dir, @params);
+    } else {
+       die_usage();
+    }
+}
+
+main();
+
+__END__
+
+=head1 NAME
+
+mutt-notmuch - notmuch (of a) helper for Mutt
+
+=head1 SYNOPSIS
+
+=over
+
+=item B<mutt-notmuch> [I<OPTION>]... search [I<SEARCH-TERM>]...
+
+=item B<mutt-notmuch> [I<OPTION>]... thread < I<MAIL>
+
+=back
+
+=head1 DESCRIPTION
+
+mutt-notmuch is a frontend to the notmuch mail indexer capable of populating
+maildir with search results.
+
+=head1 OPTIONS
+
+=over 4
+
+=item -o DIR
+
+=item --output-dir DIR
+
+Store search results as (symlink) messages under maildir DIR. Beware: DIR will
+be overwritten. (Default: F<~/.cache/mutt_results/>)
+
+=item -p
+
+=item --prompt
+
+Instead of using command line search terms, prompt the user for them (only for
+"search").
+
+=item -h
+
+=item --help
+
+Show usage information and exit.
+
+=back
+
+=head1 INTEGRATION WITH MUTT
+
+mutt-notmuch can be used to integrate notmuch with the Mutt mail user agent
+(unsurprisingly, given the name). To that end, you should define the following
+macros in your F<~/.muttrc> (replacing F<~/bin/mutt-notmuch> for the actual
+location of mutt-notmuch on your system):
+
+    macro index <F8> \
+          "<enter-command>unset wait_key<enter><shell-escape>~/bin/mutt-notmuch --prompt search<enter><change-folder-readonly>~/.cache/mutt_results<enter>" \
+          "search mail (using notmuch)"
+    macro index <F9> \
+          "<enter-command>unset wait_key<enter><pipe-message>~/bin/mutt-notmuch thread<enter><change-folder-readonly>~/.cache/mutt_results<enter><enter-command>set wait_key<enter>" \
+          "search and reconstruct owning thread (using notmuch)"
+
+The first macro (activated by <F8>) will prompt the user for notmuch search
+terms and then jump to a temporary maildir showing search results. The second
+macro (activated by <F9>) will reconstruct the thread corresponding to the
+current mail and show it as search results.
+
+To keep notmuch index current you should then periodically run C<notmuch
+new>. Depending on your local mail setup, you might want to do that via cron,
+as a hook triggered by mail retrieval, etc.
+
+=head1 SEE ALSO
+
+mutt(1), notmuch(1)
+
+=head1 AUTHOR
+
+Copyright: (C) 2011 Stefano Zacchiroli <zack@upsilon.cc>
+
+License: GNU General Public License (GPL), version 3 or higher
+
+=cut
diff --git a/blog/posts/2011/01/how_to_use_Notmuch_with_Mutt/mutt-notmuch.1 b/blog/posts/2011/01/how_to_use_Notmuch_with_Mutt/mutt-notmuch.1
new file mode 100644 (file)
index 0000000..1cee77c
--- /dev/null
@@ -0,0 +1,202 @@
+.\" Automatically generated by Pod::Man 2.22 (Pod::Simple 3.07)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.ie \nF \{\
+.    de IX
+.    tm Index:\\$1\t\\n%\t"\\$2"
+..
+.    nr % 0
+.    rr F
+.\}
+.el \{\
+.    de IX
+..
+.\}
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "MUTT-NOTMUCH 1"
+.TH MUTT-NOTMUCH 1 "2011-01-25" "perl v5.10.1" "User Contributed Perl Documentation"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+mutt\-notmuch \- notmuch (of a) helper for Mutt
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.IP "\fBmutt-notmuch\fR [\fI\s-1OPTION\s0\fR]... search [\fISEARCH-TERM\fR]..." 4
+.IX Item "mutt-notmuch [OPTION]... search [SEARCH-TERM]..."
+.PD 0
+.IP "\fBmutt-notmuch\fR [\fI\s-1OPTION\s0\fR]... thread < \fI\s-1MAIL\s0\fR" 4
+.IX Item "mutt-notmuch [OPTION]... thread < MAIL"
+.PD
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+mutt-notmuch is a frontend to the notmuch mail indexer capable of populating
+maildir with search results.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+.IP "\-o \s-1DIR\s0" 4
+.IX Item "-o DIR"
+.PD 0
+.IP "\-\-output\-dir \s-1DIR\s0" 4
+.IX Item "--output-dir DIR"
+.PD
+Store search results as (symlink) messages under maildir \s-1DIR\s0. Beware: \s-1DIR\s0 will
+be overwritten. (Default: \fI~/.cache/mutt_results/\fR)
+.IP "\-p" 4
+.IX Item "-p"
+.PD 0
+.IP "\-\-prompt" 4
+.IX Item "--prompt"
+.PD
+Instead of using command line search terms, prompt the user for them (only for
+\&\*(L"search\*(R").
+.IP "\-h" 4
+.IX Item "-h"
+.PD 0
+.IP "\-\-help" 4
+.IX Item "--help"
+.PD
+Show usage information and exit.
+.SH "INTEGRATION WITH MUTT"
+.IX Header "INTEGRATION WITH MUTT"
+mutt-notmuch can be used to integrate notmuch with the Mutt mail user agent
+(unsurprisingly, given the name). To that end, you should define the following
+macros in your \fI~/.muttrc\fR (replacing \fI~/bin/mutt\-notmuch\fR for the actual
+location of mutt-notmuch on your system):
+.PP
+.Vb 6
+\&    macro index <F8> \e
+\&          "<enter\-command>unset wait_key<enter><shell\-escape>~/bin/mutt\-notmuch \-\-prompt search<enter><change\-folder\-readonly>~/.cache/mutt_results<enter>" \e
+\&          "search mail (using notmuch)"
+\&    macro index <F9> \e
+\&          "<enter\-command>unset wait_key<enter><pipe\-message>~/bin/mutt\-notmuch thread<enter><change\-folder\-readonly>~/.cache/mutt_results<enter><enter\-command>set wait_key<enter>" \e
+\&          "search and reconstruct owning thread (using notmuch)"
+.Ve
+.PP
+The first macro (activated by <F8>) will prompt the user for notmuch search
+terms and then jump to a temporary maildir showing search results. The second
+macro (activated by <F9>) will reconstruct the thread corresponding to the
+current mail and show it as search results.
+.PP
+To keep notmuch index current you should then periodically run \f(CW\*(C`notmuch
+new\*(C'\fR. Depending on your local mail setup, you might want to do that via cron,
+as a hook triggered by mail retrieval, etc.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fImutt\fR\|(1), \fInotmuch\fR\|(1)
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Copyright: (C) 2011 Stefano Zacchiroli <zack@upsilon.cc>
+.PP
+License: \s-1GNU\s0 General Public License (\s-1GPL\s0), version 3 or higher
diff --git a/blog/posts/2011/01/how_to_use_Notmuch_with_Mutt/mutt-notmuch.1.html b/blog/posts/2011/01/how_to_use_Notmuch_with_Mutt/mutt-notmuch.1.html
new file mode 100644 (file)
index 0000000..7986657
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>mutt-notmuch - notmuch helper for Mutt</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<link rev="made" href="mailto:root@localhost" />
+</head>
+
+<body style="background-color: white">
+
+
+<!-- INDEX BEGIN -->
+<div name="index">
+<p><a name="__index__"></a></p>
+
+<ul>
+
+       <li><a href="#name">NAME</a></li>
+       <li><a href="#synopsis">SYNOPSIS</a></li>
+       <li><a href="#description">DESCRIPTION</a></li>
+       <li><a href="#options">OPTIONS</a></li>
+       <li><a href="#integration_with_mutt">INTEGRATION WITH MUTT</a></li>
+       <li><a href="#see_also">SEE ALSO</a></li>
+       <li><a href="#author">AUTHOR</a></li>
+</ul>
+
+<hr name="index" />
+</div>
+<!-- INDEX END -->
+
+<p>
+</p>
+<h1><a name="name">NAME</a></h1>
+<p>mutt-notmuch - notmuch (of a) helper for Mutt</p>
+<p>
+</p>
+<hr />
+<h1><a name="synopsis">SYNOPSIS</a></h1>
+<dl>
+<dt><strong><a name="mutt_notmuch_option_search_search_term" class="item"><strong>mutt-notmuch</strong> [<em>OPTION</em>]... search [<em>SEARCH-TERM</em>]...</a></strong></dt>
+
+<dt><strong><a name="mutt_notmuch_option_thread_mail" class="item"><strong>mutt-notmuch</strong> [<em>OPTION</em>]... thread &lt; <em>MAIL</em></a></strong></dt>
+
+</dl>
+<p>
+</p>
+<hr />
+<h1><a name="description">DESCRIPTION</a></h1>
+<p>mutt-notmuch is a frontend to the notmuch mail indexer capable of populating
+maildir with search results.</p>
+<p>
+</p>
+<hr />
+<h1><a name="options">OPTIONS</a></h1>
+<dl>
+<dt><strong><a name="o_dir" class="item">-o DIR</a></strong></dt>
+
+<dt><strong><a name="output_dir_dir" class="item">--output-dir DIR</a></strong></dt>
+
+<dd>
+<p>Store search results as (symlink) messages under maildir DIR. Beware: DIR will
+be overwritten. (Default: <em class="file">~/.cache/mutt_results/</em>)</p>
+</dd>
+<dt><strong><a name="p" class="item">-p</a></strong></dt>
+
+<dt><strong><a name="prompt" class="item">--prompt</a></strong></dt>
+
+<dd>
+<p>Instead of using command line search terms, prompt the user for them (only for
+&quot;search&quot;).</p>
+</dd>
+<dt><strong><a name="h" class="item">-h</a></strong></dt>
+
+<dt><strong><a name="help" class="item">--help</a></strong></dt>
+
+<dd>
+<p>Show usage information and exit.</p>
+</dd>
+</dl>
+<p>
+</p>
+<hr />
+<h1><a name="integration_with_mutt">INTEGRATION WITH MUTT</a></h1>
+<p>mutt-notmuch can be used to integrate notmuch with the Mutt mail user agent
+(unsurprisingly, given the name). To that end, you should define the following
+macros in your <em class="file">~/.muttrc</em> (replacing <em class="file">~/bin/mutt-notmuch</em> for the actual
+location of mutt-notmuch on your system):</p>
+<pre>
+    macro index &lt;F8&gt; \
+          &quot;&lt;enter-command&gt;unset wait_key&lt;enter&gt;&lt;shell-escape&gt;~/bin/mutt-notmuch --prompt search&lt;enter&gt;&lt;change-folder-readonly&gt;~/.cache/mutt_results&lt;enter&gt;&quot; \
+          &quot;search mail (using notmuch)&quot;
+    macro index &lt;F9&gt; \
+          &quot;&lt;enter-command&gt;unset wait_key&lt;enter&gt;&lt;pipe-message&gt;~/bin/mutt-notmuch thread&lt;enter&gt;&lt;change-folder-readonly&gt;~/.cache/mutt_results&lt;enter&gt;&lt;enter-command&gt;set wait_key&lt;enter&gt;&quot; \
+          &quot;search and reconstruct owning thread (using notmuch)&quot;</pre>
+<p>The first macro (activated by &lt;F8&gt;) will prompt the user for notmuch search
+terms and then jump to a temporary maildir showing search results. The second
+macro (activated by &lt;F9&gt;) will reconstruct the thread corresponding to the
+current mail and show it as search results.</p>
+<p>To keep notmuch index current you should then periodically run <code>notmuch
+new</code>. Depending on your local mail setup, you might want to do that via cron,
+as a hook triggered by mail retrieval, etc.</p>
+<p>
+</p>
+<hr />
+<h1><a name="see_also">SEE ALSO</a></h1>
+<p><code>mutt(1)</code>, <code>notmuch(1)</code></p>
+<p>
+</p>
+<hr />
+<h1><a name="author">AUTHOR</a></h1>
+<p>Copyright: (C) 2011 Stefano Zacchiroli &lt;<a href="mailto:zack@upsilon.cc">zack@upsilon.cc</a>&gt;</p>
+<p>License: GNU General Public License (GPL), version 3 or higher</p>
+
+</body>
+
+</html>
index d69f70e..a59c53a 100644 (file)
@@ -83,11 +83,14 @@ debugger](http://caml.inria.fr/pub/docs/manual-ocaml/manual030.html)
 
 # fire-and-forget hacks
 
+* **integration of Mutt with Notmuch**, for blazing fast mail indexing, query,
+  and thread reconstruction
+  [ [[blog post|blog/posts/2011/01/how_to_use_Notmuch_with_Mutt]] ]
 * **[[!wikipedia tickler file]] implementation for maildirs**, to "snooze" your
   INBOX and have messages reappear days later
   [ [[blog post|blog/posts/2010/05/tickler_file_for_maildir]],
   [git](http://git.upsilon.cc/cgi-bin/gitweb.cgi?p=utils/rotate-tickler.git) ]
-* **integration between Mutt and Org-mode**, to implement your GTD work flow
+* **integration of Mutt with Org-mode**, to implement your GTD work flow
   [ [[blog post|blog/posts/2010/02/integrating_Mutt_with_Org-mode]] ]
 * **pam-hooks** - PAM module that support execution of login/logout hooks
   [ [[homepage|pam-hooks]]]