Search code examples
emacsorg-mode

Color tags based on regex emacs org-mode


I'm using org-mode and I want all my tags beginning with @ to be colored in blue. Is it possible and how to do it ?

Best regards


Solution

  • The following answer uses the built-in mechanisms of org-mode. The variable org-tag-faces accepts a regexp for the tag, which is the car of the cons cell. The function org-set-tag-faces sets a global variable org-tags-special-faces-re, which combines the tags of the aforementioned cons cell(s). The global variable org-tags-special-faces-re is used by org-font-lock-add-tag-faces to re-search-forward through the org-mode buffer -- locating the matching tags and applying the appropriate face based on the function org-get-tag-face. The original version of the function org-get-tag-face looked for an exact match of the tag found (i.e., the key argument to the function assoc). The revised version of org-get-tag-face adds an additional key search for @.* and returns the proper face if the key is found -- this is necessary because the tag itself will usually look something like @home or @office, whereas our context regexp is @.*.

    (require 'org)
    
    (add-to-list 'org-tag-faces '("@.*" . (:foreground "cyan")))
    
    ;; Reset the global variable to nil, just in case org-mode has already beeen used.
    (when org-tags-special-faces-re
      (setq org-tags-special-faces-re nil))
    
    (defun org-get-tag-face (kwd)
      "Get the right face for a TODO keyword KWD.
    If KWD is a number, get the corresponding match group."
      (if (numberp kwd) (setq kwd (match-string kwd)))
      (let ((special-tag-face (or (cdr (assoc kwd org-tag-faces))
                                  (and (string-match "^@.*" kwd)
                                       (cdr (assoc "@.*" org-tag-faces))))))
        (or (org-face-from-face-or-color 'tag 'org-tag special-tag-face)
            'org-tag)))