Added support for using notmuch as an external indexer.
[muttjump] / muttjump_fallback
1 #!/bin/bash
2 # written by Johannes Wei├čl
3
4 # muttjump_fallback
5 #
6 # This is a fallback solution for muttjump which doesn't use any mail
7 # indexer to find the original mail (which is of course way slower in
8 # most cases).
9 #
10 # This requires two folder-hooks in .muttrc:
11 #
12 # # hack: set my_cwd to current folder path, abusing $record
13 # # todo: better solution?
14 # folder-hook . 'set my_backup_record=$record ; set record=^ ; set my_cwd=$record ; set record=$my_backup_record'
15
16 # # set macro for jumping to original message
17 # # needs to be set for every folder after my_cwd (see above) has been set
18 # # todo: better solution?
19 # folder-hook . 'macro generic ,J "<enter-command>push <pipe-message>\"muttjump_fallback $my_cwd $folder\"<enter><enter>" "jump to original message"'
20
21 # program paths
22 MUTT=${MUTT:-mutt}
23
24 function die () {
25     echo -e >&2 "$0: $1"
26     exit 1
27 }
28
29 # Check command-line arguments and STDIN
30 if tty -s || [ $# -gt 2 ] || [ $# -lt 1 ] ; then
31     cat >&2 <<END
32 Usage: $0 virtual-maildir [folder] < msg
33
34 This script calls mutt, jumping to the message given in stdin.
35 It uses grep to search for the messages in "virtual-maildir" (a maildir
36 containing only symbolic links), and finds out the target through readlink.
37 If "virtual-maildir" contains shortcuts like '=', "folder" can be given for
38 expansion.
39 END
40     exit 1
41 fi
42
43 # check if mutt is installed
44 if ! type -p $MUTT >/dev/null ; then
45     die "$MUTT is not in PATH, set MUTT variable"
46 fi
47
48 # search for Message-ID in STDIN
49 tmpfile=$(mktemp)
50 msgid_line=$(tee "$tmpfile" | grep -i '^Message-ID: ' | head -n1)
51 msgid=$(echo "$msgid_line" | sed -n 's/^[^:]*: \(.*\)/\1/p')
52 msgsize=$(wc -c "$tmpfile")
53 rm -f "$tmpfile"
54
55 if [ -z "$msgid" ] ; then
56     die "could not find Message-ID header in standard input"
57 fi
58 msgid_clean=$(echo "$msgid" | sed 's/^<\(.*\)>$/\1/')
59
60 maildir=$1
61
62 # If $folder is given as second argument, replace "+" or "=" in $maildir
63 if [ $# -gt 1 ] ; then
64     folder=$2
65     maildir=$(echo "$maildir" | sed "s@^[+=]@$folder/@")
66 fi
67
68 if [ ! -d "$maildir/cur" ] ; then
69     die "directory \"$maildir\" doesn't exist or is no Maildir"
70 fi
71
72 # grep for Message-ID in the current Maildir
73 # TODO: This is definitely not what we want, but there seems to be no way
74 # to pass the filename of the currently selected mail to an external
75 # program, as this is dependent on the folder format.
76 num_files=$(ls -1 "$maildir"/cur/ | wc -l)
77 if [ $num_files -ge 100 ] ; then
78     echo "Grepping through $num_files messages, this could take a while!"
79 fi
80 msgfile=$(grep -HlFx "$msgid_line" "$maildir"/cur/* | head -n1)
81 if [ -z "$msgfile" ] ; then
82     die "could not find Message-ID in maildir:
83   grep -HlFx \"Message-ID: $msgid\" \"$maildir\"/cur/*"
84 fi
85
86 # find out original message-file of linked message
87 orig_msgfile=$(readlink "$msgfile")
88 if [ -z "$orig_msgfile" ] ; then
89     die "message \"$msgfile\" is no link to another message, aborting!"
90 fi
91
92 # get containing maildir of $orig_msgfile
93 orig_maildir=$(dirname $(dirname "$orig_msgfile"))
94 if [ ! -d "$orig_maildir/cur" ] ; then
95     die "directory \"$orig_maildir\" doesn't exist or is no Maildir"
96 fi
97
98 # Close message-stdin and open terminal-stdin instead.
99 # mutt behaves different if STDIN is no terminal
100 # TODO: Find cleaner solution (e.g. mutt command-line argument?)
101 exec 0<&-
102 term="/dev/$(ps -p$$ --no-heading | awk '{print $2}')"
103 exec < $term
104
105 # start mutt, open original folder and jump to the original message
106 $MUTT -e "push <change-folder>$orig_maildir<enter><search>\"~i $msgid\"<enter>"

Benjamin Mako Hill || Want to submit a patch?