[PATCH 3/5] emacs: show: mark tags changed since buffer loaded
Mark Walters
markwalters1009 at gmail.com
Sat Dec 14 15:44:34 PST 2013
This shows any tags changed in the show buffer since it was loaded or
refreshed. By default a removed tag is displayed with strike-through
in red (if strike-through is not available, eg on a terminal, inverse
video is used instead) and an added tag is displayed underlined in
green.
One nice feature is that this makes it clear when a message was unread
when you first loaded the buffer (previously the unread tag could be
removed before a user realised that it had been unread).
The code adds into the existing tag formatting code. The user can
specify exactly how a tag should be displayed normally, when deleted,
or when added. For convenience an entry for the entry string in the
notmuch-tag-formats (and the corresponding notmuch-tag-deleted-formats
notmuch-tag-added-formats) is applied to all tags which do not have an
explicit match.
This means that a user can tell notmuch not to show deleted tags at
all by setting notmuch-tag-deleted-formats to
'(("" nil))
or not to show any deleted tags except "unread" by setting it to
'(("" nil)
("unread" (propertize tag 'face '(strike-through "red"))))
All the variables are customizable; however, more complicated cases
like changing the face depending on the type of display will require
custom lisp.
Currently this overrides notmuch-tag-deleted-formats for the tests
setting it to '(("" nil)) so that they get removed from the display
and, thus, all tests still pass.
---
emacs/notmuch-show.el | 22 ++++++++--
emacs/notmuch-tag.el | 105 +++++++++++++++++++++++++++++++++++--------------
test/test-lib.el | 4 ++
3 files changed, 96 insertions(+), 35 deletions(-)
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 1ac80ca..30e84b1 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -341,11 +341,21 @@ operation on the contents of the current buffer."
"Update the displayed tags of the current message."
(save-excursion
(goto-char (notmuch-show-message-top))
- (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
- (let ((inhibit-read-only t))
- (replace-match (concat "("
- (notmuch-tag-format-tags tags)
- ")"))))))
+ (let* ((orig-tags (notmuch-show-get-prop :orig-tags))
+ (all-tags (sort (delete-dups (append tags orig-tags)) #'string<))
+ (display-tags (mapcar (lambda (tag) (cond ((and (member tag tags) (member tag orig-tags))
+ tag)
+ ((not (member tag tags))
+ (cons tag 'deleted))
+ ((not (member tag orig-tags))
+ (cons tag 'added))))
+ all-tags)))
+
+ (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
+ (let ((inhibit-read-only t))
+ (replace-match (concat "("
+ (notmuch-tag-format-tags display-tags)
+ ")")))))))
(defun notmuch-clean-address (address)
"Try to clean a single email ADDRESS for display. Return a cons
@@ -1167,6 +1177,8 @@ function is used."
(jit-lock-register #'notmuch-show-buttonise-links)
+ (notmuch-show-mapc (lambda () (notmuch-show-set-prop :orig-tags (notmuch-show-get-tags))))
+
;; Set the header line to the subject of the first message.
(setq header-line-format (notmuch-sanitize (notmuch-show-strip-re (notmuch-show-get-subject))))
diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
index b60f46c..81ce287 100644
--- a/emacs/notmuch-tag.el
+++ b/emacs/notmuch-tag.el
@@ -28,34 +28,8 @@
(require 'crm)
(require 'notmuch-lib)
-(defcustom notmuch-tag-formats
- '(("unread" (propertize tag 'face '(:foreground "red")))
- ("flagged" (propertize tag 'face '(:foreground "blue"))
- (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
+(define-widget 'notmuch-tag-format-type 'lazy
+ "Customize widget for notmuch-tag-format and friends"
:type '(alist :key-type (string :tag "Tag")
:extra-offset -3
:value-type
@@ -82,6 +56,61 @@ with images."
(string :tag "Custom")))
(sexp :tag "Custom")))))
+(defcustom notmuch-tag-formats
+ '(("unread" (propertize tag 'face '(:foreground "red")))
+ ("flagged" (propertize tag 'face '(:foreground "blue"))
+ (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
+car is an empty string it matches all tags that do not have an
+explicit match. 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 'notmuch-tag-format-type)
+
+(defcustom notmuch-tag-deleted-formats
+ '(("" (propertize tag 'face
+ (if (display-supports-face-attributes-p '(:strike-through "red"))
+ '(:strike-through "red")
+ '(:inverse-video t)))))
+ "Custom formats for tags when deleted.
+
+By default this shows deleted tags with strike-through in red,
+unless strike-through is not available (e.g., emacs is running in
+a terminal) in which case it uses inverse video. To hide deleted
+tags completely set this to
+ '((\"\" nil))
+
+See `notmuch-tag-formats' for full documentation."
+ :group 'notmuch-show
+ :type 'notmuch-tag-format-type)
+
+(defcustom notmuch-tag-added-formats
+ '(("" (propertize tag 'face '(:underline "green"))))
+ "Custom formats for tags when added.
+
+See `notmuch-tag-formats' for full documentation."
+ :group 'notmuch-show
+ :type 'notmuch-tag-format-type)
+
(defun notmuch-tag-format-image-data (tag data)
"Replace TAG with image DATA, if available.
@@ -136,8 +165,24 @@ This can be used with `notmuch-tag-format-image-data'."
</svg>")
(defun notmuch-tag-format-tag (tag)
- "Format TAG by looking into `notmuch-tag-formats'."
- (let ((formats (assoc tag notmuch-tag-formats)))
+ "Format TAG by looking into `notmuch-tag-formats'.
+
+TAG can either be a string for a tag or a cons cell. In the
+latter case the car of the cons cell is the tag string, the cdr
+should be 'deleted or 'added to indicate whether the tag has been
+deleted or added. The format for tag is looked up in
+`notmuch-tag-formats' or `notmuch-tag-deleted-formats' or
+`notmuch-tag-added-formats' as appropriate."
+ (let* ((status (if (consp tag) (cdr tag)))
+ (tag (if (consp tag) (car tag) tag))
+ (status-formats (cond
+ ((eq status 'deleted)
+ notmuch-tag-deleted-formats)
+ ((eq status 'added)
+ notmuch-tag-added-formats)
+ (t notmuch-tag-formats)))
+ (formats (or (append (assoc tag status-formats))
+ (append (assoc "" status-formats)))))
(cond
((null formats) ;; - Tag not in `notmuch-tag-formats',
tag) ;; the format is the tag itself.
diff --git a/test/test-lib.el b/test/test-lib.el
index 1c9e224..a1b40b7 100644
--- a/test/test-lib.el
+++ b/test/test-lib.el
@@ -174,3 +174,7 @@ nothing."
(dolist (form body ret)
(setq ret (eval form))
(notmuch-post-command))))
+
+;; hide deleted tags
+(setq notmuch-tag-deleted-formats
+ '(("" nil)))
--
1.7.9.1
More information about the notmuch
mailing list