From 7e7d6889ea40c1203c78183871405c9d5d0aab94 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Tue, 24 May 2011 16:13:43 +0200 Subject: EMACS: Rainbow delimiters updated --- emacs.d/elisp/rainbow-delimiters.el | 253 +++++++++++++++++++++++------------- 1 file changed, 161 insertions(+), 92 deletions(-) (limited to 'emacs.d/elisp/rainbow-delimiters.el') diff --git a/emacs.d/elisp/rainbow-delimiters.el b/emacs.d/elisp/rainbow-delimiters.el index 19f1aa0..43bcd8f 100644 --- a/emacs.d/elisp/rainbow-delimiters.el +++ b/emacs.d/elisp/rainbow-delimiters.el @@ -4,10 +4,10 @@ ;; Author: Jeremy L. Rayman ;; Maintainer: Jeremy L. Rayman ;; Created: 2010-09-02 -;; Version: 1.2.1 -;; Keywords: faces, convenience, lisp, matching, tools -;; EmacsWiki: RainbowDelimiters -;; URL: http://www.emacswiki.org/emacs/rainbow-delimiters.el +;; Version: 1.3 +;; Keywords: faces, convenience, lisp, matching, tools, rainbow, rainbow parentheses, rainbow parens +;; EmacsWiki: http://www.emacswiki.org/emacs/RainbowDelimiters +;; URL: http://www.emacswiki.org/emacs/download/rainbow-delimiters.el ;; 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 @@ -26,28 +26,26 @@ ;;; Commentary: ;; This is a "rainbow parentheses" mode which includes support for -;; parens "()", brackets "[]", and braces "{}". It conveys nesting -;; depth by using a different face for each level. It colors all -;; statements at a given level using the same color - if several -;; statements are all at the same nested depth, they will all be the -;; same color. +;; parens "()", brackets "[]", and braces "{}". It conveys nesting depth +;; by using a different color for each successive nested set of +;; delimiters. It highlights all statements at a given level using the +;; same color - if several statements are all at the same depth, they +;; will all be the same color. ;; ;; Great care has been taken to make this mode FAST. You should see no ;; discernible change in scrolling or editing speed while using it, ;; even with delimiter-rich languages like Clojure, Lisp, and Scheme. ;; -;; The one exception is with extremely large nested data structures -;; having hundreds of delimiters; in that case there will be a brief -;; pause to colorize the structure the very first time it is displayed -;; on screen; from then on editing this structure will perform at full -;; speed. +;; The ultimate goal for the mode is to be useful with a wide variety +;; of programming languages with optional semantics catered to each. ;; -;; Default colors have been chosen with the philosophy that it's -;; better be less intrusive than to be more colorful. Color schemes -;; are always a matter of taste. If you do take the time to design a -;; new color scheme, please post it on the EmacsWiki page! +;; Default colors are subtle, with the philosophy that it's better to +;; avoid being visually intrusive. Color schemes are always a matter of +;; taste. If you take the time to design a new color scheme, please +;; share it (a plain-text list of colors is fine) on the EmacsWiki page! ;; URL: http://www.emacswiki.org/emacs/RainbowDelimiters + ;;; Installation: ;; 1. Place rainbow-delimiters.el on your emacs load-path. @@ -63,6 +61,16 @@ ;; ;; - To activate rainbow-delimiters mode temporarily in a buffer: ;; M-x rainbow-delimiters-mode +;; +;; 5. When using a dark background, if delimiter colors seem washed out +;; you may need to add the following to your dot-emacs and restart: +;; (setq-default 'frame-background-mode 'dark) +;; +;; This is because Emacs can guess frame-background-mode incorrectly, +;; causing rainbow-delimiters to use its light color scheme on dark +;; backgrounds. +;; +;; The light/dark color schemes differ only in their brightness level. ;;; Customization: @@ -75,9 +83,10 @@ ;; - Faces take the form of: ;; 'rainbow-delimiters-depth-#-face' with # being the depth. ;; Depth begins at 1, the outermost color. -;; Faces exist for depths 1-12. -;; - The unmatched delimiter face is: -;; 'rainbow-delimiters-unmatched-delimiter-face' +;; Faces exist for depths 1-9. +;; - The unmatched delimiter face (normally colored red) is: +;; 'rainbow-delimiters-unmatched-face' + ;;; Change Log: @@ -97,15 +106,29 @@ ;; faces, of form 'rainbow-delimiters-depth-#-face'. ;; 1.2.1: (2011-03-29) ;; - Conform to ELPA conventions. +;; 1.3: (2011-05-24) +;; - Add separate light and dark color schemes. +;; - Checkboxes to enable/disable highlighting for each delimiter type. +;; - Improvements to Customize interface. +;; - Infinite depth support by cycling through defined faces repeatedly. +;; - Documentation changes. ;;; TODO: +;; - Add support for independent depth tracking for each delimiter type, +;; for users of C-like languages. +;; - Add Python support - highlighting parens according to indentation level. ;; - Add support for nested tags (XML, HTML) +;; - Set up proper example color-theme.el themes for rainbow-delimiters mode. +;; - Intelligent support for other languages: Ruby, et al. ;;; Issues: ;; - Rainbow-delimiters mode does not appear to change the color of -;; delimiters when Org-mode is enabled. +;; delimiters when Org-mode is also enabled. +;; - Some Emacs versions don't set frame-background-mode to dark automatically, +;; causing users of dark backgrounds to receive the wrong set of colors. +;; See step number 5 in the Installation section. ;;; Code: @@ -123,21 +146,59 @@ :group 'applications) (defgroup rainbow-delimiters-faces nil - "Faces for each nested depth. Used to color delimiter pairs. + "Faces for each successively nested pair of delimiters. -Depths 1-12 are defined. Depth 1 is the outermost delimiter pair." +Colors repeatedly cycle through when nesting depth exceeds innermost defined face." + :tag "Color Scheme" :group 'rainbow-delimiters :link '(custom-group-link "rainbow-delimiters") + :link '(custom-group-link :tag "Toggle Delimiters" "rainbow-delimiters-toggle-delimiter-highlighting") :prefix 'rainbow-delimiters-faces-) +;; Choose which delimiters you wish to highlight in your preferred language: + +(defgroup rainbow-delimiters-toggle-delimiter-highlighting nil + "Choose which delimiters this mode should colorize." + :tag "Toggle Delimiters" + :group 'rainbow-delimiters + :link '(custom-group-link "rainbow-delimiters") + :link '(custom-group-link :tag "Color Scheme" "rainbow-delimiters-faces")) + +(defcustom rainbow-delimiters-highlight-parens-p t + "Enable highlighting of nested parentheses -- (). + +Non-nil (default) enables highlighting of parentheses. +Nil disables parentheses highlighting." + :tag "Highlight Parentheses?" + :type 'boolean + :group 'rainbow-delimiters-toggle-delimiter-highlighting) + +(defcustom rainbow-delimiters-highlight-brackets-p t + "Enable highlighting of nested brackets -- []. + +Non-nil (default) enables highlighting of brackets. +Nil disables bracket highlighting." + :tag "Highlight Brackets?" + :type 'boolean + :group 'rainbow-delimiters-toggle-delimiter-highlighting) + +(defcustom rainbow-delimiters-highlight-braces-p t + "Enable highlighting of nested braces -- {}. + +Non-nil (default) enables highlighting of braces. +Nil disables brace highlighting." + :tag "Highlight Braces?" + :type 'boolean + :group 'rainbow-delimiters-toggle-delimiter-highlighting) + ;;; Faces: ;; Unmatched delimiter face: (defface rainbow-delimiters-unmatched-face - '((t (:foreground "#88090B"))) + '((((background light)) (:foreground "#DD090B")) + (((background dark)) (:foreground "#88090B"))) "Face to color unmatched closing delimiters with." - :group 'rainbow-delimiters :group 'rainbow-delimiters-faces) @@ -146,80 +207,67 @@ Depths 1-12 are defined. Depth 1 is the outermost delimiter pair." ;; Faces for colorizing delimiters at each level: (defface rainbow-delimiters-depth-1-face - '((t (:foreground "grey55"))) - "Rainbow-delimiters nested delimiter face, depth 1 - the outermost pair." + '((((background light)) (:foreground "grey55")) + (((background dark)) (:foreground "grey55"))) + "Nested delimiters face, depth 1 - the outermost pair." + :tag "Rainbow Delimiters Depth 1 Face -- OUTERMOST" :group 'rainbow-delimiters-faces) (defface rainbow-delimiters-depth-2-face - '((t (:foreground "#93a8c6"))) - "Rainbow-delimiters nested delimiter face, depth 2." + '((((background light)) (:foreground "#6e7e94")) + (((background dark)) (:foreground "#93a8c6"))) + "Nested delimiters face, depth 2." :group 'rainbow-delimiters-faces) (defface rainbow-delimiters-depth-3-face - '((t (:foreground "#b0b1a3"))) - "Rainbow-delimiters nested delimiter face, depth 3." + '((((background light)) (:foreground "#84847a")) + (((background dark)) (:foreground "#b0b1a3"))) + "Nested delimiters face, depth 3." :group 'rainbow-delimiters-faces) (defface rainbow-delimiters-depth-4-face - '((t (:foreground "#97b098"))) - "Rainbow-delimiters nested delimiter face, depth 4." + '((((background light)) (:foreground "#718472")) + (((background dark)) (:foreground "#97b098"))) + "Nested delimiters face, depth 4." :group 'rainbow-delimiters-faces) (defface rainbow-delimiters-depth-5-face - '((t (:foreground "#aebed8"))) - "Rainbow-delimiters nested delimiter face, depth 5." + '((((background light)) (:foreground "#828ea2")) + (((background dark)) (:foreground "#aebed8"))) + "Nested delimiters face, depth 5." :group 'rainbow-delimiters-faces) (defface rainbow-delimiters-depth-6-face - '((t (:foreground "#b0b0b3"))) - "Rainbow-delimiters nested delimiter face, depth 6." + '((((background light)) (:foreground "#848486")) + (((background dark)) (:foreground "#b0b0b3"))) + "Nested delimiters face, depth 6." :group 'rainbow-delimiters-faces) (defface rainbow-delimiters-depth-7-face - '((t (:foreground "#90a890"))) - "Rainbow-delimiters nested delimiter face, depth 7." + '((((background light)) (:foreground "#6c7e6c")) + (((background dark)) (:foreground "#90a890"))) + "Nested delimiters face, depth 7." :group 'rainbow-delimiters-faces) (defface rainbow-delimiters-depth-8-face - '((t (:foreground "#a2b6da"))) - "Rainbow-delimiters nested delimiter face, depth 8." + '((((background light)) (:foreground "#7988a3")) + (((background dark)) (:foreground "#a2b6da"))) + "Nested delimiters face, depth 8." :group 'rainbow-delimiters-faces) (defface rainbow-delimiters-depth-9-face - '((t (:foreground "#9cb6ad"))) - "Rainbow-delimiters nested delimiter face, depth 9." + '((((background light)) (:foreground "#758881")) + (((background dark)) (:foreground "#9cb6ad"))) + "Nested delimiters face, depth 9." :group 'rainbow-delimiters-faces) -;; Emacs doesn't sort face names by number correctly above 1-9; trick it into -;; proper sorting by prepending a _ before the faces with depths over 10. -(defface rainbow-delimiters-depth-_10-face - '((t (:foreground "#83787e"))) - "Rainbow-delimiters nested delimiter face, depth 10." - :group 'rainbow-delimiters-faces) +;;; Faces 10+: +;; NOTE: Currently unused. Additional faces for depths 9+ can be added on request. -(defface rainbow-delimiters-depth-_11-face - '((t (:foreground "#e1ddca"))) - "Rainbow-delimiters nested delimiter face, depth 11." - :group 'rainbow-delimiters-faces) - -(defface rainbow-delimiters-depth-_12-face - '((t (:foreground "#e0c7c7"))) - "Rainbow-delimiters nested delimiter face, depth 12." - :group 'rainbow-delimiters-faces) - -;; Variable aliases for faces 10+: -;; We prepend an underline to numbers 10+ to force customize to sort correctly. -;; Here we define aliases without the underline for use everywhere else. -(put 'rainbow-delimiters-depth-10-face - 'face-alias - 'rainbow-delimiters-depth-_10-face) -(put 'rainbow-delimiters-depth-11-face - 'face-alias - 'rainbow-delimiters-depth-_11-face) -(put 'rainbow-delimiters-depth-12-face - 'face-alias - 'rainbow-delimiters-depth-_12-face) +(defconst rainbow-delimiters-max-face-count 9 + "Number of faces defined for highlighting delimiter levels. +Determines depth at which to cycle through faces again.") ;;; Face utility functions @@ -227,13 +275,25 @@ Depths 1-12 are defined. Depth 1 is the outermost delimiter pair." ;; see: http://www.gnu.org/s/emacs/manual/html_node/elisp/Compilation-Tips.html ;; this will cause problems with debugging. To debug, change defsubst -> defun. (defsubst rainbow-delimiters-depth-face (depth) - "Return face-name 'rainbow-delimiters-depth-DEPTH-face' as a string. - + "Return face-name for DEPTH as a string 'rainbow-delimiters-depth-DEPTH-face'. DEPTH is the number of nested levels deep for the delimiter being colorized. Returns a face namestring the of form 'rainbow-delimiters-depth-DEPTH-face', e.g. 'rainbow-delimiters-depth-1-face'." - (concat "rainbow-delimiters-depth-" (number-to-string depth) "-face")) + (concat "rainbow-delimiters-depth-" + (number-to-string + (or + ;; Our nesting depth has a face defined for it. + (and (< depth rainbow-delimiters-max-face-count) + depth) + ;; Deeper than # of defined faces; cycle back through to beginning. + (let ((cycled-depth (mod depth rainbow-delimiters-max-face-count))) + (if (/= cycled-depth 0) + ;; Return face # that corresponds to current nesting level. + (mod depth rainbow-delimiters-max-face-count) + ;; Special case: depth divides evenly into max, correct face # is max. + rainbow-delimiters-max-face-count)))) + "-face")) ;;; Nesting level @@ -288,9 +348,10 @@ Sets text properties: (defun rainbow-delimiters-unpropertize-delimiter (point) "Remove text properties set by rainbow-delimiters mode from char at POINT." - (remove-text-properties point (1+ point) - '(font-lock-face nil - rear-nonsticky nil))) + (with-silent-modifications + (remove-text-properties point (1+ point) + '(font-lock-face nil + rear-nonsticky nil)))) (defun rainbow-delimiters-char-ineligible-p (point) @@ -310,8 +371,22 @@ Returns t if char at point meets one of the following conditions: (and (eq (char-before point) ?\\) ; escaped char, e.g. ?\) - not counted (and (not (eq (char-before (1- point)) ?\\)) ; special-case: ignore ?\\ (eq (char-before (1- point)) ?\?)))))) -;; standard char read syntax '?)' is not tested for because emacs manual states -;; that punctuation such as delimiters should _always_ use escaped '?\)' form. +;; NOTE: standard char read syntax '?)' is not tested for because emacs manual +;; states punctuation such as delimiters should _always_ use escaped '?\)' form. + + +(defsubst rainbow-delimiters-apply-color (delim depth point) + "Apply color for DEPTH to DELIM at POINT following user settings. + +DELIM is a string specifying delimiter type. +DEPTH is the delimiter depth, or corresponding face # if colors are repeating. +POINT is location of character (delimiter) to be colorized." + (and + ;; Ensure user has enabled highlighting of this delimiter type. + (symbol-value (intern-soft + (concat "rainbow-delimiters-highlight-" delim "s-p"))) + (rainbow-delimiters-propertize-delimiter point + depth))) ;;; JIT-Lock functionality @@ -336,29 +411,23 @@ Used by jit-lock for dynamic highlighting." (let ((delim (char-after (point)))) (cond ((eq ?\( delim) ; ( (setq depth (1+ depth)) - (rainbow-delimiters-propertize-delimiter (point) - depth)) + (rainbow-delimiters-apply-color "paren" depth (point))) ((eq ?\) delim) ; ) - (rainbow-delimiters-propertize-delimiter (point) - depth) + (rainbow-delimiters-apply-color "paren" depth (point)) (setq depth (or (and (<= depth 0) 0) ; unmatched paren (1- depth)))) ((eq ?\[ delim) ; [ (setq depth (1+ depth)) - (rainbow-delimiters-propertize-delimiter (point) - depth)) + (rainbow-delimiters-apply-color "bracket" depth (point))) ((eq ?\] delim) ; ] - (rainbow-delimiters-propertize-delimiter (point) - depth) + (rainbow-delimiters-apply-color "bracket" depth (point)) (setq depth (or (and (<= depth 0) 0) ; unmatched bracket (1- depth)))) ((eq ?\{ delim) ; { (setq depth (1+ depth)) - (rainbow-delimiters-propertize-delimiter (point) - depth)) + (rainbow-delimiters-apply-color "brace" depth (point))) ((eq ?\} delim) ; } - (rainbow-delimiters-propertize-delimiter (point) - depth) + (rainbow-delimiters-apply-color "brace" depth (point)) (setq depth (or (and (<= depth 0) 0) ; unmatched brace (1- depth))))))) ;; move past delimiter so re-search-forward doesn't pick it up again -- cgit v1.2.3-54-g00ecf