[RFC][alot] design decisions
authorPatrick Totzke <patricktotzke@googlemail.com>
Wed, 21 Mar 2012 09:07:22 +0000 (09:07 +0000)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:45:40 +0000 (09:45 -0800)
b6/68bc6939f83d62b9ad4c365df8a4ea676ec316 [new file with mode: 0644]

diff --git a/b6/68bc6939f83d62b9ad4c365df8a4ea676ec316 b/b6/68bc6939f83d62b9ad4c365df8a4ea676ec316
new file mode 100644 (file)
index 0000000..82a1a2c
--- /dev/null
@@ -0,0 +1,194 @@
+Return-Path: <patricktotzke@googlemail.com>\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 43591431FAF\r
+       for <notmuch@notmuchmail.org>; Wed, 21 Mar 2012 02:07:28 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.799\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.799 tagged_above=-999 required=5\r
+       tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,\r
+       FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7] 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 QiFZfOGmUaQm for <notmuch@notmuchmail.org>;\r
+       Wed, 21 Mar 2012 02:07:27 -0700 (PDT)\r
+Received: from mail-wi0-f179.google.com (mail-wi0-f179.google.com\r
+       [209.85.212.179]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
+       (No client certificate requested)\r
+       by olra.theworths.org (Postfix) with ESMTPS id 3FCE7431FAE\r
+       for <notmuch@notmuchmail.org>; Wed, 21 Mar 2012 02:07:27 -0700 (PDT)\r
+Received: by wibhn6 with SMTP id hn6so938225wib.2\r
+       for <notmuch@notmuchmail.org>; Wed, 21 Mar 2012 02:07:26 -0700 (PDT)\r
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
+       d=googlemail.com; s=20120113;\r
+       h=content-type:mime-version:content-transfer-encoding:to:message-id\r
+       :from:user-agent:subject:date;\r
+       bh=fKKVWMfpPhBa+YjVOMkXNQETWGr8KdMJXHAPWEAg2V4=;\r
+       b=zAnBO89XvQgv/sstFTsGIajSZSd79qBQCjSigiRSyHDyrvNZMQaZfyyoXwRU1STXvy\r
+       w4kk1FwF0kwh60eLGO4Yz9RcCV7rfBIXsBJiIb7BSaty+a2wsYLTgkCgMU2ETPofnNvH\r
+       4TRh4In7/6MsWcws0B/ax1TQ0PujNFyCr+Wy3NU3FbJ1ivnM5lac2JBoNP3UJCD2hBLo\r
+       rwsiJRqoXu8Co7QDoBtMqGOEGwUGssCHQxO5bvepKZ+yl/GOzNp9FD966Gwm/78DROxl\r
+       N0iXc89Y3SvhJqWjIFhoFl98FpPLFP0zeYLzULGW/VLmtIpvpIcC/MPuN/BXF2+9yAbR\r
+       XPww==\r
+Received: by 10.180.100.2 with SMTP id eu2mr7238366wib.1.1332320845915;\r
+       Wed, 21 Mar 2012 02:07:25 -0700 (PDT)\r
+Received: from localhost (cpc1-sgyl2-0-0-cust548.18-2.cable.virginmedia.com.\r
+       [82.41.10.37])\r
+       by mx.google.com with ESMTPS id e6sm2985347wix.8.2012.03.21.02.07.24\r
+       (version=TLSv1/SSLv3 cipher=OTHER);\r
+       Wed, 21 Mar 2012 02:07:24 -0700 (PDT)\r
+Content-Type: text/plain; charset="utf-8"\r
+MIME-Version: 1.0\r
+Content-Transfer-Encoding: quoted-printable\r
+To: Notmuch Mail <notmuch@notmuchmail.org>\r
+Message-ID: <20120321090722.6892.24383@brick.lan>\r
+From: Patrick Totzke <patricktotzke@googlemail.com>\r
+User-Agent: alot/0.3\r
+Subject: [RFC][alot] design decisions\r
+Date: Wed, 21 Mar 2012 09:07:22 +0000\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, 21 Mar 2012 09:07:28 -0000\r
+\r
+Hi all,\r
+\r
+with alot 0.3 released, I started thinking seriously about proper=E2=84=A2 =\r
+MIME-display and gnupg\r
+integration for alot. I have to make a few design decisions here and could =\r
+really use\r
+some informed opinions from more experienced UI developers. My question in =\r
+particular is: =\r
+\r
+\r
+ How do I best integrate calls to external mime-handlers into my MVC event =\r
+driven code?\r
+\r
+I mostly know how to implement the individual parts but I struggle coming u=\r
+p with a\r
+consistent way of organizing it all without compromising my current layout.\r
+\r
+\r
+Background\r
+----------\r
+\r
+Model. Alot uses an abstraction layer over notmuch's thread, message and da=\r
+tabase objects\r
+to make them less fragile and generally behave more OOP-y: You can e.g. dir=\r
+ectly call\r
+message.add_tags(['foo','bar']) and so on. This is made possible by a "Data=\r
+baseManager"\r
+that maintains centralized and queued access to the notmuch index and deals=\r
+ with notmuch\r
+exceptions like a locked index [0].\r
+\r
+View/Controler. We use an event-driven interface (urwid.TwistedEventLoop, [=\r
+1]) that\r
+handles user input and maintains a tree of widgets that knows how to render=\r
+ itself.\r
+Twisted offers a neat concept of "Deferreds" to organize call- and errbacks=\r
+ that we\r
+already make use of [2].  Alot has a "MessageWidget" that displays a single=\r
+ message.\r
+\r
+We can easily access and parse email messages into MIME-trees (msg.get_emai=\r
+l() returns a\r
+email.message object; pythons email module allows extensive and RFC complia=\r
+nt dealing with\r
+this [3]).\r
+\r
+We already offer full compatibility with the mailcap protocol to constuct s=\r
+hell commands\r
+of external MIME handlers.\r
+\r
+We know how to call external commands asynchronously; `alot.helper.call_cmd=\r
+_async` does this\r
+and returns a Deferred to which we can connect callback functions.\r
+\r
+\r
+Objective\r
+---------\r
+We want to turn a email.message into nicely rendered text and display it as=\r
+ a widget.\r
+Calls to renderers should be done asynchronously, so that displaying large =\r
+threads\r
+does not block the interface unnecessarily.\r
+The text representation should be stored in a way that can be incrementally=\r
+ updated\r
+for use with message parts decrypted at a later point.\r
+\r
+\r
+Bad Solutions\r
+-------------\r
+\r
+1. Current solution: walk the MIME-tree depth-first, use blocking calls to =\r
+handlers\r
+and create a fixed "body" string that is displayed in the widget.\r
+A silly and hackish solution that we want to get rid of for obvious reasons.\r
+\r
+2. Use a "PartWidget" that is able to display a node in the MIME-tree:\r
+Its constructor creates the representation in a RFC compliant way, that is,\r
+it decodes 'text/plain' parts, stacks other widgets of the same kind on top=\r
+ of each other\r
+for multipart parts or calls external renderer to get a text representation.\r
+\r
+Cons:\r
+ * widgets should not be clever and contain/construct any kind of additiona=\r
+l info\r
+ * its hard to update these widgets when a part gets decrypted; =\r
+\r
+ * decrypted parts are not available outside the displaying widget, widgets=\r
+ get\r
+   replaced completely when one rebuilds the buffer (refresh cmd)\r
+Pros:\r
+ * we can use Deferreds relatively painlessly in the ui (as opposed to the =\r
+db-wrapper)\r
+\r
+3. Accumulate rendered text in a tree structure *inside* message-objects an=\r
+d let that\r
+massage update the widget that displays it. One could let the widget regist=\r
+er\r
+some update-callback with the widget that rebuilds the widgets content.\r
+These callbacks are called after the external handler has finished and the =\r
+message-\r
+internal text-representation has been updated.\r
+\r
+Pros: =\r
+\r
+ * rendered text/decrypted message parts end up in the message and are avai=\r
+lable to process\r
+   and redisplay at will\r
+Cons:\r
+ * the calls to MIME-handlers are dealt with as Deferreds which depend on t=\r
+he twisted event\r
+   loop and indirectly on urwid. This is exactly the kind of tight coupling=\r
+ I'm trying to avoid:\r
+   Messages should be independent of the interface.\r
+ * Messages with multiple externally rendered parts will rebuild their widg=\r
+ets more than once\r
+ * references to old widgets (replaced e.g. after a buffer rebuild) will be=\r
+ kept, which keeps\r
+   them from being garbage-collected\r
+\r
+I'm surely missing an easy and elegant solution here.\r
+Any pointers or comments are much appreciated.\r
+Thanks,\r
+/p\r
+\r
+\r
+[0]: http://alot.readthedocs.org/en/latest/api/database.html\r
+[1]: http://excess.org/urwid/\r
+[2]: http://twistedmatrix.com/documents/current/core/howto/defer.html\r
+[3]: http://docs.python.org/library/email\r