unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* [PATCH v2 0/2] Customize how each tag is displayed
@ 2013-02-06 14:53 Damien Cassou
  2013-02-06 14:53 ` [PATCH 1/2] emacs: Add notmuch-combine-face-text-property-string Damien Cassou
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Damien Cassou @ 2013-02-06 14:53 UTC (permalink / raw)
  To: notmuch

[PATCH 1/2] emacs: Add notmuch-combine-face-text-property-string
[PATCH 2/2] emacs: possibility to customize the rendering of tags

These patches are the first of an upcoming series whose goal is to
integrate notmuch-labeler into notmuch. See the following for more
details: https://github.com/DamienCassou/notmuch-labeler

- These patches depend on
id:1360013822-6562-1-git-send-email-amdragon@mit.edu
"notmuch-combine-face-text-property improvements" by Austin Clements.

- This series does not have any unit-test to make it smaller and more
  amenable to comments. I will send a patch when requested.

- Patch 1/2 just add a convenient function to call
  `notmuch-combine-face-text-property' on strings.

- Patch 2/2 introduces `notmuch-tagger-formats', a list of pairs (KEY
  FORMAT) to format a tag matching KEY using a special format.
  Currently, an example of such a list is:

   '(("unread" (propertize tag 'face '(:foreground "red")))
     ("flagged" (notmuch-tag-format-image-data tag (notmuch-tag-star-icon))))

  to set the unread tag to be red and the flagged tag to have a star
  picture attached. This variable can be customized, thanks to the
  work of Austin Clements.

- Patch 2/2 also provides 3 pictures, all in SVG and all directly
  embedded in the elisp source code as proposed by Austin Clements and
  Tomi Ollila.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/2] emacs: Add notmuch-combine-face-text-property-string
  2013-02-06 14:53 [PATCH v2 0/2] Customize how each tag is displayed Damien Cassou
@ 2013-02-06 14:53 ` Damien Cassou
  2013-02-06 14:53 ` [PATCH 2/2] emacs: possibility to customize the rendering of tags Damien Cassou
  2013-03-13  9:43 ` [PATCH v2 0/2] Customize how each tag is displayed Damien Cassou
  2 siblings, 0 replies; 9+ messages in thread
From: Damien Cassou @ 2013-02-06 14:53 UTC (permalink / raw)
  To: notmuch

Signed-off-by: Damien Cassou <damien.cassou@gmail.com>
---
 emacs/notmuch-lib.el |    8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
index 307133b..7e83371 100644
--- a/emacs/notmuch-lib.el
+++ b/emacs/notmuch-lib.el
@@ -342,6 +342,14 @@ OBJECT."
 	(setq pos next))))
   object)
 
+(defun notmuch-combine-face-text-property-string (string face &optional below)
+  (notmuch-combine-face-text-property
+   0
+   (length string)
+   face
+   below
+   string))
+
 (defun notmuch-logged-error (msg &optional extra)
   "Log MSG and EXTRA to *Notmuch errors* and signal MSG.
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/2] emacs: possibility to customize the rendering of tags
  2013-02-06 14:53 [PATCH v2 0/2] Customize how each tag is displayed Damien Cassou
  2013-02-06 14:53 ` [PATCH 1/2] emacs: Add notmuch-combine-face-text-property-string Damien Cassou
@ 2013-02-06 14:53 ` Damien Cassou
  2013-03-16  4:10   ` Austin Clements
  2013-03-13  9:43 ` [PATCH v2 0/2] Customize how each tag is displayed Damien Cassou
  2 siblings, 1 reply; 9+ messages in thread
From: Damien Cassou @ 2013-02-06 14:53 UTC (permalink / raw)
  To: notmuch

This patch extracts the rendering of tags in notmuch-show to
the notmuch-tag file.

This file introduces a `notmuch-tag-formats' variable that associates
each tag to a particular format. This variable can be customized
thanks to the work of Austin Clements. For example,

  '(("unread" (propertize tag 'face '(:foreground "red")))
    ("flagged" (notmuch-tag-format-image tag "star.svg")))

associates a red foreground to the "unread" tag and a star picture to
the "flagged" tag.

Signed-off-by: Damien Cassou <damien.cassou@gmail.com>
---
 emacs/notmuch-show.el |    6 +-
 emacs/notmuch-tag.el  |  221 ++++++++++++++++++++++++++++++++++++++++++++++++-
 emacs/notmuch.el      |    5 +-
 3 files changed, 224 insertions(+), 8 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 1864dd1..bb4bd92 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -362,8 +362,7 @@ operation on the contents of the current buffer."
     (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
 	(let ((inhibit-read-only t))
 	  (replace-match (concat "("
-				 (propertize (mapconcat 'identity tags " ")
-					     'face 'notmuch-tag-face)
+				 (notmuch-tag-format-tags tags)
 				 ")"))))))
 
 (defun notmuch-clean-address (address)
@@ -441,8 +440,7 @@ message at DEPTH in the current thread."
 	    " ("
 	    date
 	    ") ("
-	    (propertize (mapconcat 'identity tags " ")
-			'face 'notmuch-tag-face)
+	    (notmuch-tag-format-tags tags)
 	    ")\n")
     (overlay-put (make-overlay start (point)) 'face 'notmuch-message-summary-face)))
 
diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
index 4fce3a9..2a64d48 100644
--- a/emacs/notmuch-tag.el
+++ b/emacs/notmuch-tag.el
@@ -1,5 +1,6 @@
 ;; notmuch-tag.el --- tag messages within emacs
 ;;
+;; Copyright © Damien Cassou
 ;; Copyright © Carl Worth
 ;;
 ;; This file is part of Notmuch.
@@ -18,11 +19,229 @@
 ;; along with Notmuch.  If not, see <http://www.gnu.org/licenses/>.
 ;;
 ;; Authors: Carl Worth <cworth@cworth.org>
+;;          Damien Cassou <damien.cassou@gmail.com>
+;;
+;;; Code:
+;;
 
-(eval-when-compile (require 'cl))
+(require 'cl)
 (require 'crm)
 (require 'notmuch-lib)
 
+(defcustom notmuch-tag-formats
+  '(("unread" (propertize tag 'face '(:foreground "red")))
+    ("flagged" (notmuch-tag-format-image-data tag (notmuch-tag-star-icon))))
+  "Custom formats for individual tags.
+
+This gives a list that maps from tag names to lists of formatting
+expressions.  The car of each element gives a tag name and the
+cdr gives a list of Elisp expressions that modify the tag.  If
+the list is empty, the tag will simply be hidden.  Otherwise,
+each expression will be evaluated in order: for the first
+expression, the variable `tag' will be bound to the tag name; for
+each later expression, the variable `tag' will be bound to the
+result of the previous expression.  In this way, each expression
+can build on the formatting performed by the previous expression.
+The result of the last expression will displayed in place of the
+tag.
+
+For example, to replace a tag with another string, simply use
+that string as a formatting expression.  To change the foreground
+of a tag to red, use the expression
+  (propertize tag 'face '(:foreground \"red\"))
+
+See also `notmuch-tag-format-image', which can help replace tags
+with images."
+
+  :group 'notmuch-search
+  :group 'notmuch-show
+  :type '(alist :key-type (string :tag "Tag")
+		:extra-offset -3
+		:value-type
+		(radio :format "%v"
+		       (const :tag "Hidden" nil)
+		       (set :tag "Modified"
+			    (string :tag "Display as")
+			    (list :tag "Face" :extra-offset -4
+				  (const :format "" :inline t
+					 (propertize tag 'face))
+				  (list :format "%v"
+					(const :format "" quote)
+					custom-face-edit))
+			    (list :format "%v" :extra-offset -4
+				  (const :format "" :inline t
+					 (notmuch-tag-format-image-data tag))
+				  (choice :tag "Image"
+					  (const :tag "Star"
+						 (notmuch-tag-star-icon))
+					  (const :tag "Empty star"
+						 (notmuch-tag-star-empty-icon))
+					  (const :tag "Tag"
+						 (notmuch-tag-tag-icon))
+					  (string :tag "Custom")))
+			    (sexp :tag "Custom")))))
+
+(defun notmuch-tag-format-image-data (tag data)
+  "Replace TAG with image DATA, if available.
+
+This function returns a propertized string that will display image
+DATA in place of TAG.This is designed for use in
+`notmuch-tag-formats'.
+
+DATA is the content of an SVG picture (e.g., as returned by
+`notmuch-tag-star-icon')."
+  (propertize tag 'display
+	      `(image :type svg
+		      :data ,data
+		      :ascent center
+		      :mask heuristic)))
+
+(defun notmuch-tag-star-icon ()
+  "Return SVG data representing a star icon.
+This can be used with `notmuch-tag-format-image-data'."
+  "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
+<svg
+   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
+   xmlns:cc=\"http://creativecommons.org/ns#\"
+   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
+   xmlns:svg=\"http://www.w3.org/2000/svg\"
+   xmlns=\"http://www.w3.org/2000/svg\"
+   version=\"1.1\"
+   width=\"16\"
+   height=\"16\"
+   id=\"svg2\">
+  <defs
+     id=\"defs4\" />
+  <metadata
+     id=\"metadata7\">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about=\"\">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     transform=\"translate(-242.81601,-315.59635)\"
+     id=\"layer1\">
+    <path
+       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\"
+       transform=\"matrix(0.2484147,-0.02623394,0.02623394,0.2484147,174.63605,255.37691)\"
+       id=\"path2985\"
+       style=\"fill:#ffff00;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" />
+  </g>
+</svg>")
+
+(defun notmuch-tag-star-empty-icon ()
+  "Return SVG data representing an empty star icon.
+This can be used with `notmuch-tag-format-image-data'."
+  "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
+   xmlns:cc=\"http://creativecommons.org/ns#\"
+   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
+   xmlns:svg=\"http://www.w3.org/2000/svg\"
+   xmlns=\"http://www.w3.org/2000/svg\"
+   version=\"1.1\"
+   width=\"16\"
+   height=\"16\"
+   id=\"svg2\">
+  <defs
+     id=\"defs4\" />
+  <metadata
+     id=\"metadata7\">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about=\"\">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     transform=\"translate(-242.81601,-315.59635)\"
+     id=\"layer1\">
+    <path
+       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\"
+       transform=\"matrix(0.2484147,-0.02623394,0.02623394,0.2484147,174.63605,255.37691)\"
+       id=\"path2985\"
+       style=\"fill:#d6d6d1;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" />
+  </g>
+</svg>")
+
+(defun notmuch-tag-tag-icon ()
+  "Return SVG data representing a tag icon.
+This can be used with `notmuch-tag-format-image-data'."
+  "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
+   xmlns:cc=\"http://creativecommons.org/ns#\"
+   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
+   xmlns:svg=\"http://www.w3.org/2000/svg\"
+   xmlns=\"http://www.w3.org/2000/svg\"
+   version=\"1.1\"
+   width=\"16\"
+   height=\"16\"
+   id=\"svg3805\">
+  <defs
+     id=\"defs3807\" />
+  <metadata
+     id=\"metadata3810\">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about=\"\">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     transform=\"translate(0,-1036.3622)\"
+     id=\"layer1\">
+    <path
+       d=\"m 0.44642857,1040.9336 12.50000043,0 2.700893,3.6161 -2.700893,3.616 -12.50000043,0 z\"
+       id=\"rect4321\"
+       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\" />
+  </g>
+</svg>")
+
+(defun notmuch-tag-get-format (tag)
+  "Return the format for TAG in `notmuch-tag-formats'."
+  (let ((formats (assoc tag notmuch-tag-formats)))
+    (cond
+     ((null formats)		;; - Tag not in `notmuch-tag-formats',
+      tag)			;; the format is then the tag itself.
+     ((null (cdr formats))	;; - Tag was deliberately hidden,
+      nil)			;; no format must be returned
+     (t				;; - Tag was found and has formats,
+      (let ((tag tag))		;; we must apply all the formats.
+	(dolist (format (cdr formats) tag)
+	  (setq tag (eval format))))))))
+
+(defun notmuch-tag-list-get-format (tags)
+  (mapconcat #'identity
+	     ;; nil indicated that the tag was deliberately hidden
+	     (delq nil (mapcar #'notmuch-tag-get-format tags))
+	     " "))
+
+(defun notmuch-tag-format-tags (tags)
+  "Return a string representing TAGS with their formats."
+  (notmuch-combine-face-text-property-string
+   (notmuch-tag-list-get-format tags)
+   'notmuch-tag-face
+   t))
+
 (defcustom notmuch-before-tag-hook nil
   "Hooks that are run before tags of a message are modified.
 
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index c98a4fe..e58c51d 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -797,9 +797,8 @@ non-authors is found, assume that all of the authors match."
     (notmuch-search-insert-authors format-string (plist-get result :authors)))
 
    ((string-equal field "tags")
-    (let ((tags-str (mapconcat 'identity (plist-get result :tags) " ")))
-      (insert (propertize (format format-string tags-str)
-			  'face 'notmuch-tag-face))))))
+    (let ((tags (plist-get result :tags)))
+      (insert (format format-string (notmuch-tag-format-tags tags)))))))
 
 (defun notmuch-search-show-result (result &optional pos)
   "Insert RESULT at POS or the end of the buffer if POS is null."
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/2] Customize how each tag is displayed
  2013-02-06 14:53 [PATCH v2 0/2] Customize how each tag is displayed Damien Cassou
  2013-02-06 14:53 ` [PATCH 1/2] emacs: Add notmuch-combine-face-text-property-string Damien Cassou
  2013-02-06 14:53 ` [PATCH 2/2] emacs: possibility to customize the rendering of tags Damien Cassou
@ 2013-03-13  9:43 ` Damien Cassou
  2 siblings, 0 replies; 9+ messages in thread
From: Damien Cassou @ 2013-03-13  9:43 UTC (permalink / raw)
  To: notmuch mailing list

On Wed, Feb 6, 2013 at 3:53 PM, Damien Cassou <damien.cassou@gmail.com> wrote:
> [PATCH 1/2] emacs: Add notmuch-combine-face-text-property-string
> [PATCH 2/2] emacs: possibility to customize the rendering of tags


still not a single comment after more than one month

-- 
Damien Cassou
http://damiencassou.seasidehosting.st

"Success is the ability to go from one failure to another without
losing enthusiasm."
Winston Churchill

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] emacs: possibility to customize the rendering of tags
  2013-02-06 14:53 ` [PATCH 2/2] emacs: possibility to customize the rendering of tags Damien Cassou
@ 2013-03-16  4:10   ` Austin Clements
  2013-03-23 14:03     ` Damien Cassou
  0 siblings, 1 reply; 9+ messages in thread
From: Austin Clements @ 2013-03-16  4:10 UTC (permalink / raw)
  To: Damien Cassou, notmuch

(Decided I needed a brief break from working continuously.  I haven't
been following the mailing list at all, so I don't know if there's been
additional context relevant to this patch series, but this at least
appears to be the latest version.)

This is looking really good.  Just a few tiny comments below.

On Wed, 06 Feb 2013, Damien Cassou <damien.cassou@gmail.com> wrote:
> This patch extracts the rendering of tags in notmuch-show to
> the notmuch-tag file.
>
> This file introduces a `notmuch-tag-formats' variable that associates
> each tag to a particular format. This variable can be customized
> thanks to the work of Austin Clements. For example,
>
>   '(("unread" (propertize tag 'face '(:foreground "red")))
>     ("flagged" (notmuch-tag-format-image tag "star.svg")))
>
> associates a red foreground to the "unread" tag and a star picture to
> the "flagged" tag.
>
> Signed-off-by: Damien Cassou <damien.cassou@gmail.com>
> ---
>  emacs/notmuch-show.el |    6 +-
>  emacs/notmuch-tag.el  |  221 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  emacs/notmuch.el      |    5 +-
>  3 files changed, 224 insertions(+), 8 deletions(-)
>
> diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
> index 1864dd1..bb4bd92 100644
> --- a/emacs/notmuch-show.el
> +++ b/emacs/notmuch-show.el
> @@ -362,8 +362,7 @@ operation on the contents of the current buffer."
>      (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
>  	(let ((inhibit-read-only t))
>  	  (replace-match (concat "("
> -				 (propertize (mapconcat 'identity tags " ")
> -					     'face 'notmuch-tag-face)
> +				 (notmuch-tag-format-tags tags)
>  				 ")"))))))
>  
>  (defun notmuch-clean-address (address)
> @@ -441,8 +440,7 @@ message at DEPTH in the current thread."
>  	    " ("
>  	    date
>  	    ") ("
> -	    (propertize (mapconcat 'identity tags " ")
> -			'face 'notmuch-tag-face)
> +	    (notmuch-tag-format-tags tags)
>  	    ")\n")
>      (overlay-put (make-overlay start (point)) 'face 'notmuch-message-summary-face)))
>  
> diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
> index 4fce3a9..2a64d48 100644
> --- a/emacs/notmuch-tag.el
> +++ b/emacs/notmuch-tag.el
> @@ -1,5 +1,6 @@
>  ;; notmuch-tag.el --- tag messages within emacs
>  ;;
> +;; Copyright © Damien Cassou
>  ;; Copyright © Carl Worth
>  ;;
>  ;; This file is part of Notmuch.
> @@ -18,11 +19,229 @@
>  ;; along with Notmuch.  If not, see <http://www.gnu.org/licenses/>.
>  ;;
>  ;; Authors: Carl Worth <cworth@cworth.org>
> +;;          Damien Cassou <damien.cassou@gmail.com>
> +;;
> +;;; Code:
> +;;
>  
> -(eval-when-compile (require 'cl))
> +(require 'cl)
>  (require 'crm)
>  (require 'notmuch-lib)
>  
> +(defcustom notmuch-tag-formats
> +  '(("unread" (propertize tag 'face '(:foreground "red")))
> +    ("flagged" (notmuch-tag-format-image-data tag (notmuch-tag-star-icon))))
> +  "Custom formats for individual tags.
> +
> +This gives a list that maps from tag names to lists of formatting
> +expressions.  The car of each element gives a tag name and the
> +cdr gives a list of Elisp expressions that modify the tag.  If
> +the list is empty, the tag will simply be hidden.  Otherwise,
> +each expression will be evaluated in order: for the first
> +expression, the variable `tag' will be bound to the tag name; for
> +each later expression, the variable `tag' will be bound to the
> +result of the previous expression.  In this way, each expression
> +can build on the formatting performed by the previous expression.
> +The result of the last expression will displayed in place of the
> +tag.
> +
> +For example, to replace a tag with another string, simply use
> +that string as a formatting expression.  To change the foreground
> +of a tag to red, use the expression
> +  (propertize tag 'face '(:foreground \"red\"))
> +
> +See also `notmuch-tag-format-image', which can help replace tags
> +with images."
> +
> +  :group 'notmuch-search
> +  :group 'notmuch-show
> +  :type '(alist :key-type (string :tag "Tag")
> +		:extra-offset -3
> +		:value-type
> +		(radio :format "%v"
> +		       (const :tag "Hidden" nil)
> +		       (set :tag "Modified"
> +			    (string :tag "Display as")
> +			    (list :tag "Face" :extra-offset -4
> +				  (const :format "" :inline t
> +					 (propertize tag 'face))
> +				  (list :format "%v"
> +					(const :format "" quote)
> +					custom-face-edit))
> +			    (list :format "%v" :extra-offset -4
> +				  (const :format "" :inline t
> +					 (notmuch-tag-format-image-data tag))
> +				  (choice :tag "Image"
> +					  (const :tag "Star"
> +						 (notmuch-tag-star-icon))
> +					  (const :tag "Empty star"
> +						 (notmuch-tag-star-empty-icon))
> +					  (const :tag "Tag"
> +						 (notmuch-tag-tag-icon))
> +					  (string :tag "Custom")))
> +			    (sexp :tag "Custom")))))
> +
> +(defun notmuch-tag-format-image-data (tag data)
> +  "Replace TAG with image DATA, if available.
> +
> +This function returns a propertized string that will display image
> +DATA in place of TAG.This is designed for use in
> +`notmuch-tag-formats'.
> +
> +DATA is the content of an SVG picture (e.g., as returned by
> +`notmuch-tag-star-icon')."
> +  (propertize tag 'display
> +	      `(image :type svg
> +		      :data ,data
> +		      :ascent center
> +		      :mask heuristic)))
> +
> +(defun notmuch-tag-star-icon ()
> +  "Return SVG data representing a star icon.
> +This can be used with `notmuch-tag-format-image-data'."
> +  "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
> +<svg
> +   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
> +   xmlns:cc=\"http://creativecommons.org/ns#\"
> +   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
> +   xmlns:svg=\"http://www.w3.org/2000/svg\"
> +   xmlns=\"http://www.w3.org/2000/svg\"
> +   version=\"1.1\"
> +   width=\"16\"
> +   height=\"16\"
> +   id=\"svg2\">
> +  <defs
> +     id=\"defs4\" />
> +  <metadata
> +     id=\"metadata7\">
> +    <rdf:RDF>
> +      <cc:Work
> +         rdf:about=\"\">
> +        <dc:format>image/svg+xml</dc:format>
> +        <dc:type
> +           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />
> +        <dc:title></dc:title>
> +      </cc:Work>
> +    </rdf:RDF>
> +  </metadata>
> +  <g
> +     transform=\"translate(-242.81601,-315.59635)\"
> +     id=\"layer1\">
> +    <path
> +       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\"
> +       transform=\"matrix(0.2484147,-0.02623394,0.02623394,0.2484147,174.63605,255.37691)\"
> +       id=\"path2985\"
> +       style=\"fill:#ffff00;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" />
> +  </g>
> +</svg>")

You could simplify these SVGs much further.  You can remove the defs and
metadata blocks, and then remove all of the xmlns:* properties (keeping
just the root namespace).  You can also remove the id properties.  I
think you can even remove the g, leaving only the path, since it's only
a translate and I'm pretty sure the origin doesn't matter.

> +
> +(defun notmuch-tag-star-empty-icon ()
> +  "Return SVG data representing an empty star icon.
> +This can be used with `notmuch-tag-format-image-data'."
> +  "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
> +<!-- Created with Inkscape (http://www.inkscape.org/) -->
> +
> +<svg
> +   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
> +   xmlns:cc=\"http://creativecommons.org/ns#\"
> +   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
> +   xmlns:svg=\"http://www.w3.org/2000/svg\"
> +   xmlns=\"http://www.w3.org/2000/svg\"
> +   version=\"1.1\"
> +   width=\"16\"
> +   height=\"16\"
> +   id=\"svg2\">
> +  <defs
> +     id=\"defs4\" />
> +  <metadata
> +     id=\"metadata7\">
> +    <rdf:RDF>
> +      <cc:Work
> +         rdf:about=\"\">
> +        <dc:format>image/svg+xml</dc:format>
> +        <dc:type
> +           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />
> +        <dc:title></dc:title>
> +      </cc:Work>
> +    </rdf:RDF>
> +  </metadata>
> +  <g
> +     transform=\"translate(-242.81601,-315.59635)\"
> +     id=\"layer1\">
> +    <path
> +       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\"
> +       transform=\"matrix(0.2484147,-0.02623394,0.02623394,0.2484147,174.63605,255.37691)\"
> +       id=\"path2985\"
> +       style=\"fill:#d6d6d1;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" />
> +  </g>
> +</svg>")
> +
> +(defun notmuch-tag-tag-icon ()
> +  "Return SVG data representing a tag icon.
> +This can be used with `notmuch-tag-format-image-data'."
> +  "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
> +<!-- Created with Inkscape (http://www.inkscape.org/) -->
> +
> +<svg
> +   xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
> +   xmlns:cc=\"http://creativecommons.org/ns#\"
> +   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
> +   xmlns:svg=\"http://www.w3.org/2000/svg\"
> +   xmlns=\"http://www.w3.org/2000/svg\"
> +   version=\"1.1\"
> +   width=\"16\"
> +   height=\"16\"
> +   id=\"svg3805\">
> +  <defs
> +     id=\"defs3807\" />
> +  <metadata
> +     id=\"metadata3810\">
> +    <rdf:RDF>
> +      <cc:Work
> +         rdf:about=\"\">
> +        <dc:format>image/svg+xml</dc:format>
> +        <dc:type
> +           rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />
> +        <dc:title></dc:title>
> +      </cc:Work>
> +    </rdf:RDF>
> +  </metadata>
> +  <g
> +     transform=\"translate(0,-1036.3622)\"
> +     id=\"layer1\">
> +    <path
> +       d=\"m 0.44642857,1040.9336 12.50000043,0 2.700893,3.6161 -2.700893,3.616 -12.50000043,0 z\"
> +       id=\"rect4321\"
> +       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\" />
> +  </g>
> +</svg>")
> +
> +(defun notmuch-tag-get-format (tag)
> +  "Return the format for TAG in `notmuch-tag-formats'."

Hmm.  I read this as simply returning the format from
notmuch-tag-formats, like just the assoc, whereas really this *applies*
a format to tag.  Maybe notmuch-tag-format-tag?  This is really the
single tag equivalent of notmuch-tag-format-tags, so it would make sense
for the names to parallel each other.

> +  (let ((formats (assoc tag notmuch-tag-formats)))
> +    (cond
> +     ((null formats)		;; - Tag not in `notmuch-tag-formats',
> +      tag)			;; the format is then the tag itself.
> +     ((null (cdr formats))	;; - Tag was deliberately hidden,
> +      nil)			;; no format must be returned
> +     (t				;; - Tag was found and has formats,
> +      (let ((tag tag))		;; we must apply all the formats.
> +	(dolist (format (cdr formats) tag)
> +	  (setq tag (eval format))))))))
> +
> +(defun notmuch-tag-list-get-format (tags)

Is there a reason to separate this in to a separate function, rather
than inlining it into notmuch-tag-format-tags?  The reason I wonder is
that the function name doesn't seem very informative, which suggests
that it doesn't really exist as a separate concept outside of
notmuch-tag-format-tags.

> +  (mapconcat #'identity
> +	     ;; nil indicated that the tag was deliberately hidden
> +	     (delq nil (mapcar #'notmuch-tag-get-format tags))
> +	     " "))
> +
> +(defun notmuch-tag-format-tags (tags)
> +  "Return a string representing TAGS with their formats."
> +  (notmuch-combine-face-text-property-string
> +   (notmuch-tag-list-get-format tags)
> +   'notmuch-tag-face
> +   t))
> +
>  (defcustom notmuch-before-tag-hook nil
>    "Hooks that are run before tags of a message are modified.
>  
> diff --git a/emacs/notmuch.el b/emacs/notmuch.el
> index c98a4fe..e58c51d 100644
> --- a/emacs/notmuch.el
> +++ b/emacs/notmuch.el
> @@ -797,9 +797,8 @@ non-authors is found, assume that all of the authors match."
>      (notmuch-search-insert-authors format-string (plist-get result :authors)))
>  
>     ((string-equal field "tags")
> -    (let ((tags-str (mapconcat 'identity (plist-get result :tags) " ")))
> -      (insert (propertize (format format-string tags-str)
> -			  'face 'notmuch-tag-face))))))
> +    (let ((tags (plist-get result :tags)))
> +      (insert (format format-string (notmuch-tag-format-tags tags)))))))
>  
>  (defun notmuch-search-show-result (result &optional pos)
>    "Insert RESULT at POS or the end of the buffer if POS is null."
> -- 
> 1.7.10.4
>
> _______________________________________________
> notmuch mailing list
> notmuch@notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 2/2] emacs: possibility to customize the rendering of tags
  2013-03-23 11:29 [PATCH v3 " Damien Cassou
@ 2013-03-23 11:29 ` Damien Cassou
  2013-03-25 14:22   ` Austin Clements
  0 siblings, 1 reply; 9+ messages in thread
From: Damien Cassou @ 2013-03-23 11:29 UTC (permalink / raw)
  To: notmuch

This patch extracts the rendering of tags in notmuch-show to
the notmuch-tag file.

This file introduces a `notmuch-tag-formats' variable that associates
each tag to a particular format. This variable can be customized
thanks to the work of Austin Clements. For example,

  '(("unread" (propertize tag 'face '(:foreground "red")))
    ("flagged" (notmuch-tag-format-image tag "star.svg")))

associates a red foreground to the "unread" tag and a star picture to
the "flagged" tag.

Signed-off-by: Damien Cassou <damien.cassou@gmail.com>
---
 emacs/notmuch-show.el |    6 +--
 emacs/notmuch-tag.el  |  136 ++++++++++++++++++++++++++++++++++++++++++++++++-
 emacs/notmuch.el      |    5 +-
 3 files changed, 139 insertions(+), 8 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index acaef8e..a4d2c12 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -362,8 +362,7 @@ operation on the contents of the current buffer."
     (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
 	(let ((inhibit-read-only t))
 	  (replace-match (concat "("
-				 (propertize (mapconcat 'identity tags " ")
-					     'face 'notmuch-tag-face)
+				 (notmuch-tag-format-tags tags)
 				 ")"))))))
 
 (defun notmuch-clean-address (address)
@@ -441,8 +440,7 @@ message at DEPTH in the current thread."
 	    " ("
 	    date
 	    ") ("
-	    (propertize (mapconcat 'identity tags " ")
-			'face 'notmuch-tag-face)
+	    (notmuch-tag-format-tags tags)
 	    ")\n")
     (overlay-put (make-overlay start (point)) 'face 'notmuch-message-summary-face)))
 
diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
index 4fce3a9..75a438b 100644
--- a/emacs/notmuch-tag.el
+++ b/emacs/notmuch-tag.el
@@ -1,5 +1,6 @@
 ;; notmuch-tag.el --- tag messages within emacs
 ;;
+;; Copyright © Damien Cassou
 ;; Copyright © Carl Worth
 ;;
 ;; This file is part of Notmuch.
@@ -18,11 +19,144 @@
 ;; along with Notmuch.  If not, see <http://www.gnu.org/licenses/>.
 ;;
 ;; Authors: Carl Worth <cworth@cworth.org>
+;;          Damien Cassou <damien.cassou@gmail.com>
+;;
+;;; Code:
+;;
 
-(eval-when-compile (require 'cl))
+(require 'cl)
 (require 'crm)
 (require 'notmuch-lib)
 
+(defcustom notmuch-tag-formats
+  '(("unread" (propertize tag 'face '(:foreground "red")))
+    ("flagged" (notmuch-tag-format-image-data tag (notmuch-tag-star-icon))))
+  "Custom formats for individual tags.
+
+This gives a list that maps from tag names to lists of formatting
+expressions.  The car of each element gives a tag name and the
+cdr gives a list of Elisp expressions that modify the tag.  If
+the list is empty, the tag will simply be hidden.  Otherwise,
+each expression will be evaluated in order: for the first
+expression, the variable `tag' will be bound to the tag name; for
+each later expression, the variable `tag' will be bound to the
+result of the previous expression.  In this way, each expression
+can build on the formatting performed by the previous expression.
+The result of the last expression will displayed in place of the
+tag.
+
+For example, to replace a tag with another string, simply use
+that string as a formatting expression.  To change the foreground
+of a tag to red, use the expression
+  (propertize tag 'face '(:foreground \"red\"))
+
+See also `notmuch-tag-format-image', which can help replace tags
+with images."
+
+  :group 'notmuch-search
+  :group 'notmuch-show
+  :type '(alist :key-type (string :tag "Tag")
+		:extra-offset -3
+		:value-type
+		(radio :format "%v"
+		       (const :tag "Hidden" nil)
+		       (set :tag "Modified"
+			    (string :tag "Display as")
+			    (list :tag "Face" :extra-offset -4
+				  (const :format "" :inline t
+					 (propertize tag 'face))
+				  (list :format "%v"
+					(const :format "" quote)
+					custom-face-edit))
+			    (list :format "%v" :extra-offset -4
+				  (const :format "" :inline t
+					 (notmuch-tag-format-image-data tag))
+				  (choice :tag "Image"
+					  (const :tag "Star"
+						 (notmuch-tag-star-icon))
+					  (const :tag "Empty star"
+						 (notmuch-tag-star-empty-icon))
+					  (const :tag "Tag"
+						 (notmuch-tag-tag-icon))
+					  (string :tag "Custom")))
+			    (sexp :tag "Custom")))))
+
+(defun notmuch-tag-format-image-data (tag data)
+  "Replace TAG with image DATA, if available.
+
+This function returns a propertized string that will display image
+DATA in place of TAG.This is designed for use in
+`notmuch-tag-formats'.
+
+DATA is the content of an SVG picture (e.g., as returned by
+`notmuch-tag-star-icon')."
+  (propertize tag 'display
+	      `(image :type svg
+		      :data ,data
+		      :ascent center
+		      :mask heuristic)))
+
+(defun notmuch-tag-star-icon ()
+  "Return SVG data representing a star icon.
+This can be used with `notmuch-tag-format-image-data'."
+"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
+<svg version=\"1.1\" width=\"16\" height=\"16\">
+  <g transform=\"translate(-242.81601,-315.59635)\">
+    <path
+       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\"
+       transform=\"matrix(0.2484147,-0.02623394,0.02623394,0.2484147,174.63605,255.37691)\"
+       style=\"fill:#ffff00;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" />
+  </g>
+</svg>")
+
+(defun notmuch-tag-star-empty-icon ()
+  "Return SVG data representing an empty star icon.
+This can be used with `notmuch-tag-format-image-data'."
+  "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
+<svg version=\"1.1\" width=\"16\" height=\"16\">
+  <g transform=\"translate(-242.81601,-315.59635)\">
+    <path
+       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\"
+       transform=\"matrix(0.2484147,-0.02623394,0.02623394,0.2484147,174.63605,255.37691)\"
+       style=\"fill:#d6d6d1;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" />
+  </g>
+</svg>")
+
+(defun notmuch-tag-tag-icon ()
+  "Return SVG data representing a tag icon.
+This can be used with `notmuch-tag-format-image-data'."
+  "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
+<svg version=\"1.1\" width=\"16\" height=\"16\">
+  <g transform=\"translate(0,-1036.3622)\">
+    <path
+       d=\"m 0.44642857,1040.9336 12.50000043,0 2.700893,3.6161 -2.700893,3.616 -12.50000043,0 z\"
+       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\" />
+  </g>
+</svg>")
+
+(defun notmuch-tag-format-tag (tag)
+  "Format TAG by looking into `notmuch-tag-formats'."
+  (let ((formats (assoc tag notmuch-tag-formats)))
+    (cond
+     ((null formats)		;; - Tag not in `notmuch-tag-formats',
+      tag)			;;   the format is the tag itself.
+     ((null (cdr formats))	;; - Tag was deliberately hidden,
+      nil)			;;   no format must be returned
+     (t				;; - Tag was found and has formats,
+      (let ((tag tag))		;;   we must apply all the formats.
+	(dolist (format (cdr formats) tag)
+	  (setq tag (eval format))))))))
+
+(defun notmuch-tag-format-tags (tags)
+  "Return a string representing formatted TAGS."
+  (notmuch-combine-face-text-property-string
+   (mapconcat #'identity
+	      ;; nil indicated that the tag was deliberately hidden
+	      (delq nil (mapcar #'notmuch-tag-format-tag tags))
+	      " ")
+   'notmuch-tag-face
+   t))
+
 (defcustom notmuch-before-tag-hook nil
   "Hooks that are run before tags of a message are modified.
 
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index c98a4fe..e58c51d 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -797,9 +797,8 @@ non-authors is found, assume that all of the authors match."
     (notmuch-search-insert-authors format-string (plist-get result :authors)))
 
    ((string-equal field "tags")
-    (let ((tags-str (mapconcat 'identity (plist-get result :tags) " ")))
-      (insert (propertize (format format-string tags-str)
-			  'face 'notmuch-tag-face))))))
+    (let ((tags (plist-get result :tags)))
+      (insert (format format-string (notmuch-tag-format-tags tags)))))))
 
 (defun notmuch-search-show-result (result &optional pos)
   "Insert RESULT at POS or the end of the buffer if POS is null."
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] emacs: possibility to customize the rendering of tags
  2013-03-16  4:10   ` Austin Clements
@ 2013-03-23 14:03     ` Damien Cassou
  0 siblings, 0 replies; 9+ messages in thread
From: Damien Cassou @ 2013-03-23 14:03 UTC (permalink / raw)
  To: Austin Clements; +Cc: notmuch mailing list

[-- Attachment #1: Type: text/plain, Size: 380 bytes --]

On Sat, Mar 16, 2013 at 5:10 AM, Austin Clements <amdragon@mit.edu> wrote:

> Just a few tiny comments below.



Thanks for your comments. Please see v3 in
id:1364038194-19856-1-git-send-email-damien.cassou@gmail.com


-- 
Damien Cassou
http://damiencassou.seasidehosting.st

"Success is the ability to go from one failure to another without losing
enthusiasm."
Winston Churchill

[-- Attachment #2: Type: text/html, Size: 964 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] emacs: possibility to customize the rendering of tags
  2013-03-23 11:29 ` [PATCH 2/2] emacs: possibility to customize the rendering of tags Damien Cassou
@ 2013-03-25 14:22   ` Austin Clements
  2013-03-25 14:26     ` Austin Clements
  0 siblings, 1 reply; 9+ messages in thread
From: Austin Clements @ 2013-03-25 14:22 UTC (permalink / raw)
  To: Damien Cassou; +Cc: notmuch

Series LGTM.  I noticed a few things below that would be fine to tweak
in a follow-up trivial patch or two.

Quoth Damien Cassou on Mar 23 at 12:29 pm:
> This patch extracts the rendering of tags in notmuch-show to
> the notmuch-tag file.
> 
> This file introduces a `notmuch-tag-formats' variable that associates
> each tag to a particular format. This variable can be customized
> thanks to the work of Austin Clements. For example,
> 
>   '(("unread" (propertize tag 'face '(:foreground "red")))
>     ("flagged" (notmuch-tag-format-image tag "star.svg")))
> 
> associates a red foreground to the "unread" tag and a star picture to
> the "flagged" tag.
> 
> Signed-off-by: Damien Cassou <damien.cassou@gmail.com>
> ---
>  emacs/notmuch-show.el |    6 +--
>  emacs/notmuch-tag.el  |  136 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  emacs/notmuch.el      |    5 +-
>  3 files changed, 139 insertions(+), 8 deletions(-)
> 
> diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
> index acaef8e..a4d2c12 100644
> --- a/emacs/notmuch-show.el
> +++ b/emacs/notmuch-show.el
> @@ -362,8 +362,7 @@ operation on the contents of the current buffer."
>      (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
>  	(let ((inhibit-read-only t))
>  	  (replace-match (concat "("
> -				 (propertize (mapconcat 'identity tags " ")
> -					     'face 'notmuch-tag-face)
> +				 (notmuch-tag-format-tags tags)
>  				 ")"))))))
>  
>  (defun notmuch-clean-address (address)
> @@ -441,8 +440,7 @@ message at DEPTH in the current thread."
>  	    " ("
>  	    date
>  	    ") ("
> -	    (propertize (mapconcat 'identity tags " ")
> -			'face 'notmuch-tag-face)
> +	    (notmuch-tag-format-tags tags)
>  	    ")\n")
>      (overlay-put (make-overlay start (point)) 'face 'notmuch-message-summary-face)))
>  
> diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
> index 4fce3a9..75a438b 100644
> --- a/emacs/notmuch-tag.el
> +++ b/emacs/notmuch-tag.el
> @@ -1,5 +1,6 @@
>  ;; notmuch-tag.el --- tag messages within emacs
>  ;;
> +;; Copyright © Damien Cassou
>  ;; Copyright © Carl Worth
>  ;;
>  ;; This file is part of Notmuch.
> @@ -18,11 +19,144 @@
>  ;; along with Notmuch.  If not, see <http://www.gnu.org/licenses/>.
>  ;;
>  ;; Authors: Carl Worth <cworth@cworth.org>
> +;;          Damien Cassou <damien.cassou@gmail.com>
> +;;
> +;;; Code:
> +;;
>  
> -(eval-when-compile (require 'cl))
> +(require 'cl)
>  (require 'crm)
>  (require 'notmuch-lib)
>  
> +(defcustom notmuch-tag-formats
> +  '(("unread" (propertize tag 'face '(:foreground "red")))
> +    ("flagged" (notmuch-tag-format-image-data tag (notmuch-tag-star-icon))))
> +  "Custom formats for individual tags.
> +
> +This gives a list that maps from tag names to lists of formatting
> +expressions.  The car of each element gives a tag name and the
> +cdr gives a list of Elisp expressions that modify the tag.  If
> +the list is empty, the tag will simply be hidden.  Otherwise,
> +each expression will be evaluated in order: for the first
> +expression, the variable `tag' will be bound to the tag name; for
> +each later expression, the variable `tag' will be bound to the
> +result of the previous expression.  In this way, each expression
> +can build on the formatting performed by the previous expression.
> +The result of the last expression will displayed in place of the
> +tag.
> +
> +For example, to replace a tag with another string, simply use
> +that string as a formatting expression.  To change the foreground
> +of a tag to red, use the expression
> +  (propertize tag 'face '(:foreground \"red\"))
> +
> +See also `notmuch-tag-format-image', which can help replace tags
> +with images."
> +
> +  :group 'notmuch-search
> +  :group 'notmuch-show
> +  :type '(alist :key-type (string :tag "Tag")
> +		:extra-offset -3
> +		:value-type
> +		(radio :format "%v"
> +		       (const :tag "Hidden" nil)
> +		       (set :tag "Modified"
> +			    (string :tag "Display as")
> +			    (list :tag "Face" :extra-offset -4
> +				  (const :format "" :inline t
> +					 (propertize tag 'face))
> +				  (list :format "%v"
> +					(const :format "" quote)
> +					custom-face-edit))
> +			    (list :format "%v" :extra-offset -4
> +				  (const :format "" :inline t
> +					 (notmuch-tag-format-image-data tag))
> +				  (choice :tag "Image"
> +					  (const :tag "Star"
> +						 (notmuch-tag-star-icon))
> +					  (const :tag "Empty star"
> +						 (notmuch-tag-star-empty-icon))
> +					  (const :tag "Tag"
> +						 (notmuch-tag-tag-icon))
> +					  (string :tag "Custom")))
> +			    (sexp :tag "Custom")))))
> +
> +(defun notmuch-tag-format-image-data (tag data)
> +  "Replace TAG with image DATA, if available.
> +
> +This function returns a propertized string that will display image
> +DATA in place of TAG.This is designed for use in

Missing spaces after the period.

> +`notmuch-tag-formats'.
> +
> +DATA is the content of an SVG picture (e.g., as returned by
> +`notmuch-tag-star-icon')."
> +  (propertize tag 'display
> +	      `(image :type svg
> +		      :data ,data
> +		      :ascent center
> +		      :mask heuristic)))
> +
> +(defun notmuch-tag-star-icon ()

Should these be notmuch-tag-icon-{star,star-empty,tag}?  That would
better match standard naming conventions (most general term to least
general term) and would avoid the awkward notmuch-tag-tag-icon.

> +  "Return SVG data representing a star icon.
> +This can be used with `notmuch-tag-format-image-data'."
> +"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
> +<svg version=\"1.1\" width=\"16\" height=\"16\">
> +  <g transform=\"translate(-242.81601,-315.59635)\">
> +    <path
> +       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\"
> +       transform=\"matrix(0.2484147,-0.02623394,0.02623394,0.2484147,174.63605,255.37691)\"
> +       style=\"fill:#ffff00;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" />

Here's an even simpler equivalent SVG:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg version="1.1" width="16" height="16">
  <path
      d="M 12.69462,15.21399 8.00320,12.75053 3.31422,15.21864 4.20739,9.99558 0.41110,6.29879 5.65452,5.53422 7.99727,0.78137 10.34472,5.53189 15.58890,6.29126 11.79629,9.99182 z"
      style="fill:#ffff00;stroke:#000000;stroke-width:0.25" />
</svg>

I pre-applied the transformations and removed the style attributes
that had default or unimportant values.  (The script to do the path
math is attached.)

> +  </g>
> +</svg>")
> +
> +(defun notmuch-tag-star-empty-icon ()
> +  "Return SVG data representing an empty star icon.
> +This can be used with `notmuch-tag-format-image-data'."
> +  "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
> +<svg version=\"1.1\" width=\"16\" height=\"16\">
> +  <g transform=\"translate(-242.81601,-315.59635)\">
> +    <path
> +       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\"
> +       transform=\"matrix(0.2484147,-0.02623394,0.02623394,0.2484147,174.63605,255.37691)\"
> +       style=\"fill:#d6d6d1;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" />
> +  </g>
> +</svg>")

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg version="1.1" width="16" height="16">
  <path
      d="M 12.69462,15.21399 8.00320,12.75053 3.31422,15.21864 4.20739,9.99558 0.41110,6.29879 5.65452,5.53422 7.99727,0.78137 10.34472,5.53189 15.58890,6.29126 11.79629,9.99182 z"
      style="fill:#d6d6d1;stroke:#000000;stroke-width:0.25" />
</svg>

> +
> +(defun notmuch-tag-tag-icon ()
> +  "Return SVG data representing a tag icon.
> +This can be used with `notmuch-tag-format-image-data'."
> +  "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
> +<svg version=\"1.1\" width=\"16\" height=\"16\">
> +  <g transform=\"translate(0,-1036.3622)\">
> +    <path
> +       d=\"m 0.44642857,1040.9336 12.50000043,0 2.700893,3.6161 -2.700893,3.616 -12.50000043,0 z\"
> +       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\" />
> +  </g>
> +</svg>")

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg version="1.1" width="16" height="16">
  <path
      d="M 0.44643,4.57140 12.94643,4.57140 15.64732,8.18750 12.94643,11.80350 0.44643,11.80350 z"
      style="fill:#ffff00;stroke:#000000;stroke-width:0.25" />
</svg>

> +
> +(defun notmuch-tag-format-tag (tag)
> +  "Format TAG by looking into `notmuch-tag-formats'."
> +  (let ((formats (assoc tag notmuch-tag-formats)))
> +    (cond
> +     ((null formats)		;; - Tag not in `notmuch-tag-formats',
> +      tag)			;;   the format is the tag itself.
> +     ((null (cdr formats))	;; - Tag was deliberately hidden,
> +      nil)			;;   no format must be returned
> +     (t				;; - Tag was found and has formats,
> +      (let ((tag tag))		;;   we must apply all the formats.
> +	(dolist (format (cdr formats) tag)
> +	  (setq tag (eval format))))))))
> +
> +(defun notmuch-tag-format-tags (tags)
> +  "Return a string representing formatted TAGS."
> +  (notmuch-combine-face-text-property-string
> +   (mapconcat #'identity
> +	      ;; nil indicated that the tag was deliberately hidden
> +	      (delq nil (mapcar #'notmuch-tag-format-tag tags))
> +	      " ")
> +   'notmuch-tag-face
> +   t))
> +
>  (defcustom notmuch-before-tag-hook nil
>    "Hooks that are run before tags of a message are modified.
>  
> diff --git a/emacs/notmuch.el b/emacs/notmuch.el
> index c98a4fe..e58c51d 100644
> --- a/emacs/notmuch.el
> +++ b/emacs/notmuch.el
> @@ -797,9 +797,8 @@ non-authors is found, assume that all of the authors match."
>      (notmuch-search-insert-authors format-string (plist-get result :authors)))
>  
>     ((string-equal field "tags")
> -    (let ((tags-str (mapconcat 'identity (plist-get result :tags) " ")))
> -      (insert (propertize (format format-string tags-str)
> -			  'face 'notmuch-tag-face))))))
> +    (let ((tags (plist-get result :tags)))
> +      (insert (format format-string (notmuch-tag-format-tags tags)))))))
>  
>  (defun notmuch-search-show-result (result &optional pos)
>    "Insert RESULT at POS or the end of the buffer if POS is null."

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] emacs: possibility to customize the rendering of tags
  2013-03-25 14:22   ` Austin Clements
@ 2013-03-25 14:26     ` Austin Clements
  0 siblings, 0 replies; 9+ messages in thread
From: Austin Clements @ 2013-03-25 14:26 UTC (permalink / raw)
  To: Damien Cassou; +Cc: notmuch

[-- Attachment #1: Type: text/plain, Size: 211 bytes --]

Quoth myself on Mar 25 at 10:22 am:
> I pre-applied the transformations and removed the style attributes
> that had default or unimportant values.  (The script to do the path
> math is attached.)

Now attached.

[-- Attachment #2: xform.py --]
[-- Type: text/x-python, Size: 1632 bytes --]

import re, numpy

def parse_xform(xform):
    [(name, args)] = re.findall(r"([a-z]+)\(([-0-9.,]+)\)", xform)
    args = map(float, args.split(","))
    if name == "translate":
        x, y = args
        return numpy.matrix([[1,0,x], [0,1,y], [0,0,1]])
    if name == "matrix":
        a, b, c, d, e, f = args
        return numpy.matrix([[a,c,e], [b,d,f], [0,0,1]])
    raise ValueError("Couldn't parse %r" % xform)

def parse_path(spath):
    # Parse an 'm' path
    pos = (0,0)
    res = []
    for op in spath.split():
        dx, dy = map(float, op.split(","))
        pos = (pos[0] + dx, pos[1] + dy)
        res.append(numpy.matrix([pos[0], pos[1], 1]).T)
    return res

def str_path(path):
    # Print an 'M' path (different from parse_path!)
    return " ".join("%.5f,%.5f" % (c[0][0], c[1][0]) for c in path)

# Star icons
xform = (parse_xform("translate(-242.81601,-315.59635)") *
         parse_xform("matrix(0.2484147,-0.02623394,0.02623394,0.2484147,174.63605,255.37691)"))
path = parse_path("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")
xpath = [xform * coord for coord in path]
# Path
print str_path(xpath)
# Stroke
print numpy.linalg.norm(xform * numpy.matrix([1, 0, 1]).T -
                        xform * numpy.matrix([0, 0, 1]).T)
print

# Tag icon
xform = parse_xform("translate(0,-1036.3622)")
path = parse_path("0.44642857,1040.9336 12.50000043,0 2.700893,3.6161 -2.700893,3.616 -12.50000043,0")
xpath = [xform * coord for coord in path]
# Path
print str_path(xpath)

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2013-03-25 14:26 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-06 14:53 [PATCH v2 0/2] Customize how each tag is displayed Damien Cassou
2013-02-06 14:53 ` [PATCH 1/2] emacs: Add notmuch-combine-face-text-property-string Damien Cassou
2013-02-06 14:53 ` [PATCH 2/2] emacs: possibility to customize the rendering of tags Damien Cassou
2013-03-16  4:10   ` Austin Clements
2013-03-23 14:03     ` Damien Cassou
2013-03-13  9:43 ` [PATCH v2 0/2] Customize how each tag is displayed Damien Cassou
  -- strict thread matches above, loose matches on Subject: below --
2013-03-23 11:29 [PATCH v3 " Damien Cassou
2013-03-23 11:29 ` [PATCH 2/2] emacs: possibility to customize the rendering of tags Damien Cassou
2013-03-25 14:22   ` Austin Clements
2013-03-25 14:26     ` Austin Clements

Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).