;;; rainbow-parens.el --- Argh! My eyes! ;; Copyright (C) 2009 Mark Triggs ;; Author: Mark Triggs with thanks to help ;; from Alex Osborne ;; Keywords: pain, horror ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; The horror! M-x rainbow-paren-mode to start it. ;;; Code: ;; Too lazy to define my own functions for figuring out whether I'm in a string ;; or comment... (require 'paredit) (require 'cl) (defun rainbow-paren-face-from-colour (colour) (let ((face (make-face (intern (concat "rainbow-paren-" colour "-face"))))) (set-face-foreground face colour) face)) (defvar *rainbow-paren-faces* `[,(rainbow-paren-face-from-colour "red") ,(rainbow-paren-face-from-colour "yellow") ,(rainbow-paren-face-from-colour "pink") ,(rainbow-paren-face-from-colour "green") ,(rainbow-paren-face-from-colour "purple") ,(rainbow-paren-face-from-colour "orange") ,(rainbow-paren-face-from-colour "blue")]) (defun rainbow-paren-this-paren-nesting () (let ((point (point)) (depth 0)) (while (ignore-errors (setq point (scan-lists point -1 1))) (when (= (char-after point) 40) (setq depth (1+ depth)))) depth)) (defun rainbow-paren-face-for-depth (n) (aref *rainbow-paren-faces* (mod n (length *rainbow-paren-faces*)))) (defun rainbow-paren-apply (point face) (let* ((os (overlays-at point)) (o (or (some (lambda (o) (and (eq (overlay-get o 'type) 'rainbow-paren) o)) os) (make-overlay point (1+ point) nil t nil)))) (overlay-put o 'type 'rainbow-paren) (overlay-put o 'face face) (overlay-put o 'evaporate t))) (defun rainbow-paren-boring-paren-p () (or (paredit-in-string-p) (paredit-in-comment-p))) (defun rainbow-paren-skip-boring (bound) (while (and (< (point) bound) (rainbow-paren-boring-paren-p)) (forward-char 1))) (defun rainbow-paren-fontify (beg end) (save-excursion (goto-char beg) (rainbow-paren-skip-boring end) (let* ((depth (rainbow-paren-this-paren-nesting))) (while (< (point) end) (rainbow-paren-skip-boring end) (cond ((= (char-after (point)) 40) (rainbow-paren-apply (point) (rainbow-paren-face-for-depth depth)) (setq depth (1+ depth))) ((= (char-after (point)) 41) (setq depth (1- depth)) (rainbow-paren-apply (point) (rainbow-paren-face-for-depth depth)))) (forward-char 1))))) (defun rainbow-paren-unfontify (beg end) (mapc #'(lambda (o) (when (eq (overlay-get o 'type) 'rainbow-paren) (delete-overlay o))) (overlays-in beg end))) (define-minor-mode rainbow-paren-mode "Angry fruit salad parens" nil " R" nil (cond ((not rainbow-paren-mode) (jit-lock-unregister 'rainbow-paren-fontify) (rainbow-paren-unfontify (point-min) (point-max))) (t (jit-lock-register 'rainbow-paren-fontify)))) (provide 'rainbow-parens) ;;; rainbow-parens.el ends here