--- /dev/null
+Return-Path: <too@guru-group.fi>\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 8BA8A431FAE\r
+ for <notmuch@notmuchmail.org>; Wed, 24 Oct 2012 00:00:00 -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 cVLve8SfgVK5 for <notmuch@notmuchmail.org>;\r
+ Tue, 23 Oct 2012 23:59:59 -0700 (PDT)\r
+Received: from guru.guru-group.fi (guru.guru-group.fi [46.183.73.34])\r
+ by olra.theworths.org (Postfix) with ESMTP id 25C61431FAF\r
+ for <notmuch@notmuchmail.org>; Tue, 23 Oct 2012 23:59:59 -0700 (PDT)\r
+Received: by guru.guru-group.fi (Postfix, from userid 501)\r
+ id A4B9D100390; Wed, 24 Oct 2012 10:00:01 +0300 (EEST)\r
+From: Tomi Ollila <tomi.ollila@iki.fi>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH 2/2] contrib/nmbug/nmbug-status: combine thread messages\r
+Date: Wed, 24 Oct 2012 09:59:59 +0300\r
+Message-Id: <1351061999-25473-2-git-send-email-tomi.ollila@iki.fi>\r
+X-Mailer: git-send-email 1.7.1\r
+In-Reply-To: <1351061999-25473-1-git-send-email-tomi.ollila@iki.fi>\r
+References: <1351061999-25473-1-git-send-email-tomi.ollila@iki.fi>\r
+Cc: tomi.ollila@iki.fi\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: Wed, 24 Oct 2012 07:00:00 -0000\r
+\r
+Newer patch email containing In-Reply-To: to an email sent some time ago\r
+(i.e. to a "thread") was not visible in that "thread" in patch view when\r
+another patch "thread" was submitted in between. This change collects\r
+all messages in every (notmuch-created) thread together before printing\r
+all these threads out in a patch view.\r
+\r
+Thanks to Ethan Glasser-Camp for initial review and suggestions with\r
+code examples.\r
+---\r
+Notes:\r
+\r
+Thread class was added for convenience at late time to replace tuple\r
+containing last dict & lines list; It could be more utilized -- my excuse\r
+of not doing so is to minimize change...\r
+\r
+OrderedDict could be used in place of threadlist but that requires \r
+Python 2.7 (I used python 2.6 where argparse.py was copied to cwd;\r
+also nmbug site uses python 2.6...). \r
+\r
+The table row separator '\n<tr><td colspan="2"><br /></td></tr>\n'\r
+is a hack; If someone knows better simple semantic alternative that\r
+could be used later...\r
+\r
+ contrib/nmbug/nmbug-status | 73 +++++++++++++++++++++++++++----------------\r
+ 1 files changed, 46 insertions(+), 27 deletions(-)\r
+\r
+diff --git a/contrib/nmbug/nmbug-status b/contrib/nmbug/nmbug-status\r
+index c663409..69b407c 100755\r
+--- a/contrib/nmbug/nmbug-status\r
++++ b/contrib/nmbug/nmbug-status\r
+@@ -51,12 +51,19 @@ if args.text:\r
+ else:\r
+ output_format = 'html'\r
+ \r
+-headers = ['date', 'from', 'subject']\r
+-last = {}\r
++class Thread:\r
++ def __init__(self, last, lines):\r
++ self.last = last\r
++ self.lines = lines\r
++\r
++ def join_utf8_with_newlines(self):\r
++ return '\n'.join( (line.encode('utf-8') for line in self.lines) )\r
+ \r
+-def clear_last():\r
+- for header in headers:\r
+- last[header] = ''\r
++def output_with_separator(threadlist, sep):\r
++ outputs = (thread.join_utf8_with_newlines() for thread in threadlist)\r
++ print sep.join(outputs)\r
++\r
++headers = ['date', 'from', 'subject']\r
+ \r
+ def print_view(title, query, comment):\r
+ \r
+@@ -64,7 +71,12 @@ def print_view(title, query, comment):\r
+ q_new = notmuch.Query(db, query_string)\r
+ q_new.set_sort(notmuch.Query.SORT.OLDEST_FIRST)\r
+ \r
+- last['thread_id'] = ''\r
++ last_thread_id = ''\r
++ threads = {}\r
++ threadlist = []\r
++ out = {}\r
++ last = None\r
++ lines = None\r
+ \r
+ if output_format == 'html':\r
+ print '<h3><a name="%s" />%s</h3>' % (title, title)\r
+@@ -77,11 +89,21 @@ def print_view(title, query, comment):\r
+ \r
+ for m in q_new.search_messages():\r
+ \r
+- out = {}\r
+-\r
+ thread_id = m.get_thread_id()\r
+- if thread_id != last['thread_id']:\r
+- clear_last()\r
++\r
++ if thread_id != last_thread_id:\r
++ if threads.has_key(thread_id):\r
++ last = threads[thread_id].last\r
++ lines = threads[thread_id].lines\r
++ else:\r
++ last = {}\r
++ lines = []\r
++ thread = Thread(last, lines)\r
++ threads[thread_id] = thread\r
++ for h in headers:\r
++ last[h] = ''\r
++ threadlist.append(thread)\r
++ last_thread_id = thread_id\r
+ \r
+ for header in headers:\r
+ val = m.get_header(header)\r
+@@ -94,38 +116,35 @@ def print_view(title, query, comment):\r
+ if val == '':\r
+ val = addr.split('@')[0]\r
+ \r
+- if last[header] == val:\r
++ if header != 'subject' and last[header] == val:\r
+ out[header] = ''\r
+ else:\r
+- out[header] = val.encode('utf-8')\r
++ out[header] = val\r
+ last[header] = val\r
+ \r
+ mid = m.get_message_id()\r
+ out['id'] = 'id:"%s"' % mid\r
+ \r
+ if output_format == 'html':\r
+- # XXX using <br /> is a hack, but ... // 20111216 too\r
+- if thread_id != last['thread_id']:\r
+- br = '<br />'\r
+- else:\r
+- br = ''\r
+ \r
+ out['subject'] = '<a href="http://mid.gmane.org/%s">%s</a>' \\r
+ % (urllib.quote(mid), out['subject'])\r
+ \r
+- print ' <tr><td>%s %s' % (br, out['date'])\r
+- print '</td><td>%s %s' % (br, out['id'])\r
+- print '</td></tr>'\r
+- print ' <tr><td>%s' % out['from']\r
+- print '</td><td>%s' % out['subject']\r
+- print '</td></tr>\n'\r
++ lines.append(' <tr><td>%s' % out['date'])\r
++ lines.append('</td><td>%s' % out['id'])\r
++ lines.append('</td></tr>')\r
++ lines.append(' <tr><td>%s' % out['from'])\r
++ lines.append('</td><td>%s' % out['subject'])\r
++ lines.append('</td></tr>')\r
+ else:\r
+- print '%(date)-10.10s %(from)-20.20s %(subject)-40.40s\n%(id)72s\n' % out\r
+-\r
+- last['thread_id'] = thread_id\r
++ lines.append('%(date)-10.10s %(from)-20.20s %(subject)-40.40s\n%(id)72s' % out)\r
+ \r
+ if output_format == 'html':\r
++ output_with_separator(threadlist,\r
++ '\n<tr><td colspan="2"><br /></td></tr>\n')\r
+ print '</table>'\r
++ else:\r
++ output_with_separator(threadlist, '\n\n')\r
+ \r
+ # main program\r
+ \r
+-- \r
+1.7.1\r
+\r