Living with rainbow-delimiters-mode

Update: more up-to-date version of this article is this link: Small rainbow-delimiters tutorial | Yoo Box

1. Introduction to Rainbow Delimiters

Rainbow delimiters mode highlights lisp parentheses of different nesting depth in different colors in Emacs. The Github link and the EmacsWiki link have setup instructions. It also highlights other nesting delimiters like square brackets (for Emacs Lisp and Clojure) and curly brackets (for Clojure).

If every time you type a paren, other parens (below the current line) get recolored, that probably means that you are not using paredit or autopair that automatically inserts close parens for you.

2. customizations from the customize interface

M-x customize-group RET rainbow-delimiters RET

It provides user options for turning off highlighting of some delimiters and you can also customize the faces used by the package.

3. other customizations

3.1. bold for the outermost parens and then gray all the way

You might want to have just the outermost parens display in bold, and have all other parens display in gray color. The following code will do the job. You can also customize the two faces defined in the code if you want.

(defface my-outermost-paren-face
  '((t (:weight bold)))
  "Face used for outermost parens.")

(defface my-inner-paren-face
  ;; face definition I got from esk-paren-face of starter-kit-lisp
  '((((class color) (background dark))
     (:foreground "grey50"))
    (((class color) (background light))
     (:foreground "grey55")))
  "Face used to dim inner parentheses.")

(require 'cl-lib)
(cl-loop
 for index from 1 to rainbow-delimiters-max-face-count
 do
 (let ((face (intern (format "rainbow-delimiters-depth-%d-face" index))))
   (set-face-attribute face nil
                       :foreground 'unspecified
                       :inherit (if (= index 1)
                                    'my-outermost-paren-face
                                  'my-inner-paren-face))))

3.2. using stronger colors

You might want to use colors stronger than default. By strong, I mean more saturated, i.e., less gray. Use this code:

(require 'cl-lib)
(require 'color)
(cl-loop
 for index from 1 to rainbow-delimiters-max-face-count
 do
 (let ((face (intern (format "rainbow-delimiters-depth-%d-face" index))))
   (cl-callf color-saturate-name (face-foreground face) 30)))

3.3. making unmatched parens stand out more

Unmatched close parens are highlighted in a color that stands out by default. But if you customize rainbow delimiters to use strong colors, you have to customize the face for unmatched parens too so that they stand out again among all those colorful parens.

This code will make unmatched parens display in bold red and with a strike through.

(set-face-attribute 'rainbow-delimiters-unmatched-face nil
                    :foreground 'unspecified
                    :inherit 'error
                    :strike-through t)

This code will make them display in violet background.

(require 'paren) ; show-paren-mismatch is defined in paren.el
(set-face-attribute 'rainbow-delimiters-unmatched-face nil
                    :foreground 'unspecified
                    :inherit 'show-paren-mismatch)

3.4. alternating dual color

Following code is for alternating between just two colors.

(require 'cl-lib)

(defvar my-paren-dual-colors
  '("hot pink" "dodger blue"))

(cl-loop
 for index from 1 to rainbow-delimiters-max-face-count
 do
 (set-face-foreground
  (intern (format "rainbow-delimiters-depth-%d-face" index))
  (elt my-paren-dual-colors
       (if (cl-evenp index) 0 1))))

The idea is to maximize eye detection of off-by-one paren depth difference especially in code that uses one space indent convention such as cond forms. One doesn’t usually rely on colored parens to read Lisp code. He just relies on indentation to see the structure of code in most cases. Colored parens are helpful in a few cases such as some defface or let or cond forms where some lines are dense or where one space indent convention is used while the form is vertically spread out. See examples in appendix.

3.5. other dual color combinations

subtle colors:

'("#a07070" "#7070a0")

louder colors:

'("deep pink" "royal blue")

blending more into white background:

'("pink" "sky blue")

3.6. bold outermost parens

(set-face-attribute 'rainbow-delimiters-depth-1-face nil
                    :weight 'bold)

4. complications

4.1. what happens at deeper depth?

The package provides faces for depth 1 to depth 9. For deeper depth, it cycles through the faces repeatedly. It seems that whether it should cycle just from depths 2 to 9 (excluding the face for depth 1) is not set in stone yet. The customization for singling out outermost parens and the customization for dual color are somewhat buggy customizations if 1 is included in the cycle, which is the case as of now.

5. appendix

5.1. examples of forms where colored parens help seeing structure

These examples are simplistic for demonstration purposes. For each example, imagine a bigger example.

(when t
  ;; example where arguments of mapcar are
  ;; indented with just one space
  (blah blah)
  (mapcar
   (lambda (x y)
     (blah blah)
     (blah blah))
   (list 1
         2))
  (blah blah)

  ;; example: let form
  (let ((a 1)
        (b (+ 1
              1))
        (c 3))
    (blah blah
          blah)
    (blah (+ 1 1)
          blah)
    (blah))

  ;; example: let form 2
  ;; with a line that is about to grow dense
  (let ((a 1) (b (+ 1 1)) (c 3)) ; <--
    (blah blah
          blah)
    (blah (+ 1 1)
          blah)
    (blah))

  ;; example: cond form
  ;; one space indent (between (1) and (2))
  (cond ((blih 1 x)
         (blah (+ 1 1)
               blah)
         (blah blah ; <--(1)
               blah))
        ((blih x ; <--(2)
               (+ blah blah))
         (blah blah))
        (t (blah)))

  ;; example: cond form 2
  ;; with one space indent (between (1), (2), (3))
  (cond
   ((blih 1 x)
    (blah (+ 1 1)
          blah)
    (blah blah ;<--(1)
          blah))
   ((blih x ;<--(2)
          (+ blah blah))
    (blah blah)))
  (blah blah ;<--(3)
        blah)
  (blah)

  t)
This entry was posted in Emacs and tagged . Bookmark the permalink.

One Response to Living with rainbow-delimiters-mode

  1. Thanks a bunch for these customizations! I was looking for some brighter colors than the defaults and didn’t feel like doing my own. A couple of your snippets went right into my dotemacs 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s