X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=emacs%2Fnotmuch-tag.el;h=c7a1e3220946ad3a2ec1c1f8afc7b320d9c7ae83;hp=42c425ed4624572dad29dad94f672396b06cc365;hb=df3fab18fe70ea750f6f06da30291c67de7e74f2;hpb=7023466ece21b43a62dc0a2502e84bea78b1501c diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el index 42c425ed..c7a1e322 100644 --- a/emacs/notmuch-tag.el +++ b/emacs/notmuch-tag.el @@ -1,4 +1,4 @@ -;; notmuch-tag.el --- tag messages within emacs +;;; notmuch-tag.el --- tag messages within emacs ;; ;; Copyright © Damien Cassou ;; Copyright © Carl Worth @@ -16,21 +16,124 @@ ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License -;; along with Notmuch. If not, see . +;; along with Notmuch. If not, see . ;; ;; Authors: Carl Worth ;; Damien Cassou -;; + ;;; Code: -;; -(require 'cl) +(require 'cl-lib) +(eval-when-compile + (require 'pcase)) + (require 'crm) + (require 'notmuch-lib) +(declare-function notmuch-search-tag "notmuch" + (tag-changes &optional beg end only-matched)) +(declare-function notmuch-show-tag "notmuch-show" (tag-changes)) +(declare-function notmuch-tree-tag "notmuch-tree" (tag-changes)) +(declare-function notmuch-jump "notmuch-jump" (action-map prompt)) + +(define-widget 'notmuch-tag-key-type 'list + "A single key tagging binding." + :format "%v" + :args '((list :inline t + :format "%v" + (key-sequence :tag "Key") + (radio :tag "Tag operations" + (repeat :tag "Tag list" + (string :format "%v" :tag "change")) + (variable :tag "Tag variable")) + (string :tag "Name")))) + +(defcustom notmuch-tagging-keys + `((,(kbd "a") notmuch-archive-tags "Archive") + (,(kbd "u") notmuch-show-mark-read-tags "Mark read") + (,(kbd "f") ("+flagged") "Flag") + (,(kbd "s") ("+spam" "-inbox") "Mark as spam") + (,(kbd "d") ("+deleted" "-inbox") "Delete")) + "A list of keys and corresponding tagging operations. + +For each key (or key sequence) you can specify a sequence of +tagging operations to apply, or a variable which contains a list +of tagging operations such as `notmuch-archive-tags'. The final +element is a name for this tagging operation. If the name is +omitted or empty then the list of tag changes, or the variable +name is used as the name. + +The key `notmuch-tag-jump-reverse-key' (k by default) should not +be used (either as a key, or as the start of a key sequence) as +it is already bound: it switches the menu to a menu of the +reverse tagging operations. The reverse of a tagging operation is +the same list of individual tag-ops but with `+tag` replaced by +`-tag` and vice versa. + +If setting this variable outside of customize then it should be a +list of triples (lists of three elements). Each triple should be +of the form (key-binding tagging-operations name). KEY-BINDING +can be a single character or a key sequence; TAGGING-OPERATIONS +should either be a list of individual tag operations each of the +form `+tag` or `-tag`, or the variable name of a variable that is +a list of tagging operations; NAME should be a name for the +tagging operation, if omitted or empty than then name is taken +from TAGGING-OPERATIONS." + :tag "List of tagging bindings" + :type '(repeat notmuch-tag-key-type) + :group 'notmuch-tag) + +(define-widget 'notmuch-tag-format-type 'lazy + "Customize widget for notmuch-tag-format and friends." + :type '(alist :key-type (regexp :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 + (notmuch-apply-face tag)) + (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"))))) + +(defface notmuch-tag-unread + '((t :foreground "red")) + "Default face used for the unread tag. + +Used in the default value of `notmuch-tag-formats`." + :group 'notmuch-faces) + +(defface notmuch-tag-flagged + '((((class color) + (background dark)) + (:foreground "LightBlue1")) + (((class color) + (background light)) + (:foreground "blue"))) + "Face used for the flagged tag. + +Used in the default value of `notmuch-tag-formats`." + :group 'notmuch-faces) + (defcustom notmuch-tag-formats - '(("unread" (propertize tag 'face '(:foreground "red"))) - ("flagged" (propertize tag 'face '(:foreground "blue")) + '(("unread" (propertize tag 'face 'notmuch-tag-unread)) + ("flagged" (propertize tag 'face 'notmuch-tag-flagged) (notmuch-tag-format-image-data tag (notmuch-tag-star-icon)))) "Custom formats for individual tags. @@ -57,34 +160,62 @@ of a tag to red, use the expression See also `notmuch-tag-format-image', which can help replace tags with images." - :group 'notmuch-search :group 'notmuch-show - :type '(alist :key-type (regexp :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"))))) + :group 'notmuch-faces + :type 'notmuch-tag-format-type) + +(defface notmuch-tag-deleted + '((((class color) (supports :strike-through "red")) :strike-through "red") + (t :inverse-video t)) + "Face used to display deleted tags. + +Used in the default value of `notmuch-tag-deleted-formats`." + :group 'notmuch-faces) + +(defcustom notmuch-tag-deleted-formats + '(("unread" (notmuch-apply-face bare-tag `notmuch-tag-deleted)) + (".*" (notmuch-apply-face tag `notmuch-tag-deleted))) + "Custom formats for tags when deleted. + +For deleted tags the formats in `notmuch-tag-formats` are applied +first and then these formats are applied on top; that is `tag' +passed to the function is the tag with all these previous +formattings applied. The formatted can access the original +unformatted tag as `bare-tag'. + +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 + :group 'notmuch-faces + :type 'notmuch-tag-format-type) + +(defface notmuch-tag-added + '((t :underline "green")) + "Default face used for added tags. + +Used in the default value for `notmuch-tag-added-formats`." + :group 'notmuch-faces) + +(defcustom notmuch-tag-added-formats + '((".*" (notmuch-apply-face tag 'notmuch-tag-added))) + "Custom formats for tags when added. + +For added tags the formats in `notmuch-tag-formats` are applied +first and then these formats are applied on top. + +To disable special formatting of added tags, set this variable to +nil. + +See `notmuch-tag-formats' for full documentation." + :group 'notmuch-show + :group 'notmuch-faces + :type 'notmuch-tag-format-type) (defun notmuch-tag-format-image-data (tag data) "Replace TAG with image DATA, if available. @@ -104,7 +235,7 @@ DATA is the content of an SVG picture (e.g., as returned by (defun notmuch-tag-star-icon () "Return SVG data representing a star icon. This can be used with `notmuch-tag-format-image-data'." -" + "