emacs: Use text properties instead of overlays for tag coloring

Previously, tag-based search result highlighting was done by creating
an overlay over each search result.  However, overlays have annoying
front- and rear-advancement semantics that make it difficult to
manipulate text at their boundaries, which the next patch will do.
They also have performance problems (creating an overlay is linear in
the number of overlays between point and the new overlay, making
highlighting a search buffer quadratic in the number of results).

Text properties have neither problem.  However, text properties make
it more difficult to apply multiple faces since, unlike with overlays,
a given character can only have a single 'face text property.  Hence,
we introduce a utility function that combines faces into any existing
'face text properties.

Using this utility function, it's straightforward to apply all of the
appropriate tag faces in notmuch-search-color-line.
This commit is contained in:
Austin Clements 2012-07-21 13:37:06 -04:00 committed by David Bremner
parent ae30f33093
commit 60ebc84945
2 changed files with 22 additions and 14 deletions

View file

@ -269,6 +269,21 @@ current buffer, if possible."
(loop for (key value . rest) on plist by #'cddr (loop for (key value . rest) on plist by #'cddr
collect (cons (intern (substring (symbol-name key) 1)) value))) collect (cons (intern (substring (symbol-name key) 1)) value)))
(defun notmuch-combine-face-text-property (start end face)
"Combine FACE into the 'face text property between START and END.
This function combines FACE with any existing faces between START
and END. Attributes specified by FACE take precedence over
existing attributes. FACE must be a face name (a symbol or
string), a property list of face attributes, or a list of these."
(let ((pos start))
(while (< pos end)
(let ((cur (get-text-property pos 'face))
(next (next-single-property-change pos 'face nil end)))
(put-text-property pos next 'face (cons face cur))
(setq pos next)))))
;; Compatibility functions for versions of emacs before emacs 23. ;; Compatibility functions for versions of emacs before emacs 23.
;; ;;
;; Both functions here were copied from emacs 23 with the following copyright: ;; Both functions here were copied from emacs 23 with the following copyright:

View file

@ -633,20 +633,13 @@ foreground and blue background."
(defun notmuch-search-color-line (start end line-tag-list) (defun notmuch-search-color-line (start end line-tag-list)
"Colorize lines in `notmuch-show' based on tags." "Colorize lines in `notmuch-show' based on tags."
;; Create the overlay only if the message has tags which match one (mapc (lambda (elem)
;; of those specified in `notmuch-search-line-faces'. (let ((tag (car elem))
(let (overlay) (attributes (cdr elem)))
(mapc (lambda (elem) (when (member tag line-tag-list)
(let ((tag (car elem)) (notmuch-combine-face-text-property start end attributes))))
(attributes (cdr elem))) ;; Reverse the list so earlier entries take precedence
(when (member tag line-tag-list) (reverse notmuch-search-line-faces)))
(when (not overlay)
(setq overlay (make-overlay start end)))
;; Merge the specified properties with any already
;; applied from an earlier match.
(overlay-put overlay 'face
(append (overlay-get overlay 'face) attributes)))))
notmuch-search-line-faces)))
(defun notmuch-search-author-propertize (authors) (defun notmuch-search-author-propertize (authors)
"Split `authors' into matching and non-matching authors and "Split `authors' into matching and non-matching authors and