[PATCH 2/3] emacs: Add thread-outline functionality
authorDaniel Schoepe <daniel.schoepe@googlemail.com>
Sun, 12 Jun 2011 23:31:19 +0000 (01:31 +0200)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:38:36 +0000 (09:38 -0800)
79/d77f677edf30dea45672d01949831b1dd93263 [new file with mode: 0644]

diff --git a/79/d77f677edf30dea45672d01949831b1dd93263 b/79/d77f677edf30dea45672d01949831b1dd93263
new file mode 100644 (file)
index 0000000..4b5836c
--- /dev/null
@@ -0,0 +1,274 @@
+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