--- /dev/null
+Return-Path: <daniel.schoepe@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 06399429E2F\r
+ for <notmuch@notmuchmail.org>; Sun, 12 Jun 2011 16:31:39 -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 SEoq3O0rXGcg for <notmuch@notmuchmail.org>;\r
+ Sun, 12 Jun 2011 16:31:35 -0700 (PDT)\r
+Received: from mail-fx0-f53.google.com (mail-fx0-f53.google.com\r
+ [209.85.161.53]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
+ (No client certificate requested)\r
+ by olra.theworths.org (Postfix) with ESMTPS id 1ECFE429E26\r
+ for <notmuch@notmuchmail.org>; Sun, 12 Jun 2011 16:31:34 -0700 (PDT)\r
+Received: by mail-fx0-f53.google.com with SMTP id 8so2672136fxm.26\r
+ for <notmuch@notmuchmail.org>; Sun, 12 Jun 2011 16:31:34 -0700 (PDT)\r
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
+ d=googlemail.com; s=gamma;\r
+ h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer\r
+ :in-reply-to:references;\r
+ bh=h5E1pB0KvHoQ8M23JdVflKZOhGV6QnEhW8z5X+5lm1A=;\r
+ b=eS+9NvUp9alL4LM85dSj00/+MUO5AA3+GJ0XIpdEczhNnmkVgIWdro42yCWMSbv/If\r
+ M3sPXMzbQ0K5cpx/lq1W667YracHnF/vk/MVc7QjTWrKHm06uyYUVkbZ9GaPw1+OoBmt\r
+ IAXxpWMnW4bO9XgIq92g11ko1y2rUF2y24NfU=\r
+DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma;\r
+ h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references;\r
+ b=Vandc9WlerQ2RB5V0gxR8ysjbTMimYC/fnzvR0Gdp+Dindow8YIt/gI5Bskn8tRC60\r
+ L9kzjpLp2njhH2cK2ll3OsEvw0PhlQRqlJ6Ncdpdrt9YkXE4TwAhiEY7IV1nn1yCDbXV\r
+ YJrxPE3Vn/ryl03eUSAYKgZ5xZQulLtr9xwBE=\r
+Received: by 10.223.25.201 with SMTP id a9mr4442180fac.141.1307921494722;\r
+ Sun, 12 Jun 2011 16:31:34 -0700 (PDT)\r
+Received: from localhost (dslb-088-068-023-159.pools.arcor-ip.net\r
+ [88.68.23.159])\r
+ by mx.google.com with ESMTPS id g8sm983113fai.44.2011.06.12.16.31.32\r
+ (version=TLSv1/SSLv3 cipher=OTHER);\r
+ Sun, 12 Jun 2011 16:31:33 -0700 (PDT)\r
+From: Daniel Schoepe <daniel.schoepe@googlemail.com>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH 2/3] emacs: Add thread-outline functionality\r
+Date: Mon, 13 Jun 2011 01:31:19 +0200\r
+Message-Id: <1307921480-17130-3-git-send-email-daniel.schoepe@googlemail.com>\r
+X-Mailer: git-send-email 1.7.5.4\r
+In-Reply-To: <1307921480-17130-1-git-send-email-daniel.schoepe@googlemail.com>\r
+References: <1307921480-17130-1-git-send-email-daniel.schoepe@googlemail.com>\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: Sun, 12 Jun 2011 23:31:39 -0000\r
+\r
+This patch adds some functionality to display the outline for threads\r
+displayed by notmuch-show. The entries in the outline buffer are\r
+links to the corresponding message in the notmuch-show buffer.\r
+---\r
+ emacs/notmuch-lib.el | 7 +++\r
+ emacs/notmuch-show.el | 144 ++++++++++++++++++++++++++++++++++++++++++++++++-\r
+ 2 files changed, 150 insertions(+), 1 deletions(-)\r
+\r
+diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el\r
+index a21dc14..6918218 100644\r
+--- a/emacs/notmuch-lib.el\r
++++ b/emacs/notmuch-lib.el\r
+@@ -91,9 +91,16 @@ the user hasn't set this variable with the old or new value."\r
+ "Return the user.primary_email value (as a list) from the notmuch configuration."\r
+ (split-string (notmuch-config-get "user.other_email") "\n"))\r
+ \r
++(declare-function notmuch-show-outline-buffer-name "notmuch-show" (&optional buf))\r
++\r
+ (defun notmuch-kill-this-buffer ()\r
+ "Kill the current buffer."\r
+ (interactive)\r
++ ;; if we are in a notmuch-show buffer, kill the associated outline buffer, if any\r
++ (when (eq major-mode 'notmuch-show-mode)\r
++ (let ((outline-buf (get-buffer (notmuch-show-outline-buffer-name))))\r
++ (when outline-buf\r
++ (kill-buffer outline-buf))))\r
+ (kill-buffer (current-buffer)))\r
+ \r
+ ;;\r
+diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el\r
+index aecd35f..4f2a30e 100644\r
+--- a/emacs/notmuch-show.el\r
++++ b/emacs/notmuch-show.el\r
+@@ -107,6 +107,48 @@ same as that of the previous message."\r
+ :group 'notmuch\r
+ :type 'boolean)\r
+ \r
++(defcustom notmuch-always-show-outline nil\r
++ "Should an outline of the thread always be opened?"\r
++ :group 'notmuch\r
++ :type 'boolean)\r
++\r
++(defcustom notmuch-outline-format\r
++ '(("author" . "%s")\r
++ "-"\r
++ ("reldate" . "%s"))\r
++ "Format in which thread-outline entries are displayed\r
++\r
++The following fields are supported: date, reldate, author,\r
++subject. The list can also contain strings as elements which\r
++will be printed literally. This variable can also be a function\r
++that will be given the message as returned by\r
++`notmuch-show-get-message-properties' and should return a\r
++string."\r
++ :group 'notmuch\r
++ :type '(repeat (choice (string :tag "string")\r
++ (cons (choice (const :tag "author" "author")\r
++ (const :tag "subject" "subject")\r
++ (const :tag "date" "date")\r
++ (const :tag "reldate" "reldate"))\r
++ (string :tag "format specifier")))))\r
++\r
++(defface notmuch-outline '((t :inherit default))\r
++ "Face used to display (unhighlighted) lines in thread outlines"\r
++ :group 'notmuch)\r
++\r
++(defvar notmuch-outline-mode-map\r
++ (let ((map (make-sparse-keymap)))\r
++ (define-key map "n" 'next-line)\r
++ (define-key map "p" 'previous-line)\r
++ (define-key map "q" 'notmuch-kill-this-buffer)\r
++ map))\r
++\r
++(defvar notmuch-outline-button-map\r
++ (let ((map (copy-keymap button-map)))\r
++ (define-key map (kbd "<mouse-1>") 'push-button)\r
++ map)\r
++ "Keymap used for buttons in thread outlines.")\r
++\r
+ (defmacro with-current-notmuch-show-message (&rest body)\r
+ "Evaluate body with current buffer set to the text of current message"\r
+ `(save-excursion\r
+@@ -787,6 +829,103 @@ current buffer, if possible."\r
+ (defvar notmuch-show-parent-buffer nil)\r
+ (make-variable-buffer-local 'notmuch-show-parent-buffer)\r
+ \r
++(defun notmuch-goto-marker (m)\r
++"Open corresponding buffer and go to marker position in another window."\r
++ (switch-to-buffer-other-window (marker-buffer m))\r
++ (goto-char (marker-position m)))\r
++\r
++(defun notmuch-show-message-is-visible ()\r
++ "Return t if current message is visible."\r
++ (plist-get (notmuch-show-get-message-properties) :message-visible))\r
++\r
++(defun notmuch-outline-render-format (format)\r
++ "Render FORMAT, interpreted as described for `notmuch-outline-format'"\r
++ (if (functionp format)\r
++ (funcall format (notmuch-show-get-message-properties))\r
++ (mapconcat\r
++ (lambda (entry)\r
++ (if (consp entry)\r
++ (let ((key (car entry))\r
++ (fmt (cdr entry)))\r
++ (cond\r
++ ((equal key "author") (format fmt (notmuch-show-get-from)))\r
++ ((equal key "date") (format fmt (notmuch-show-get-date)))\r
++ ((equal key "subject") (format fmt (notmuch-show-get-subject)))\r
++ ((equal key "reldate")\r
++ (format fmt (plist-get (notmuch-show-get-message-properties)\r
++ :date_relative)))\r
++ (t (concat "Unknown field: " (car entry)))))\r
++ entry))\r
++ format\r
++ " ")))\r
++\r
++(defun notmuch-show-outline-buffer-name (&optional buf)\r
++ "Return the name of the outline buffer for BUF."\r
++ (concat (buffer-name buf) " - outline"))\r
++\r
++(defun notmuch-show-has-outline ()\r
++ "Returns non-nil if there is an outline for the current thread."\r
++ (get-buffer (notmuch-show-outline-buffer-name)))\r
++\r
++(defun notmuch-outline-message ()\r
++ "Outline the message under the point.\r
++\r
++Expects the point to be on the beginning of the first line of the message."\r
++ (lexical-let* ((extent (notmuch-show-message-extent))\r
++ (buffer-name (notmuch-show-outline-buffer-name))\r
++ (goto-message (lambda (btn)\r
++ (select-window (get-buffer-window buffer-name))\r
++ (when (marker-buffer (car extent))\r
++ (notmuch-goto-marker (car extent))\r
++ (when (not (notmuch-show-message-is-visible))\r
++ (notmuch-show-toggle-message))))))\r
++ (let ((indentation 0)\r
++ (button-label (notmuch-outline-render-format\r
++ notmuch-outline-format)))\r
++ ;; this is not very robust if the output of notmuch-show changes\r
++ (while (string-equal (thing-at-point 'char) " ")\r
++ (incf indentation)\r
++ (forward-char))\r
++ (loop for i from 1 to indentation do\r
++ (princ " ")) ;; somewhat ugly\r
++ (princ button-label)\r
++ (with-current-buffer standard-output\r
++ (make-button (line-beginning-position) (line-end-position)\r
++ 'action goto-message\r
++ 'keymap notmuch-outline-button-map\r
++ 'face 'notmuch-outline)\r
++ (put-text-property (line-beginning-position) (line-end-position)\r
++ :message-start (car extent)))\r
++ (princ "\n"))))\r
++\r
++(defun notmuch-show-outline ()\r
++ "Generate an outline for the current buffer.\r
++\r
++This function must only be called in a notmuch-show buffer."\r
++ (interactive)\r
++ (let ((buf-name (notmuch-show-outline-buffer-name)))\r
++ ;; In the extremly rare case that the user might have been doing\r
++ ;; work in a buffer with the exact same name of the outline buffer\r
++ ;; we don't want to kill that buffer\r
++ (kill-buffer-if-not-modified buf-name)\r
++ (save-excursion\r
++ (with-output-to-temp-buffer buf-name\r
++ (with-current-buffer buf-name\r
++ (notmuch-outline-mode))\r
++ (goto-char (point-min))\r
++ (while (not (eobp))\r
++ (notmuch-outline-message)\r
++ (goto-char (marker-position (cdr (notmuch-show-message-extent)))))\r
++ (with-current-buffer buf-name\r
++ (setq buffer-read-only t))))))\r
++ \r
++(defun notmuch-outline-mode ()\r
++ (interactive)\r
++ (kill-all-local-variables)\r
++ (use-local-map notmuch-outline-mode-map)\r
++ (setq major-mode 'notmuch-show-outline-mode\r
++ mode-name "notmuch-show-outline"))\r
++\r
+ ;;;###autoload\r
+ (defun notmuch-show (thread-id &optional parent-buffer query-context buffer-name crypto-switch)\r
+ "Run \"notmuch show\" with the given thread ID and display results.\r
+@@ -846,7 +985,9 @@ function is used. "\r
+ ;; Set the header line to the subject of the first open message.\r
+ (setq header-line-format (notmuch-show-strip-re (notmuch-show-get-subject)))\r
+ \r
+- (notmuch-show-mark-read)))\r
++ (notmuch-show-mark-read)\r
++ (when notmuch-always-show-outline\r
++ (notmuch-show-outline))))\r
+ \r
+ (defvar notmuch-show-stash-map\r
+ (let ((map (make-sparse-keymap)))\r
+@@ -888,6 +1029,7 @@ function is used. "\r
+ (define-key map "P" 'notmuch-show-previous-message)\r
+ (define-key map "n" 'notmuch-show-next-open-message)\r
+ (define-key map "p" 'notmuch-show-previous-open-message)\r
++ (define-key map "o" 'notmuch-show-outline)\r
+ (define-key map (kbd "DEL") 'notmuch-show-rewind)\r
+ (define-key map " " 'notmuch-show-advance-and-archive)\r
+ (define-key map (kbd "M-RET") 'notmuch-show-open-or-close-all)\r
+-- \r
+1.7.5.4\r
+\r