1 Return-Path: <markwalters1009@gmail.com>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id AF4F5431FD6
\r
6 for <notmuch@notmuchmail.org>; Sat, 14 Dec 2013 15:53:40 -0800 (PST)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=0.201 tagged_above=-999 required=5
\r
12 tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,
\r
13 FREEMAIL_ENVFROM_END_DIGIT=1, FREEMAIL_FROM=0.001,
\r
14 RCVD_IN_DNSWL_LOW=-0.7] autolearn=unavailable
\r
15 Received: from olra.theworths.org ([127.0.0.1])
\r
16 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
17 with ESMTP id hYcG+esHyUMZ for <notmuch@notmuchmail.org>;
\r
18 Sat, 14 Dec 2013 15:53:40 -0800 (PST)
\r
19 Received: from mail-wi0-f172.google.com (mail-wi0-f172.google.com
\r
20 [209.85.212.172]) (using TLSv1 with cipher RC4-SHA (128/128 bits))
\r
21 (No client certificate requested)
\r
22 by olra.theworths.org (Postfix) with ESMTPS id 1BFFF431FDD
\r
23 for <notmuch@notmuchmail.org>; Sat, 14 Dec 2013 15:53:38 -0800 (PST)
\r
24 Received: by mail-wi0-f172.google.com with SMTP id en1so736010wid.5
\r
25 for <notmuch@notmuchmail.org>; Sat, 14 Dec 2013 15:53:38 -0800 (PST)
\r
26 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
\r
27 h=from:to:cc:subject:date:message-id:in-reply-to:references;
\r
28 bh=6RRraT+Vza5sw07yf6mzcXfq7FHpVVmI06BVv/F6dG8=;
\r
29 b=GOLUjzkpk8CfrSm5sczDvQ5dyDP42dRhEOwzhz2xYkoSlZ+45rwfUdK6W4i9l7hzv/
\r
30 2vl5xpsaHlXj1iB6QNzyVV9/cruHP+rBLykU2+NbRICGB/WtkqnSmsj3zqBPlTHquoRq
\r
31 bb8NG8+UpPpYmOHRczPtLWTgPwouqGhZqrbQbEIoEXAnikUaUjb26XV0QQxRF1WRotqb
\r
32 xDtx6YJqBiDSoIkOS1ANuto9AxTQ7fvPq3jmub7W8S+vMqbznEfhloUGEDlCXCrh2uem
\r
33 yA1uxokTkDw+jIZiK7JiCMLQhxLtahO867mj6x8fgKpfJj8MCJLrv7wc+sWBX8/Y68cW
\r
35 X-Received: by 10.180.206.11 with SMTP id lk11mr5505535wic.16.1387065217994;
\r
36 Sat, 14 Dec 2013 15:53:37 -0800 (PST)
\r
37 Received: from localhost (93-97-24-31.zone5.bethere.co.uk. [93.97.24.31])
\r
38 by mx.google.com with ESMTPSA id xm7sm11198835wib.0.2013.12.14.15.53.36
\r
39 for <multiple recipients>
\r
40 (version=TLSv1.2 cipher=RC4-SHA bits=128/128);
\r
41 Sat, 14 Dec 2013 15:53:37 -0800 (PST)
\r
42 From: Mark Walters <markwalters1009@gmail.com>
\r
43 To: notmuch@notmuchmail.org
\r
44 Subject: [PATCH v2 3/5] emacs: show: mark tags changed since buffer loaded
\r
45 Date: Sat, 14 Dec 2013 23:53:15 +0000
\r
46 Message-Id: <1387065197-15776-4-git-send-email-markwalters1009@gmail.com>
\r
47 X-Mailer: git-send-email 1.7.9.1
\r
48 In-Reply-To: <1387065197-15776-1-git-send-email-markwalters1009@gmail.com>
\r
49 References: <1387065197-15776-1-git-send-email-markwalters1009@gmail.com>
\r
50 X-BeenThere: notmuch@notmuchmail.org
\r
51 X-Mailman-Version: 2.1.13
\r
53 List-Id: "Use and development of the notmuch mail system."
\r
54 <notmuch.notmuchmail.org>
\r
55 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
56 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
57 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
58 List-Post: <mailto:notmuch@notmuchmail.org>
\r
59 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
60 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
61 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
62 X-List-Received-Date: Sat, 14 Dec 2013 23:53:41 -0000
\r
64 This shows any tags changed in the show buffer since it was loaded or
\r
65 refreshed. By default a removed tag is displayed with strike-through
\r
66 in red (if strike-through is not available, eg on a terminal, inverse
\r
67 video is used instead) and an added tag is displayed underlined in
\r
70 One nice feature is that this makes it clear when a message was unread
\r
71 when you first loaded the buffer (previously the unread tag could be
\r
72 removed before a user realised that it had been unread).
\r
74 The code adds into the existing tag formatting code. The user can
\r
75 specify exactly how a tag should be displayed normally, when deleted,
\r
76 or when added. For convenience an entry for the entry string in the
\r
77 notmuch-tag-formats (and the corresponding notmuch-tag-deleted-formats
\r
78 notmuch-tag-added-formats) is applied to all tags which do not have an
\r
81 This means that a user can tell notmuch not to show deleted tags at
\r
82 all by setting notmuch-tag-deleted-formats to
\r
84 or not to show any deleted tags except "unread" by setting it to
\r
86 ("unread" (propertize tag 'face '(strike-through "red"))))
\r
88 All the variables are customizable; however, more complicated cases
\r
89 like changing the face depending on the type of display will require
\r
92 Currently this overrides notmuch-tag-deleted-formats for the tests
\r
93 setting it to '(("" nil)) so that they get removed from the display
\r
94 and, thus, all tests still pass.
\r
96 emacs/notmuch-show.el | 22 ++++++++--
\r
97 emacs/notmuch-tag.el | 105 +++++++++++++++++++++++++++++++++++--------------
\r
98 test/test-lib.el | 4 ++
\r
99 3 files changed, 96 insertions(+), 35 deletions(-)
\r
101 diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
\r
102 index 1ac80ca..30e84b1 100644
\r
103 --- a/emacs/notmuch-show.el
\r
104 +++ b/emacs/notmuch-show.el
\r
105 @@ -341,11 +341,21 @@ operation on the contents of the current buffer."
\r
106 "Update the displayed tags of the current message."
\r
108 (goto-char (notmuch-show-message-top))
\r
109 - (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
\r
110 - (let ((inhibit-read-only t))
\r
111 - (replace-match (concat "("
\r
112 - (notmuch-tag-format-tags tags)
\r
114 + (let* ((orig-tags (notmuch-show-get-prop :orig-tags))
\r
115 + (all-tags (sort (delete-dups (append tags orig-tags)) #'string<))
\r
116 + (display-tags (mapcar (lambda (tag) (cond ((and (member tag tags) (member tag orig-tags))
\r
118 + ((not (member tag tags))
\r
119 + (cons tag 'deleted))
\r
120 + ((not (member tag orig-tags))
\r
121 + (cons tag 'added))))
\r
124 + (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
\r
125 + (let ((inhibit-read-only t))
\r
126 + (replace-match (concat "("
\r
127 + (notmuch-tag-format-tags display-tags)
\r
130 (defun notmuch-clean-address (address)
\r
131 "Try to clean a single email ADDRESS for display. Return a cons
\r
132 @@ -1167,6 +1177,8 @@ function is used."
\r
134 (jit-lock-register #'notmuch-show-buttonise-links)
\r
136 + (notmuch-show-mapc (lambda () (notmuch-show-set-prop :orig-tags (notmuch-show-get-tags))))
\r
138 ;; Set the header line to the subject of the first message.
\r
139 (setq header-line-format (notmuch-sanitize (notmuch-show-strip-re (notmuch-show-get-subject))))
\r
141 diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
\r
142 index b60f46c..81ce287 100644
\r
143 --- a/emacs/notmuch-tag.el
\r
144 +++ b/emacs/notmuch-tag.el
\r
147 (require 'notmuch-lib)
\r
149 -(defcustom notmuch-tag-formats
\r
150 - '(("unread" (propertize tag 'face '(:foreground "red")))
\r
151 - ("flagged" (propertize tag 'face '(:foreground "blue"))
\r
152 - (notmuch-tag-format-image-data tag (notmuch-tag-star-icon))))
\r
153 - "Custom formats for individual tags.
\r
155 -This gives a list that maps from tag names to lists of formatting
\r
156 -expressions. The car of each element gives a tag name and the
\r
157 -cdr gives a list of Elisp expressions that modify the tag. If
\r
158 -the list is empty, the tag will simply be hidden. Otherwise,
\r
159 -each expression will be evaluated in order: for the first
\r
160 -expression, the variable `tag' will be bound to the tag name; for
\r
161 -each later expression, the variable `tag' will be bound to the
\r
162 -result of the previous expression. In this way, each expression
\r
163 -can build on the formatting performed by the previous expression.
\r
164 -The result of the last expression will displayed in place of the
\r
167 -For example, to replace a tag with another string, simply use
\r
168 -that string as a formatting expression. To change the foreground
\r
169 -of a tag to red, use the expression
\r
170 - (propertize tag 'face '(:foreground \"red\"))
\r
172 -See also `notmuch-tag-format-image', which can help replace tags
\r
175 - :group 'notmuch-search
\r
176 - :group 'notmuch-show
\r
177 +(define-widget 'notmuch-tag-format-type 'lazy
\r
178 + "Customize widget for notmuch-tag-format and friends"
\r
179 :type '(alist :key-type (string :tag "Tag")
\r
182 @@ -82,6 +56,61 @@ with images."
\r
183 (string :tag "Custom")))
\r
184 (sexp :tag "Custom")))))
\r
186 +(defcustom notmuch-tag-formats
\r
187 + '(("unread" (propertize tag 'face '(:foreground "red")))
\r
188 + ("flagged" (propertize tag 'face '(:foreground "blue"))
\r
189 + (notmuch-tag-format-image-data tag (notmuch-tag-star-icon))))
\r
190 + "Custom formats for individual tags.
\r
192 +This gives a list that maps from tag names to lists of formatting
\r
193 +expressions. The car of each element gives a tag name and the
\r
194 +cdr gives a list of Elisp expressions that modify the tag. If the
\r
195 +car is an empty string it matches all tags that do not have an
\r
196 +explicit match. If the list is empty, the tag will simply be
\r
197 +hidden. Otherwise, each expression will be evaluated in order:
\r
198 +for the first expression, the variable `tag' will be bound to the
\r
199 +tag name; for each later expression, the variable `tag' will be
\r
200 +bound to the result of the previous expression. In this way,
\r
201 +each expression can build on the formatting performed by the
\r
202 +previous expression. The result of the last expression will
\r
203 +displayed in place of the tag.
\r
205 +For example, to replace a tag with another string, simply use
\r
206 +that string as a formatting expression. To change the foreground
\r
207 +of a tag to red, use the expression
\r
208 + (propertize tag 'face '(:foreground \"red\"))
\r
210 +See also `notmuch-tag-format-image', which can help replace tags
\r
212 + :group 'notmuch-search
\r
213 + :group 'notmuch-show
\r
214 + :type 'notmuch-tag-format-type)
\r
216 +(defcustom notmuch-tag-deleted-formats
\r
217 + '(("" (propertize tag 'face
\r
218 + (if (display-supports-face-attributes-p '(:strike-through "red"))
\r
219 + '(:strike-through "red")
\r
220 + '(:inverse-video t)))))
\r
221 + "Custom formats for tags when deleted.
\r
223 +By default this shows deleted tags with strike-through in red,
\r
224 +unless strike-through is not available (e.g., emacs is running in
\r
225 +a terminal) in which case it uses inverse video. To hide deleted
\r
226 +tags completely set this to
\r
229 +See `notmuch-tag-formats' for full documentation."
\r
230 + :group 'notmuch-show
\r
231 + :type 'notmuch-tag-format-type)
\r
233 +(defcustom notmuch-tag-added-formats
\r
234 + '(("" (propertize tag 'face '(:underline "green"))))
\r
235 + "Custom formats for tags when added.
\r
237 +See `notmuch-tag-formats' for full documentation."
\r
238 + :group 'notmuch-show
\r
239 + :type 'notmuch-tag-format-type)
\r
241 (defun notmuch-tag-format-image-data (tag data)
\r
242 "Replace TAG with image DATA, if available.
\r
244 @@ -136,8 +165,24 @@ This can be used with `notmuch-tag-format-image-data'."
\r
247 (defun notmuch-tag-format-tag (tag)
\r
248 - "Format TAG by looking into `notmuch-tag-formats'."
\r
249 - (let ((formats (assoc tag notmuch-tag-formats)))
\r
250 + "Format TAG by looking into `notmuch-tag-formats'.
\r
252 +TAG can either be a string for a tag or a cons cell. In the
\r
253 +latter case the car of the cons cell is the tag string, the cdr
\r
254 +should be 'deleted or 'added to indicate whether the tag has been
\r
255 +deleted or added. The format for tag is looked up in
\r
256 +`notmuch-tag-formats' or `notmuch-tag-deleted-formats' or
\r
257 +`notmuch-tag-added-formats' as appropriate."
\r
258 + (let* ((status (if (consp tag) (cdr tag)))
\r
259 + (tag (if (consp tag) (car tag) tag))
\r
260 + (status-formats (cond
\r
261 + ((eq status 'deleted)
\r
262 + notmuch-tag-deleted-formats)
\r
263 + ((eq status 'added)
\r
264 + notmuch-tag-added-formats)
\r
265 + (t notmuch-tag-formats)))
\r
266 + (formats (or (append (assoc tag status-formats))
\r
267 + (append (assoc "" status-formats)))))
\r
269 ((null formats) ;; - Tag not in `notmuch-tag-formats',
\r
270 tag) ;; the format is the tag itself.
\r
271 diff --git a/test/test-lib.el b/test/test-lib.el
\r
272 index 1c9e224..a1b40b7 100644
\r
273 --- a/test/test-lib.el
\r
274 +++ b/test/test-lib.el
\r
275 @@ -174,3 +174,7 @@ nothing."
\r
276 (dolist (form body ret)
\r
277 (setq ret (eval form))
\r
278 (notmuch-post-command))))
\r
280 +;; hide deleted tags
\r
281 +(setq notmuch-tag-deleted-formats
\r