1 Return-Path: <damien.cassou@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 56FB4431FB6
\r
6 for <notmuch@notmuchmail.org>; Wed, 6 Feb 2013 06:54:10 -0800 (PST)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=-0.799 tagged_above=-999 required=5
\r
12 tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,
\r
13 FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled
\r
14 Received: from olra.theworths.org ([127.0.0.1])
\r
15 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
16 with ESMTP id eT2flK3b42Lq for <notmuch@notmuchmail.org>;
\r
17 Wed, 6 Feb 2013 06:54:08 -0800 (PST)
\r
18 Received: from mail-wg0-f43.google.com (mail-wg0-f43.google.com
\r
19 [74.125.82.43]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (No client
\r
20 certificate requested) by olra.theworths.org (Postfix) with ESMTPS id
\r
21 9E5EB431FAF for <notmuch@notmuchmail.org>; Wed, 6 Feb 2013 06:54:07 -0800
\r
23 Received: by mail-wg0-f43.google.com with SMTP id e12so1144316wge.10
\r
24 for <notmuch@notmuchmail.org>; Wed, 06 Feb 2013 06:54:06 -0800 (PST)
\r
25 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
\r
26 h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to
\r
27 :references:mime-version:content-type:content-transfer-encoding;
\r
28 bh=xa8ypnoW75jJBtOX0s0Oxv09Zy5HLrnHMMHZSHv05e8=;
\r
29 b=Nl9DSiYV30gcVK2e+blUVaeAw25C8NI45a1j7erFUDb98DoVyCDzZ0NSfFCTFgQTT5
\r
30 KFWibnK8JS2pX6CLENw2Z376HegCki4c2/KrJeAUSeeeNxem1DIiEaIBey4NvIvGpj7u
\r
31 c31FCUWdcZGKkbmhnCIiqnqt+QIpBVAc988UklRRC2+x5icBncKMyxNd5jYimGcg8YUq
\r
32 3WjTu8BKMTiiZPUO9yIN3aWQjtesfMVayMfXpORM1F2o/c2XfClQf7DR0L7EBr+htqnh
\r
33 AS94zqNidLzEywk8HUwuQUoliUzPElNZVXoouHya25XnmxVteIjnN7iONzhg82Op+Akx
\r
35 X-Received: by 10.180.85.8 with SMTP id d8mr5643285wiz.4.1360162446497;
\r
36 Wed, 06 Feb 2013 06:54:06 -0800 (PST)
\r
37 Received: from luz3.lille.inria.fr ([193.51.236.44])
\r
38 by mx.google.com with ESMTPS id df2sm3441008wib.0.2013.02.06.06.54.05
\r
39 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128);
\r
40 Wed, 06 Feb 2013 06:54:05 -0800 (PST)
\r
41 From: Damien Cassou <damien.cassou@gmail.com>
\r
42 To: notmuch@notmuchmail.org
\r
43 Subject: [PATCH 2/2] emacs: possibility to customize the rendering of tags
\r
44 Date: Wed, 6 Feb 2013 15:53:55 +0100
\r
45 Message-Id: <1360162435-29506-3-git-send-email-damien.cassou@gmail.com>
\r
46 X-Mailer: git-send-email 1.7.10.4
\r
47 In-Reply-To: <1360162435-29506-1-git-send-email-damien.cassou@gmail.com>
\r
48 References: <1360162435-29506-1-git-send-email-damien.cassou@gmail.com>
\r
50 Content-Type: text/plain; charset=UTF-8
\r
51 Content-Transfer-Encoding: 8bit
\r
52 X-BeenThere: notmuch@notmuchmail.org
\r
53 X-Mailman-Version: 2.1.13
\r
55 List-Id: "Use and development of the notmuch mail system."
\r
56 <notmuch.notmuchmail.org>
\r
57 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
58 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
59 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
60 List-Post: <mailto:notmuch@notmuchmail.org>
\r
61 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
62 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
63 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
64 X-List-Received-Date: Wed, 06 Feb 2013 14:54:10 -0000
\r
66 This patch extracts the rendering of tags in notmuch-show to
\r
67 the notmuch-tag file.
\r
69 This file introduces a `notmuch-tag-formats' variable that associates
\r
70 each tag to a particular format. This variable can be customized
\r
71 thanks to the work of Austin Clements. For example,
\r
73 '(("unread" (propertize tag 'face '(:foreground "red")))
\r
74 ("flagged" (notmuch-tag-format-image tag "star.svg")))
\r
76 associates a red foreground to the "unread" tag and a star picture to
\r
79 Signed-off-by: Damien Cassou <damien.cassou@gmail.com>
\r
81 emacs/notmuch-show.el | 6 +-
\r
82 emacs/notmuch-tag.el | 221 ++++++++++++++++++++++++++++++++++++++++++++++++-
\r
83 emacs/notmuch.el | 5 +-
\r
84 3 files changed, 224 insertions(+), 8 deletions(-)
\r
86 diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
\r
87 index 1864dd1..bb4bd92 100644
\r
88 --- a/emacs/notmuch-show.el
\r
89 +++ b/emacs/notmuch-show.el
\r
90 @@ -362,8 +362,7 @@ operation on the contents of the current buffer."
\r
91 (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
\r
92 (let ((inhibit-read-only t))
\r
93 (replace-match (concat "("
\r
94 - (propertize (mapconcat 'identity tags " ")
\r
95 - 'face 'notmuch-tag-face)
\r
96 + (notmuch-tag-format-tags tags)
\r
99 (defun notmuch-clean-address (address)
\r
100 @@ -441,8 +440,7 @@ message at DEPTH in the current thread."
\r
104 - (propertize (mapconcat 'identity tags " ")
\r
105 - 'face 'notmuch-tag-face)
\r
106 + (notmuch-tag-format-tags tags)
\r
108 (overlay-put (make-overlay start (point)) 'face 'notmuch-message-summary-face)))
\r
110 diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
\r
111 index 4fce3a9..2a64d48 100644
\r
112 --- a/emacs/notmuch-tag.el
\r
113 +++ b/emacs/notmuch-tag.el
\r
115 ;; notmuch-tag.el --- tag messages within emacs
\r
117 +;; Copyright © Damien Cassou
\r
118 ;; Copyright © Carl Worth
\r
120 ;; This file is part of Notmuch.
\r
121 @@ -18,11 +19,229 @@
\r
122 ;; along with Notmuch. If not, see <http://www.gnu.org/licenses/>.
\r
124 ;; Authors: Carl Worth <cworth@cworth.org>
\r
125 +;; Damien Cassou <damien.cassou@gmail.com>
\r
130 -(eval-when-compile (require 'cl))
\r
133 (require 'notmuch-lib)
\r
135 +(defcustom notmuch-tag-formats
\r
136 + '(("unread" (propertize tag 'face '(:foreground "red")))
\r
137 + ("flagged" (notmuch-tag-format-image-data tag (notmuch-tag-star-icon))))
\r
138 + "Custom formats for individual tags.
\r
140 +This gives a list that maps from tag names to lists of formatting
\r
141 +expressions. The car of each element gives a tag name and the
\r
142 +cdr gives a list of Elisp expressions that modify the tag. If
\r
143 +the list is empty, the tag will simply be hidden. Otherwise,
\r
144 +each expression will be evaluated in order: for the first
\r
145 +expression, the variable `tag' will be bound to the tag name; for
\r
146 +each later expression, the variable `tag' will be bound to the
\r
147 +result of the previous expression. In this way, each expression
\r
148 +can build on the formatting performed by the previous expression.
\r
149 +The result of the last expression will displayed in place of the
\r
152 +For example, to replace a tag with another string, simply use
\r
153 +that string as a formatting expression. To change the foreground
\r
154 +of a tag to red, use the expression
\r
155 + (propertize tag 'face '(:foreground \"red\"))
\r
157 +See also `notmuch-tag-format-image', which can help replace tags
\r
160 + :group 'notmuch-search
\r
161 + :group 'notmuch-show
\r
162 + :type '(alist :key-type (string :tag "Tag")
\r
165 + (radio :format "%v"
\r
166 + (const :tag "Hidden" nil)
\r
167 + (set :tag "Modified"
\r
168 + (string :tag "Display as")
\r
169 + (list :tag "Face" :extra-offset -4
\r
170 + (const :format "" :inline t
\r
171 + (propertize tag 'face))
\r
172 + (list :format "%v"
\r
173 + (const :format "" quote)
\r
174 + custom-face-edit))
\r
175 + (list :format "%v" :extra-offset -4
\r
176 + (const :format "" :inline t
\r
177 + (notmuch-tag-format-image-data tag))
\r
178 + (choice :tag "Image"
\r
179 + (const :tag "Star"
\r
180 + (notmuch-tag-star-icon))
\r
181 + (const :tag "Empty star"
\r
182 + (notmuch-tag-star-empty-icon))
\r
183 + (const :tag "Tag"
\r
184 + (notmuch-tag-tag-icon))
\r
185 + (string :tag "Custom")))
\r
186 + (sexp :tag "Custom")))))
\r
188 +(defun notmuch-tag-format-image-data (tag data)
\r
189 + "Replace TAG with image DATA, if available.
\r
191 +This function returns a propertized string that will display image
\r
192 +DATA in place of TAG.This is designed for use in
\r
193 +`notmuch-tag-formats'.
\r
195 +DATA is the content of an SVG picture (e.g., as returned by
\r
196 +`notmuch-tag-star-icon')."
\r
197 + (propertize tag 'display
\r
198 + `(image :type svg
\r
201 + :mask heuristic)))
\r
203 +(defun notmuch-tag-star-icon ()
\r
204 + "Return SVG data representing a star icon.
\r
205 +This can be used with `notmuch-tag-format-image-data'."
\r
206 + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
\r
208 + xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
\r
209 + xmlns:cc=\"http://creativecommons.org/ns#\"
\r
210 + xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
\r
211 + xmlns:svg=\"http://www.w3.org/2000/svg\"
\r
212 + xmlns=\"http://www.w3.org/2000/svg\"
\r
220 + id=\"metadata7\">
\r
224 + <dc:format>image/svg+xml</dc:format>
\r
226 + rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />
\r
227 + <dc:title></dc:title>
\r
232 + transform=\"translate(-242.81601,-315.59635)\"
\r
235 + d=\"m 290.25762,334.31206 -17.64143,-11.77975 -19.70508,7.85447 5.75171,-20.41814 -13.55925,-16.31348 21.19618,-0.83936 11.325,-17.93675 7.34825,19.89939 20.55849,5.22795 -16.65471,13.13786 z\"
\r
236 + transform=\"matrix(0.2484147,-0.02623394,0.02623394,0.2484147,174.63605,255.37691)\"
\r
238 + style=\"fill:#ffff00;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" />
\r
242 +(defun notmuch-tag-star-empty-icon ()
\r
243 + "Return SVG data representing an empty star icon.
\r
244 +This can be used with `notmuch-tag-format-image-data'."
\r
245 + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
\r
246 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
\r
249 + xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
\r
250 + xmlns:cc=\"http://creativecommons.org/ns#\"
\r
251 + xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
\r
252 + xmlns:svg=\"http://www.w3.org/2000/svg\"
\r
253 + xmlns=\"http://www.w3.org/2000/svg\"
\r
261 + id=\"metadata7\">
\r
265 + <dc:format>image/svg+xml</dc:format>
\r
267 + rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />
\r
268 + <dc:title></dc:title>
\r
273 + transform=\"translate(-242.81601,-315.59635)\"
\r
276 + d=\"m 290.25762,334.31206 -17.64143,-11.77975 -19.70508,7.85447 5.75171,-20.41814 -13.55925,-16.31348 21.19618,-0.83936 11.325,-17.93675 7.34825,19.89939 20.55849,5.22795 -16.65471,13.13786 z\"
\r
277 + transform=\"matrix(0.2484147,-0.02623394,0.02623394,0.2484147,174.63605,255.37691)\"
\r
279 + style=\"fill:#d6d6d1;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" />
\r
283 +(defun notmuch-tag-tag-icon ()
\r
284 + "Return SVG data representing a tag icon.
\r
285 +This can be used with `notmuch-tag-format-image-data'."
\r
286 + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
\r
287 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
\r
290 + xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
\r
291 + xmlns:cc=\"http://creativecommons.org/ns#\"
\r
292 + xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
\r
293 + xmlns:svg=\"http://www.w3.org/2000/svg\"
\r
294 + xmlns=\"http://www.w3.org/2000/svg\"
\r
300 + id=\"defs3807\" />
\r
302 + id=\"metadata3810\">
\r
306 + <dc:format>image/svg+xml</dc:format>
\r
308 + rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />
\r
309 + <dc:title></dc:title>
\r
314 + transform=\"translate(0,-1036.3622)\"
\r
317 + d=\"m 0.44642857,1040.9336 12.50000043,0 2.700893,3.6161 -2.700893,3.616 -12.50000043,0 z\"
\r
319 + style=\"fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1\" />
\r
323 +(defun notmuch-tag-get-format (tag)
\r
324 + "Return the format for TAG in `notmuch-tag-formats'."
\r
325 + (let ((formats (assoc tag notmuch-tag-formats)))
\r
327 + ((null formats) ;; - Tag not in `notmuch-tag-formats',
\r
328 + tag) ;; the format is then the tag itself.
\r
329 + ((null (cdr formats)) ;; - Tag was deliberately hidden,
\r
330 + nil) ;; no format must be returned
\r
331 + (t ;; - Tag was found and has formats,
\r
332 + (let ((tag tag)) ;; we must apply all the formats.
\r
333 + (dolist (format (cdr formats) tag)
\r
334 + (setq tag (eval format))))))))
\r
336 +(defun notmuch-tag-list-get-format (tags)
\r
337 + (mapconcat #'identity
\r
338 + ;; nil indicated that the tag was deliberately hidden
\r
339 + (delq nil (mapcar #'notmuch-tag-get-format tags))
\r
342 +(defun notmuch-tag-format-tags (tags)
\r
343 + "Return a string representing TAGS with their formats."
\r
344 + (notmuch-combine-face-text-property-string
\r
345 + (notmuch-tag-list-get-format tags)
\r
346 + 'notmuch-tag-face
\r
349 (defcustom notmuch-before-tag-hook nil
\r
350 "Hooks that are run before tags of a message are modified.
\r
352 diff --git a/emacs/notmuch.el b/emacs/notmuch.el
\r
353 index c98a4fe..e58c51d 100644
\r
354 --- a/emacs/notmuch.el
\r
355 +++ b/emacs/notmuch.el
\r
356 @@ -797,9 +797,8 @@ non-authors is found, assume that all of the authors match."
\r
357 (notmuch-search-insert-authors format-string (plist-get result :authors)))
\r
359 ((string-equal field "tags")
\r
360 - (let ((tags-str (mapconcat 'identity (plist-get result :tags) " ")))
\r
361 - (insert (propertize (format format-string tags-str)
\r
362 - 'face 'notmuch-tag-face))))))
\r
363 + (let ((tags (plist-get result :tags)))
\r
364 + (insert (format format-string (notmuch-tag-format-tags tags)))))))
\r
366 (defun notmuch-search-show-result (result &optional pos)
\r
367 "Insert RESULT at POS or the end of the buffer if POS is null."
\r