]> git.cworth.org Git - obsolete/notmuch-old/blob - contrib/nmbug/nmbug-status
contrib/nmbug/nmbug-status: combine thread messages
[obsolete/notmuch-old] / contrib / nmbug / nmbug-status
1 #!/usr/bin/python
2 #
3 # Copyright (c) 2011-2012 David Bremner <david@tethera.net>
4 # License: Same as notmuch
5 # dependencies
6 #       - python 2.6 for json
7 #       - argparse; either python 2.7, or install separately
8
9 import datetime
10 import notmuch
11 import rfc822
12 import urllib
13 import json
14 import argparse
15 import os
16 import subprocess
17
18 # parse command line arguments
19
20 parser = argparse.ArgumentParser()
21 parser.add_argument('--text', help='output plain text format',
22                     action='store_true')
23
24 parser.add_argument('--config', help='load config from given file')
25
26
27 args = parser.parse_args()
28
29 # read config from json file
30
31 if args.config != None:
32     fp = open(args.config)
33 else:
34     nmbhome = os.getenv('NMBGIT', os.path.expanduser('~/.nmbug'))
35
36     # read only the first line from the pipe
37     sha1 = subprocess.Popen(['git', '--git-dir', nmbhome,
38                              'show-ref', '-s', 'config'],
39                             stdout=subprocess.PIPE).stdout.readline()
40
41     sha1 = sha1.rstrip()
42
43     fp = subprocess.Popen(['git', '--git-dir', nmbhome,
44                            'cat-file', 'blob', sha1+':status-config.json'],
45                           stdout=subprocess.PIPE).stdout
46
47 config = json.load(fp)
48
49 if args.text:
50     output_format = 'text'
51 else:
52     output_format = 'html'
53
54 class Thread:
55     def __init__(self, last, lines):
56         self.last = last
57         self.lines = lines
58
59     def join_utf8_with_newlines(self):
60         return '\n'.join( (line.encode('utf-8') for line in self.lines) )
61
62 def output_with_separator(threadlist, sep):
63     outputs = (thread.join_utf8_with_newlines() for thread in threadlist)
64     print sep.join(outputs)
65
66 headers = ['date', 'from', 'subject']
67
68 def print_view(title, query, comment):
69
70     query_string = ' and '.join(query)
71     q_new = notmuch.Query(db, query_string)
72     q_new.set_sort(notmuch.Query.SORT.OLDEST_FIRST)
73
74     last_thread_id = ''
75     threads = {}
76     threadlist = []
77     out = {}
78     last = None
79     lines = None
80
81     if output_format == 'html':
82         print '<h3><a name="%s" />%s</h3>' % (title, title)
83         print comment
84         print 'The view is generated from the following query:'
85         print '<blockquote>'
86         print query_string
87         print '</blockquote>'
88         print '<table>\n'
89
90     for m in q_new.search_messages():
91
92         thread_id = m.get_thread_id()
93
94         if thread_id != last_thread_id:
95             if threads.has_key(thread_id):
96                 last = threads[thread_id].last
97                 lines = threads[thread_id].lines
98             else:
99                 last = {}
100                 lines = []
101                 thread = Thread(last, lines)
102                 threads[thread_id] = thread
103                 for h in headers:
104                     last[h] = ''
105                 threadlist.append(thread)
106             last_thread_id = thread_id
107
108         for header in headers:
109             val = m.get_header(header)
110
111             if header == 'date':
112                 val = str.join(' ', val.split(None)[1:4])
113                 val = str(datetime.datetime.strptime(val, '%d %b %Y').date())
114             elif header == 'from':
115                 (val, addr) = rfc822.parseaddr(val)
116                 if val == '':
117                     val = addr.split('@')[0]
118
119             if header != 'subject' and last[header] == val:
120                 out[header] = ''
121             else:
122                 out[header] = val
123                 last[header] = val
124
125         mid = m.get_message_id()
126         out['id'] = 'id:"%s"' % mid
127
128         if output_format == 'html':
129
130             out['subject'] = '<a href="http://mid.gmane.org/%s">%s</a>' \
131                 % (urllib.quote(mid), out['subject'])
132
133             lines.append(' <tr><td>%s' % out['date'])
134             lines.append('</td><td>%s' % out['id'])
135             lines.append('</td></tr>')
136             lines.append(' <tr><td>%s' % out['from'])
137             lines.append('</td><td>%s' % out['subject'])
138             lines.append('</td></tr>')
139         else:
140             lines.append('%(date)-10.10s %(from)-20.20s %(subject)-40.40s\n%(id)72s' % out)
141
142     if output_format == 'html':
143         output_with_separator(threadlist,
144                               '\n<tr><td colspan="2"><br /></td></tr>\n')
145         print '</table>'
146     else:
147         output_with_separator(threadlist, '\n\n')
148
149 # main program
150
151 db = notmuch.Database(mode=notmuch.Database.MODE.READ_WRITE)
152
153 if output_format == 'html':
154     print '''<?xml version="1.0" encoding="utf-8" ?>
155 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
156 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
157 <head>
158 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
159 <title>Notmuch Patches</title>
160 </head>
161 <body>'''
162     print '<h2>Notmuch Patches</h2>'
163     print 'Generated: %s<br />' % datetime.datetime.utcnow().date()
164     print 'For more infomation see <a href="http://notmuchmail.org/nmbug">nmbug</a>'
165
166     print '<h3>Views</h3>'
167     print '<ul>'
168     for view in config['views']:
169         print '<li><a href="#%(title)s">%(title)s</a></li>' % view
170     print '</ul>'
171
172 for view in config['views']:
173     print_view(**view)
174
175 if output_format == 'html':
176     print '</body>\n</html>'