I have a function that gathers strings that looks like these:

  • Example #1:   :event:lawlist:HIGH:misc:

  • Example #2:  :LOW:

  • Example #3: :MEDIUM:task:george:

I created a monstrosity of a snippet that breaks the string down into various sub-components, adds text properties to each component, and then reconstructs the new string.

Q:  Is there a more sophisticated way to do this project?

(let* (
    (string ":event:lawlist:HIGH:misc:")
    (lst (delete "" (split-string string ":")))
    (separator (propertize ":" 'face '(:foreground "cyan"))) )
  (dolist (e lst)
    (put-text-property 0 (length e) 'face
        ((string= e "event")
          '(:foreground "red"))
        ((string= e "lawlist")
          '(:foreground "blue"))
        ((string= e "HIGH")
          '(:foreground "yellow"))
    (push e new-list))
  (concat separator (mapconcat 'identity (reverse new-list) separator) separator))
  • You don't show/describe the context (the project), so this question seems overly broad. For example, are you manipulating strings when you could be manipulating text in buffers?
    – Drew
    Jul 2 '16 at 22:25
  • Are you decorating org-mode tags? Can you use org-tag-faces for this?
    – erikstokes
    Jul 2 '16 at 22:36
  • @Drew -- I have a custom function that uses an approximate 23-component regexp to extract certain elements of an outline, which is used in a custom version of org-mode. Here is a link to an older version of the regexp and function that I am using stackoverflow.com/a/20960301/2112489 I would prefer to operate on strings, instead of the buffer for this particular project. I realize the popular method is to use (while (re-search-forward ...), but this project is different.
    – lawlist
    Jul 2 '16 at 22:44
  • @erickstokes -- yes, (org-font-lock-add-tag-faces (point-max)) is a means of accomplishing the end goal (but it is not an answer to this question). It operates on the buffer, as @Drew is suggesting. I haven't found an example in org-mode that operates on strings. My snippet works, but it's just not very fancy -- I thought perhaps there were a few functions that I am not aware of that permits walking a string with delimiters or regexp to add text properties. In fact, I'd be rather surprised if such a function does not exist already.
    – lawlist
    Jul 2 '16 at 22:59
  • 1
    Insert the string into a temporary buffer, search for delimiters and add properties, then retrieve the buffer contents as string.
    – wasamasa
    Jul 3 '16 at 7:06

The following is an alternative (but similar) method as described in the question above to walk (loop through) a string and add text properties:

(defun walk-string+add-face (str)
  (loop with start = 0
        with regexp = "[a-zA-Z0-9]+"
        with substring = nil
        with result = nil
        with separator = (propertize ":" 'face '(:foreground "cyan"))
        while (string-match regexp str start)
        do (setq substring (match-string 0 str))
        do (put-text-property 0 (length substring) 'face
               ((string= substring "event")
                 '(:foreground "red"))
               ((string= substring "lawlist")
                 '(:foreground "blue"))
               ((string= substring "HIGH")
                 '(:foreground "yellow"))
        do (push substring result)
        do (setq start (match-end 0))
        finally return
            (mapconcat 'identity (reverse result) separator)

The usage is as follows: (walk-string+add-face ":event:lawlist:HIGH:misc:")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.