* [PATCH v2]: contrib/notmuch-mutt
2012-03-25 13:13 mutt-notmuch in notmuch contrib David Bremner
@ 2012-03-29 13:35 ` Stefano Zacchiroli
2012-03-30 21:38 ` David Bremner
0 siblings, 1 reply; 7+ messages in thread
From: Stefano Zacchiroli @ 2012-03-29 13:35 UTC (permalink / raw)
To: notmuch; +Cc: Ben Boeckel, 628018-quiet
[-- Attachment #1.1: Type: text/plain, Size: 1448 bytes --]
On Sun, Mar 25, 2012 at 10:13:38AM -0300, David Bremner wrote:
> In the mean time, we at least have a contrib directory, and I think
> mutt-notmuch would be welcome there. Could you (or somebody) make a
> reasonable size patch series that adds it to contrib/mutt-notmuch
> against current master. The patch series should be sent to the
> upstream mailing list notmuch@notmuchmail.org for review.
>
> On the debian side your patch series could also include the necessary
> changes to make a new binary package.
>
> Notmuch itself is already GPL3+ so no hassles there (for once).
Here is an updated set of patches, which I consider final for inclusion
of notmuch-mutt as part of notmuch contrib/. AFAICT I've implemented
all changes that have been requested either on this list or in private
mail to me: renaming, Debian packaging, XDG userdir support, shell
quoting in all notmuch calls. TTBOMK, no further changes have been
requested.
Can some kind soul "git am" the attached patches to notmuch Git repo?
If OTOH you have further request for changes, please let me know. I'll
be happy to act on them.
TIA,
Cheers.
--
Stefano Zacchiroli zack@{upsilon.cc,pps.jussieu.fr,debian.org} . o .
Maître de conférences ...... http://upsilon.cc/zack ...... . . o
Debian Project Leader ....... @zack on identi.ca ....... o o o
« the first rule of tautology club is the first rule of tautology club »
[-- Attachment #1.2: 0001-contrib-new-mutt-notmuch-utility-for-Mutt-integratio.patch --]
[-- Type: text/x-diff, Size: 11892 bytes --]
From 9121254754ad742ec025b77c50d5abe3334ba547 Mon Sep 17 00:00:00 2001
From: Stefano Zacchiroli <zack@upsilon.cc>
Date: Mon, 26 Mar 2012 10:45:58 +0200
Subject: [PATCH 1/2] contrib: new mutt-notmuch utility for Mutt integration
---
contrib/notmuch-mutt/.gitignore | 2 +
contrib/notmuch-mutt/Makefile | 12 ++
contrib/notmuch-mutt/README | 59 +++++++++
contrib/notmuch-mutt/notmuch-mutt | 238 ++++++++++++++++++++++++++++++++++
contrib/notmuch-mutt/notmuch-mutt.rc | 9 ++
5 files changed, 320 insertions(+)
create mode 100644 contrib/notmuch-mutt/.gitignore
create mode 100644 contrib/notmuch-mutt/Makefile
create mode 100644 contrib/notmuch-mutt/README
create mode 100755 contrib/notmuch-mutt/notmuch-mutt
create mode 100644 contrib/notmuch-mutt/notmuch-mutt.rc
diff --git a/contrib/notmuch-mutt/.gitignore b/contrib/notmuch-mutt/.gitignore
new file mode 100644
index 0000000..682a577
--- /dev/null
+++ b/contrib/notmuch-mutt/.gitignore
@@ -0,0 +1,2 @@
+notmuch-mutt.1
+README.html
diff --git a/contrib/notmuch-mutt/Makefile b/contrib/notmuch-mutt/Makefile
new file mode 100644
index 0000000..87f9031
--- /dev/null
+++ b/contrib/notmuch-mutt/Makefile
@@ -0,0 +1,12 @@
+NAME = notmuch-mutt
+
+all: $(NAME) $(NAME).1
+
+$(NAME).1: $(NAME)
+ pod2man $< > $@
+
+README.html: README
+ markdown $< > $@
+
+clean:
+ rm -f notmuch-mutt.1 README.html
diff --git a/contrib/notmuch-mutt/README b/contrib/notmuch-mutt/README
new file mode 100644
index 0000000..382ac91
--- /dev/null
+++ b/contrib/notmuch-mutt/README
@@ -0,0 +1,59 @@
+notmuch-mutt: Notmuch (of a) helper for Mutt
+============================================
+
+notmuch-mutt provide integration among the [Mutt] [1] mail user agent and the
+[Notmuch] [2] mail indexer.
+
+notmuch-mutt offer two main integration features. The first one is the ability
+of stating a **search query interactively** and then jump to a fresh Maildir
+containing its search results only. The second one is the ability to
+**reconstruct threads on the fly** starting from the currently highlighted
+mail, which comes handy when a thread has been split across different maildirs,
+archived, or the like.
+
+notmuch-mutt enables to trigger mail searches via a Mutt macro (usually F8) and
+reconstruct threads via another (usually F9). Check the manpage for the 2-liner
+configuration snippet for your Mutt configuration files (~/.muttrc,
+/etc/Muttrc, or a /etc/Muttrc.d snippet).
+
+A [blog style introduction] [3] to notmuch-mutt is available and includes some
+more rationale for its existence.
+
+Arguably, some of the logics of notmuch-mutt could disappear by adding support
+for a --output=symlinks flag to notmuch.
+
+
+[1]: http://www.mutt.org/
+[2]: http://notmuchmail.org/
+[3]: http://upsilon.cc/~zack/blog/posts/2011/01/how_to_use_Notmuch_with_Mutt/
+
+
+Requirements
+------------
+
+To *run* notmuch-mutt you will need Perl with the following libraries:
+
+- Mail::Box <http://search.cpan.org/~markov/Mail-Box/>
+ (Debian package: libmail-box-perl)
+- Mail::Internet <http://search.cpan.org/~markov/MailTools/>
+ (Debian package: libmailtools-perl)
+- String::ShellQuote <http://search.cpan.org/~rosch/String-ShellQuote/ShellQuote.pm>
+ (Debian package: libstring-shellquote-perl)
+- Term::ReadLine <http://search.cpan.org/~hayashi/Term-ReadLine-Gnu/>
+ (Debian package: libterm-readline-gnu-perl)
+
+To *build* notmuch-mutt documentation you will need:
+
+- pod2man (coming with Perl) to generate the manpage
+- markdown to generate README.html out of this file
+
+
+License
+-------
+
+notmuch-mutt is copyright (C) 2011-2012 Stefano Zacchiroli <zack@upsilon.cc>.
+
+notmuch-mutt is released under the terms of the GNU General Public License
+(GPL), version 3 or above. A copy of the license is available online at
+<http://www.gnu.org/licenses/>.
+
diff --git a/contrib/notmuch-mutt/notmuch-mutt b/contrib/notmuch-mutt/notmuch-mutt
new file mode 100755
index 0000000..6b34e94
--- /dev/null
+++ b/contrib/notmuch-mutt/notmuch-mutt
@@ -0,0 +1,238 @@
+#!/usr/bin/perl -w
+#
+# notmuch-mutt - notmuch (of a) helper for Mutt
+#
+# Copyright: © 2011-2012 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 notmuch-mutt > notmuch-mutt.1"
+
+use strict;
+use warnings;
+
+use File::Path;
+use Getopt::Long qw(:config no_getopt_compat);
+use Mail::Internet;
+use Mail::Box::Maildir;
+use Pod::Usage;
+use String::ShellQuote;
+use Term::ReadLine;
+
+
+my $xdg_cache_dir = "$ENV{HOME}/.cache";
+$xdg_cache_dir = $ENV{XDG_CACHE_HOME} if $ENV{XDG_CACHE_HOME};
+my $cache_dir = "$xdg_cache_dir/notmuch/mutt";
+
+
+# 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) = @_;
+ $query = shell_quote($query);
+
+ empty_maildir($maildir);
+ system("notmuch search --output=files $query"
+ . " | sed -e 's: :\\\\ :g'"
+ . " | xargs --no-run-if-empty ln -s -t $maildir/cur/");
+}
+
+sub prompt($$) {
+ my ($text, $default) = @_;
+ my $query = "";
+ my $term = Term::ReadLine->new( "notmuch-mutt" );
+ my $histfile = "$cache_dir/history";
+
+ $term->ornaments( 0 );
+ $term->unbind_key( ord( "\t" ) );
+ $term->MinLine( 3 );
+ $histfile = $ENV{MUTT_NOTMUCH_HISTFILE} if $ENV{MUTT_NOTMUCH_HISTFILE};
+ $term->ReadHistory($histfile) if (-r $histfile);
+ while (1) {
+ chomp($query = $term->readline($text, $default));
+ if ($query eq "?") {
+ system("man", "notmuch");
+ } else {
+ $term->WriteHistory($histfile);
+ return $query;
+ }
+ }
+}
+
+sub get_message_id() {
+ my $mail = Mail::Internet->new(\*STDIN);
+ $mail->head->get("message-id") =~ /^<(.*)>$/; # get message-id
+ return $1;
+}
+
+sub search_action($$@) {
+ my ($interactive, $results_dir, @params) = @_;
+
+ if (! $interactive) {
+ search($results_dir, join(' ', @params));
+ } else {
+ my $query = prompt("search ('?' for man): ", join(' ', @params));
+ if ($query ne "") {
+ search($results_dir,$query);
+ }
+ }
+}
+
+sub thread_action(@) {
+ my ($results_dir, @params) = @_;
+
+ my $mid = get_message_id();
+ my $search_cmd = 'notmuch search --output=threads ' . shell_quote("id:$mid");
+ my $tid = `$search_cmd`; # get thread id
+ chomp($tid);
+
+ search($results_dir, $tid);
+}
+
+sub tag_action(@) {
+ my $mid = get_message_id();
+
+ system("notmuch tag "
+ . shell_quote(join(' ', @_))
+ . " id:$mid");
+}
+
+sub die_usage() {
+ my %podflags = ( "verbose" => 1,
+ "exitval" => 2 );
+ pod2usage(%podflags);
+}
+
+sub main() {
+ mkpath($cache_dir) unless (-d $cache_dir);
+
+ my $results_dir = "$cache_dir/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]);
+
+ foreach my $param (@params) {
+ $param =~ s/folder:=/folder:/g;
+ }
+
+ 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);
+ } elsif ($action eq "tag") {
+ tag_action(@params);
+ } else {
+ die_usage();
+ }
+}
+
+main();
+
+__END__
+
+=head1 NAME
+
+notmuch-mutt - notmuch (of a) helper for Mutt
+
+=head1 SYNOPSIS
+
+=over
+
+=item B<notmuch-mutt> [I<OPTION>]... search [I<SEARCH-TERM>]...
+
+=item B<notmuch-mutt> [I<OPTION>]... thread < I<MAIL>
+
+=item B<notmuch-mutt> [I<OPTION>]... tag [I<TAGS>]... < I<MAIL>
+
+=back
+
+=head1 DESCRIPTION
+
+notmuch-mutt 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/notmuch/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
+
+notmuch-mutt can be used to integrate notmuch with the Mutt mail user agent
+(unsurprisingly, given the name). To that end, you should define macros like
+the following in your Mutt configuration (usually one of: F<~/.muttrc>,
+F</etc/Muttrc>, or a configuration snippet under F</etc/Muttrc.d/>):
+
+ macro index <F8> \
+ "<enter-command>unset wait_key<enter><shell-escape>notmuch-mutt --prompt search<enter><change-folder-readonly>~/.cache/notmuch/mutt/results<enter>" \
+ "notmuch: search mail"
+ macro index <F9> \
+ "<enter-command>unset wait_key<enter><pipe-message>notmuch-mutt thread<enter><change-folder-readonly>~/.cache/notmuch/mutt/results<enter><enter-command>set wait_key<enter>" \
+ "notmuch: reconstruct thread"
+ macro index <F6> \
+ "<enter-command>unset wait_key<enter><pipe-message>notmuch-mutt tag -inbox<enter>" \
+ "notmuch: remove message from inbox"
+
+The first macro (activated by <F8>) prompts the user for notmuch search terms
+and then jump to a temporary maildir showing search results. The second macro
+(activated by <F9>) reconstructs the thread corresponding to the current mail
+and show it as search results. The third macro (activated by <F6>) removes the
+tag C<inbox> from the current message; by changing C<-inbox> this macro may be
+customised to add or remove tags appropriate to the users notmuch work-flow.
+
+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-2012 Stefano Zacchiroli <zack@upsilon.cc>
+
+License: GNU General Public License (GPL), version 3 or higher
+
+=cut
diff --git a/contrib/notmuch-mutt/notmuch-mutt.rc b/contrib/notmuch-mutt/notmuch-mutt.rc
new file mode 100644
index 0000000..c0ff000
--- /dev/null
+++ b/contrib/notmuch-mutt/notmuch-mutt.rc
@@ -0,0 +1,9 @@
+macro index <F8> \
+ "<enter-command>unset wait_key<enter><shell-escape>notmuch-mutt --prompt search<enter><change-folder-readonly>`echo ${XDG_CACHE_HOME:-$HOME/.cache}/notmuch/mutt/results`<enter>" \
+ "notmuch: search mail"
+macro index <F9> \
+ "<enter-command>unset wait_key<enter><pipe-message>notmuch-mutt thread<enter><change-folder-readonly>`echo ${XDG_CACHE_HOME:-$HOME/.cache}/notmuch/mutt/results`<enter><enter-command>set wait_key<enter>" \
+ "notmuch: reconstruct thread"
+macro index <F6> \
+ "<enter-command>unset wait_key<enter><pipe-message>notmuch-mutt tag -inbox<enter>" \
+ "notmuch: remove message from inbox"
--
1.7.9.5
[-- Attachment #1.3: 0002-debian-packaging-new-binary-package-notmuch-mutt.patch --]
[-- Type: text/x-diff, Size: 3297 bytes --]
From 856204dea0f5133b2f80da74ad329355d5124b36 Mon Sep 17 00:00:00 2001
From: Stefano Zacchiroli <zack@upsilon.cc>
Date: Mon, 26 Mar 2012 10:51:44 +0200
Subject: [PATCH 2/2] debian packaging: new binary package notmuch-mutt
---
debian/changelog | 6 ++++++
debian/control | 16 ++++++++++++++++
debian/notmuch-mutt.docs | 1 +
debian/notmuch-mutt.install | 2 ++
debian/notmuch-mutt.manpages | 1 +
debian/rules | 2 ++
6 files changed, 28 insertions(+)
create mode 100644 debian/notmuch-mutt.docs
create mode 100644 debian/notmuch-mutt.install
create mode 100644 debian/notmuch-mutt.manpages
diff --git a/debian/changelog b/debian/changelog
index d0eec37..bd70d08 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+notmuch (0.12-2) UNRELEASED; urgency=low
+
+ * new binary package "notmuch-mutt" for Mutt integration
+
+ -- Stefano Zacchiroli <zack@debian.org> Mon, 26 Mar 2012 10:47:29 +0200
+
notmuch (0.12-1) unstable; urgency=low
* New upstream release
diff --git a/debian/control b/debian/control
index ed27c58..ada9d3d 100644
--- a/debian/control
+++ b/debian/control
@@ -105,3 +105,19 @@ Description: thread-based email index, search and tagging (vim interface)
This package provides a vim based mail user agent based on
notmuch.
+Package: notmuch-mutt
+Architecture: all
+Depends: notmuch, libmail-box-perl, libmailtools-perl,
+ libstring-shellquote-perl, libterm-readline-gnu-perl,
+ ${misc:Depends}
+Recommends: mutt
+Enhances: notmuch, mutt
+Description: thread-based email index, search and tagging (Mutt interface)
+ notmuch-mutt provides integration among the Mutt mail user agent and
+ the Notmuch mail indexer.
+ .
+ notmuch-mutt offer two main integration features. The first one is
+ the ability of stating a search query interactively and then jump to
+ a fresh Maildir containing its search results only. The second one is
+ the ability to reconstruct threads on the fly starting from the
+ current highlighted mail.
diff --git a/debian/notmuch-mutt.docs b/debian/notmuch-mutt.docs
new file mode 100644
index 0000000..f3d25cd
--- /dev/null
+++ b/debian/notmuch-mutt.docs
@@ -0,0 +1 @@
+contrib/notmuch-mutt/README
diff --git a/debian/notmuch-mutt.install b/debian/notmuch-mutt.install
new file mode 100644
index 0000000..9141c26
--- /dev/null
+++ b/debian/notmuch-mutt.install
@@ -0,0 +1,2 @@
+contrib/notmuch-mutt/notmuch-mutt usr/bin
+contrib/notmuch-mutt/notmuch-mutt.rc etc/Muttrc.d
diff --git a/debian/notmuch-mutt.manpages b/debian/notmuch-mutt.manpages
new file mode 100644
index 0000000..3f6b8ab
--- /dev/null
+++ b/debian/notmuch-mutt.manpages
@@ -0,0 +1 @@
+contrib/notmuch-mutt/notmuch-mutt.1
diff --git a/debian/rules b/debian/rules
index 956f3f2..603b3ab 100755
--- a/debian/rules
+++ b/debian/rules
@@ -9,10 +9,12 @@ override_dh_auto_configure:
override_dh_auto_build:
dh_auto_build
dh_auto_build --sourcedirectory bindings/python
+ $(MAKE) -C contrib/notmuch-mutt
override_dh_auto_clean:
dh_auto_clean
dh_auto_clean --sourcedirectory bindings/python
+ $(MAKE) -C contrib/notmuch-mutt clean
override_dh_auto_install:
dh_auto_install
--
1.7.9.5
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 828 bytes --]
^ permalink raw reply related [flat|nested] 7+ messages in thread