emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master 9fdc037 243/271: Merge branch 'develop'


From: Jackson Ray Hamilton
Subject: [elpa] master 9fdc037 243/271: Merge branch 'develop'
Date: Thu, 05 Feb 2015 18:31:37 +0000

branch: master
commit 9fdc0376c2b10aeb1f046699a4c2a14d4eb7aa6e
Merge: 6706bc2 4ac1eaa
Author: Jackson Ray Hamilton <address@hidden>
Commit: Jackson Ray Hamilton <address@hidden>

    Merge branch 'develop'
---
 Makefile                                           |   10 +-
 README.md                                          |  108 +++---
 benchmark/context-coloring-benchmark.el            |   47 +++-
 context-coloring.el                                |  366 +++++++++-----------
 languages/javascript/.jshintrc                     |   24 ++
 languages/javascript/.jslintrc                     |    4 -
 languages/javascript/{bin => binaries}/cli.js      |    0
 languages/javascript/{bin => binaries}/scopifier   |    0
 languages/javascript/{lib => libraries}/escope.js  |    0
 languages/javascript/{lib => libraries}/esprima.js |    0
 .../javascript/{lib => libraries}/estraverse.js    |    0
 languages/javascript/scopifier.js                  |   31 +-
 {lib => libraries}/.dir-locals.el                  |    0
 {lib => libraries}/ert-async.el                    |    0
 {lib => libraries}/js2-mode.el                     |    0
 scopifier-example.png                              |  Bin 2516 -> 0 bytes
 scopifier.png                                      |  Bin 0 -> 2609 bytes
 screenshot.png                                     |  Bin 21829 -> 22006 bytes
 test/context-coloring-test.el                      |  340 ++++++++++++------
 test/fixtures/comments-and-strings.js              |    3 +
 20 files changed, 547 insertions(+), 386 deletions(-)

diff --git a/Makefile b/Makefile
index 2b6569c..e718601 100644
--- a/Makefile
+++ b/Makefile
@@ -5,23 +5,23 @@ all: clean compile test
 bench:
        ${EMACS} -Q \
        -L . \
-       -L lib \
+       -L libraries \
        -l context-coloring \
        -l benchmark/context-coloring-benchmark \
        -f context-coloring-benchmark-run
 
 compile:
        ${EMACS} -Q -batch \
-       -L lib \
-       -f batch-byte-compile *.el lib/*.el
+       -L libraries \
+       -f batch-byte-compile *.el libraries/*.el
 
 clean:
-       rm -f *.elc lib/*.elc
+       rm -f *.elc libraries/*.elc
 
 test:
        ${EMACS} -Q -batch \
        -L . \
-       -L lib \
+       -L libraries \
        -l ert \
        -l ert-async \
        -l context-coloring \
diff --git a/README.md b/README.md
index b687f45..af1be13 100644
--- a/README.md
+++ b/README.md
@@ -9,21 +9,21 @@ Highlights code according to function context.
 - Code in the global scope is one color. Code in functions within the global
   scope is a different color, and code within such functions is another color,
   and so on.
-- Identifiers retain the color of the scope in which they were declared.
-- Comments are gray.
+- Identifiers retain the color of the scope in which they are declared.
 
 Lexical scope information at-a-glance can assist a programmer in understanding
-the overall structure of a program. It can also help curb nasty bugs like name
-shadowing or unexpected assignment. A rainbow can indicate excessive
-complexity. A spot of contrast followed by an assignment expression could be a
-side-effect... or, the state of a closure could be undergoing change.
-
-This coloring strategy is probably more useful than conventional *syntax*
-highlighting. Highlighting keywords can help one to detect spelling errors, and
-highlighting the content between quotation marks can alert one to unclosed
-string literals. But a [linter][] could also spot those errors, and if
-[integrated via flycheck][integration], an extra spot opens up in your editing
-toolbelt.
+the overall structure of a program. It can help to curb nasty bugs like name
+shadowing. A rainbow can indicate excessive complexity. State change within a
+closure is easily monitored.
+
+By default, Context Coloring still highlights comments and strings
+syntactically. It is still easy to differentiate code from non-code, and 
strings
+cannot be confused for variables.
+
+This coloring strategy is probably more useful than conventional syntax
+highlighting. Highlighting keywords can help one to detect spelling errors, but
+a [linter][] could also spot those errors, and if integrated with [flycheck][],
+an extra spot opens up in your editing toolbelt.
 
 Give context coloring a try; you may find that it *changes the way you write
 code*.
@@ -32,14 +32,7 @@ code*.
 
 - Supported languages: JavaScript
 - Light and dark (customizable) color schemes.
-- Insanely fast for regular files, quick for big ones too.
-  - jQuery (9191 lines): 0.20 seconds (js2-mode), 0.57 seconds (js-mode)
-  - Lodash (6786 lines): 0.07 seconds (js2-mode), 0.35 seconds (js-mode)
-  - Async (1124 lines): 0.03 seconds (js2-mode), 0.17 seconds (js-mode)
-  - mkdirp (98 lines): 0.002 seconds (js2-mode), 0.09 seconds (js-mode)
-
-\* js2-mode parses idly, irrespective of this plugin; its benchmarks represent
-coloring only. js-mode benchmarks represent parsing and coloring.
+- Very fast for files under 1000 lines.
 
 ## Usage
 
@@ -72,45 +65,35 @@ make compile
 
 ## Customizing
 
-You can adjust the colors to your liking using
-`context-coloring-set-colors`. The first argument is an alist of levels, and 
the
-optional second argument is the new total number of levels. This plugin does 
not
-figure out the total for you; you need to specify it if your number of colors 
is
-different from the default (`7`).
+You can adjust the colors to your liking using `context-coloring-set-colors`.
 
 I like to take the colors from an existing theme and use those to create a
-rainbow that matches that theme. The end result is consistent, and usually 
looks
-as good as the theme does. Here's an example for `tango`:
+rainbow that matches that theme. Here's an example for [`zenburn`][zenburn] 
(which is the
+theme used in the screenshot above).
 
 ```lisp
 ;; ~/.emacs
-(load-theme 'tango)
+(load-theme 'zenburn t)
 (require 'context-coloring)
-(defun jrh-context-coloring-tango ()
-  (interactive)
-  (context-coloring-set-colors
-   '((comment . "#5f615c")
-     (0       . "#2e3436") ; Globals.
-     (1       . "#346604")
-     (2       . "#204a87")
-     (3       . "#5c3566")
-     (4       . "#a40000")
-     (5       . "#b35000")
-     (6       . "#c4a000")
-     (7       . "#8ae234") ; "You're screwed" colors.
-     (8       . "#8cc4ff")
-     (9       . "#ad7fa8")
-     (10      . "#ef2929")
-     (11      . "#fcaf3e")
-     (12      . "#fce94f"))
-   13))
-(jrh-context-coloring-tango)
+(context-coloring-set-colors
+ "#DCDCCC"
+ "#93E0E3"
+ "#BFEBBF"
+ "#F0DFAF"
+ "#DFAF8F"
+ "#CC9393"
+ "#DC8CC3"
+ "#94BFF3"
+ "#9FC59F"
+ "#D0BF8F"
+ "#DCA3A3")
 ```
 
 ## Extending
 
-To add support for a new language, write a "scopifier" for it, and add an entry
-to `context-coloring-dispatch-plist`. Then the plugin should handle the rest.
+To add support for a new language, write a "scopifier" for it, and define a new
+coloring dispatch strategy with `context-coloring-define-dispatch`. Then the
+plugin should handle the rest.
 
 A "scopifier" is a CLI program that reads a buffer's contents from stdin and
 writes a JSON array of numbers to stdout. Every three numbers in the array
@@ -134,15 +117,34 @@ applying level 1 coloring to the range &#91;9, 23) would 
result in the following
 coloring:
 
 <p align="center">
-  <img alt="Screenshot of ranges &#91;1, 24) and &#91;9, 23)." 
src="scopifier-example.png" title="Screenshot">
+  <img alt="Screenshot of ranges &#91;1, 24) and &#91;9, 23)." 
src="scopifier.png" title="Screenshot">
 </p>
 
 If there is an abstract syntax tree generator for your language, you can walk
 the syntax tree, find variables and scopes, and build their positions and 
levels
 into an array like the one above.
 
-[linter]: https://github.com/jacksonrayhamilton/jslinted
-[integration]: https://github.com/jacksonrayhamilton/jslinted#emacs-integration
+For example, a Ruby scopifier might be defined and implemented like this:
+
+```lisp
+(context-coloring-define-dispatch 'ruby
+  :modes '(ruby-mode)
+  :executable "ruby"
+  :command "/home/username/scopifier")
+```
+
+```ruby
+#!/usr/bin/env ruby
+def scopifier(code)
+    # Parse code.
+    # Return an array.
+end
+print scopifier ARGF.read
+```
+
+[linter]: http://jshint.com/about/
+[flycheck]: http://www.flycheck.org/
+[zenburn]: http://github.com/bbatsov/zenburn-emacs
 [point]: http://www.gnu.org/software/emacs/manual/html_node/elisp/Point.html
 [js2-mode]: https://github.com/mooz/js2-mode
 [node]: http://nodejs.org/download/
diff --git a/benchmark/context-coloring-benchmark.el 
b/benchmark/context-coloring-benchmark.el
index 6d66f18..cc5b221 100644
--- a/benchmark/context-coloring-benchmark.el
+++ b/benchmark/context-coloring-benchmark.el
@@ -1,12 +1,32 @@
-;; -*- lexical-binding: t; -*-
+;;; benchmark/context-coloring-benchmark.el --- Benchmarks for context 
coloring. -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2014 Jackson Ray Hamilton
+
+;; 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 <http://www.gnu.org/licenses/>.
+
+;;; Code:
 
 (defconst context-coloring-benchmark-path
-  (file-name-directory (or load-file-name buffer-file-name)))
+  (file-name-directory (or load-file-name buffer-file-name))
+  "This file's directory.")
 
 (defun context-coloring-benchmark-resolve-path (path)
+  "Resolve PATH from this file's directory."
   (expand-file-name path context-coloring-benchmark-path))
 
 (defun context-coloring-benchmark-log-results (result-file fixture)
+  "Log benchmarking results for FIXTURE to RESULT-FILE."
   (elp-results)
   (let ((results-buffer (current-buffer)))
     (with-temp-buffer
@@ -19,9 +39,13 @@
   (append-to-file nil nil result-file))
 
 (defun context-coloring-benchmark-next-tick (function)
+  "Defer execution of FUNCTION to clear the stack and to ensure
+asynchrony."
   (run-at-time 0.001 nil function))
 
 (defun context-coloring-benchmark-next (list continue stop)
+  "Run the next test in LIST by calling CONTINUE.  When LIST is
+exhausted, call STOP instead."
   (if (null list)
       (context-coloring-benchmark-next-tick stop)
     (context-coloring-benchmark-next-tick
@@ -33,9 +57,12 @@
           (context-coloring-benchmark-next (cdr list) continue stop)))))))
 
 (defun context-coloring-benchmark-async (title setup teardown fixtures 
callback)
+  "Measure the performance of all FIXTURES, calling CALLBACK when
+all are done."
   (funcall setup)
   (let ((result-file (context-coloring-benchmark-resolve-path
-                      (concat "./logs/results-" title "-" (format-time-string 
"%s") ".log"))))
+                      (format "./logs/results-%s-%s.log"
+                              title (format-time-string "%s")))))
     (context-coloring-benchmark-next
      fixtures
      (lambda (path next)
@@ -69,16 +96,20 @@
   '("./fixtures/jquery-2.1.1.js"
     "./fixtures/lodash-2.4.1.js"
     "./fixtures/async-0.9.0.js"
-    "./fixtures/mkdirp-0.5.0.js"))
+    "./fixtures/mkdirp-0.5.0.js")
+  "Arbitrary JavaScript files for performance scrutiny.")
 
 (defun context-coloring-benchmark-js-mode-setup ()
+  "Preparation logic for `js-mode'."
   (add-hook 'js-mode-hook 'context-coloring-mode)
   (elp-instrument-package "context-coloring-"))
 
 (defun context-coloring-benchmark-js-mode-teardown ()
+  "Cleanup logic for `js-mode'."
   (remove-hook 'js-mode-hook 'context-coloring-mode))
 
 (defun context-coloring-benchmark-js-mode-run (callback)
+  "Benchmark `js-mode', then call CALLBACK."
   (context-coloring-benchmark-async
    "js-mode"
    'context-coloring-benchmark-js-mode-setup
@@ -87,6 +118,7 @@
    callback))
 
 (defun context-coloring-benchmark-js2-mode-setup ()
+  "Preparation logic for `js2-mode'."
   (require 'js2-mode)
   (setq js2-mode-show-parse-errors nil)
   (setq js2-mode-show-strict-warnings nil)
@@ -95,6 +127,7 @@
   (elp-instrument-package "context-coloring-"))
 
 (defun context-coloring-benchmark-js2-mode-teardown ()
+  "Cleanup logic for `js2-mode'."
   (remove-hook 'js2-mode-hook 'context-coloring-mode)
   (setq auto-mode-alist (delete '("\\.js\\'" . js2-mode)
                                 auto-mode-alist))
@@ -102,6 +135,7 @@
   (setq js2-mode-show-parse-errors t))
 
 (defun context-coloring-benchmark-js2-mode-run (callback)
+  "Benchmark `js2-mode', then call CALLBACK."
   (context-coloring-benchmark-async
    "js2-mode"
    'context-coloring-benchmark-js2-mode-setup
@@ -110,6 +144,7 @@
    callback))
 
 (defun context-coloring-benchmark-run ()
+  "Benchmark all modes, then exit."
   (context-coloring-benchmark-next
    '(context-coloring-benchmark-js-mode-run
      context-coloring-benchmark-js2-mode-run)
@@ -117,3 +152,7 @@
      (funcall function next))
    (lambda ()
      (kill-emacs))))
+
+(provide 'context-coloring-benchmark)
+
+;;; context-coloring-benchmark.el ends here
diff --git a/context-coloring.el b/context-coloring.el
index ef7164b..40465f8 100644
--- a/context-coloring.el
+++ b/context-coloring.el
@@ -4,7 +4,7 @@
 
 ;; Author: Jackson Ray Hamilton <address@hidden>
 ;; Keywords: context coloring syntax highlighting
-;; Version: 2.1.0
+;; Version: 3.0.0
 ;; Package-Requires: ((emacs "24") (js2-mode "20141228"))
 
 ;; This program is free software; you can redistribute it and/or modify
@@ -22,14 +22,7 @@
 
 ;;; Commentary:
 
-;; Colors code by scope, rather than by syntax.
-
-;; A range of characters encompassing a scope is colored according to its 
level;
-;; the global scope is white, scopes within the global scope are yellow, scopes
-;; within scopes within the global scope are green, etc.  Variables defined in 
a
-;; parent scope which are referenced from child scopes retain the same color as
-;; the scope in which they are defined; a variable defined in the global scope
-;; will be the same color when referenced from nested scopes.
+;; Highlights code according to function context.
 
 ;; To use, add the following to your ~/.emacs:
 
@@ -53,16 +46,21 @@
 (defcustom context-coloring-delay 0.25
   "Delay between a buffer update and colorization.
 
-Increase this if your machine is high-performing. Decrease it if it ain't.
+Increase this if your machine is high-performing.  Decrease it if
+it ain't.
 
 Supported modes: `js-mode', `js3-mode'"
   :group 'context-coloring)
 
+(defcustom context-coloring-comments-and-strings t
+  "If non-nil, also color comments and strings using `font-lock'."
+  :group 'context-coloring)
+
 (defcustom context-coloring-js-block-scopes nil
   "If non-nil, also color block scopes in the scope hierarchy in JavaScript.
 
-The block-scope-inducing `let' and `const' are introduced in
-ES6. If you are writing ES6 code, enable this; otherwise, don't.
+The block-scope-inducing `let' and `const' are introduced in ES6.
+If you are writing ES6 code, enable this; otherwise, don't.
 
 Supported modes: `js2-mode'"
   :group 'context-coloring)
@@ -94,150 +92,78 @@ used.")
 
 ;;; Faces
 
-(defface context-coloring-level--1-face
-  '((((type tty)) (:foreground "white"))
-    (t (:foreground "#7f7f7f")))
-  "Context coloring face, level -1; comments."
-  :group 'context-coloring-faces)
-
-(defface context-coloring-level-0-face
-  '((((type tty)) (:foreground "white"))
-    (((background light)) (:foreground "#000000"))
-    (((background dark)) (:foreground "#ffffff")))
-  "Context coloring face, level 0; global scope."
-  :group 'context-coloring-faces)
-
-(defface context-coloring-level-1-face
-  '((((type tty)) (:foreground "yellow"))
-    (((background light)) (:foreground "#007f80"))
-    (((background dark)) (:foreground "#ffff80")))
-  "Context coloring face, level 1."
-  :group 'context-coloring-faces)
-
-(defface context-coloring-level-2-face
-  '((((type tty)) (:foreground "green"))
-    (((background light)) (:foreground "#001580"))
-    (((background dark)) (:foreground "#cdfacd")))
-  "Context coloring face, level 2."
-  :group 'context-coloring-faces)
-
-(defface context-coloring-level-3-face
-  '((((type tty)) (:foreground "cyan"))
-    (((background light)) (:foreground "#550080"))
-    (((background dark)) (:foreground "#d8d8ff")))
-  "Context coloring face, level 3."
-  :group 'context-coloring-faces)
-
-(defface context-coloring-level-4-face
-  '((((type tty)) (:foreground "blue"))
-    (((background light)) (:foreground "#802b00"))
-    (((background dark)) (:foreground "#e7c7ff")))
-  "Context coloring face, level 4."
-  :group 'context-coloring-faces)
-
-(defface context-coloring-level-5-face
-  '((((type tty)) (:foreground "magenta"))
-    (((background light)) (:foreground "#6a8000"))
-    (((background dark)) (:foreground "#ffcdcd")))
-  "Context coloring face, level 5."
-  :group 'context-coloring-faces)
-
-(defface context-coloring-level-6-face
-  '((((type tty)) (:foreground "red"))
-    (((background light)) (:foreground "#008000"))
-    (((background dark)) (:foreground "#ffe390")))
-  "Context coloring face, level 6."
-  :group 'context-coloring-faces)
-
-;;; Additional 6 faces for insane levels of nesting
-
-(defface context-coloring-level-7-face
-  '((t (:inherit context-coloring-level-1-face)))
-  "Context coloring face, level 7."
-  :group 'context-coloring-faces)
-
-(defface context-coloring-level-8-face
-  '((t (:inherit context-coloring-level-2-face)))
-  "Context coloring face, level 8."
-  :group 'context-coloring-faces)
-
-(defface context-coloring-level-9-face
-  '((t (:inherit context-coloring-level-3-face)))
-  "Context coloring face, level 9."
-  :group 'context-coloring-faces)
-
-(defface context-coloring-level-10-face
-  '((t (:inherit context-coloring-level-4-face)))
-  "Context coloring face, level 10."
-  :group 'context-coloring-faces)
-
-(defface context-coloring-level-11-face
-  '((t (:inherit context-coloring-level-5-face)))
-  "Context coloring face, level 11."
-  :group 'context-coloring-faces)
-
-(defface context-coloring-level-12-face
-  '((t (:inherit context-coloring-level-6-face)))
-  "Context coloring face, level 12."
-  :group 'context-coloring-faces)
-
-(defcustom context-coloring-face-count 7
-  "Number of faces defined for highlighting levels.
-Determines level at which to cycle through faces again."
-  :group 'context-coloring)
+(defun context-coloring-defface (level tty light dark)
+  (let ((face (intern (format "context-coloring-level-%s-face" level)))
+        (doc (format "Context coloring face, level %s." level)))
+    (eval (macroexpand `(defface ,face
+                          '((((type tty)) (:foreground ,tty))
+                            (((background light)) (:foreground ,light))
+                            (((background dark)) (:foreground ,dark)))
+                          ,doc
+                          :group 'context-coloring)))))
+
+(defvar context-coloring-face-count nil
+  "Number of faces available for context coloring.")
+
+(defun context-coloring-defface-default (level)
+  (context-coloring-defface level "white" "#3f3f3f" "#cdcdcd"))
+
+(defun context-coloring-set-colors-default ()
+  (context-coloring-defface 0 "white"   "#000000" "#ffffff")
+  (context-coloring-defface 1 "yellow"  "#007f80" "#ffff80")
+  (context-coloring-defface 2 "green"   "#001580" "#cdfacd")
+  (context-coloring-defface 3 "cyan"    "#550080" "#d8d8ff")
+  (context-coloring-defface 4 "blue"    "#802b00" "#e7c7ff")
+  (context-coloring-defface 5 "magenta" "#6a8000" "#ffcdcd")
+  (context-coloring-defface 6 "red"     "#008000" "#ffe390")
+  (context-coloring-defface-default 7)
+  (setq context-coloring-face-count 8))
+
+(context-coloring-set-colors-default)
 
 
 ;;; Face functions
 
 (defsubst context-coloring-face-symbol (level)
   "Returns a symbol for a face with LEVEL."
-  (intern-soft (concat "context-coloring-level-" (number-to-string level) 
"-face")))
-
-(defun context-coloring-set-colors (pairs &optional count)
-  "Set an alist of PAIRS for different levels' colors. Also sets
-`context-coloring-face-count' to COUNT, if specified."
-  (dolist (pair pairs)
-    (let ((level (car pair))
-          (color (cdr pair)))
-      (cond
-       ((eq level 'comment)
-        (setq level -1)))
-      (set-face-foreground (context-coloring-face-symbol level) color)))
-  (when count
-    (setq context-coloring-face-count count)))
+  ;; `concat' is faster than `format' here.
+  (intern-soft (concat "context-coloring-level-"
+                       (number-to-string level)
+                       "-face")))
+
+(defun context-coloring-set-colors (&rest colors)
+  "Set context coloring's levels' coloring to COLORS, where the
+Nth element of COLORS is level N's color."
+  (setq context-coloring-face-count (length colors))
+  (let ((level 0))
+    (dolist (color colors)
+      ;; Ensure there are available faces to contain new colors.
+      (when (not (context-coloring-face-symbol level))
+        (context-coloring-defface-default level))
+      (set-face-foreground (context-coloring-face-symbol level) color)
+      (setq level (+ level 1)))))
 
 (defsubst context-coloring-level-face (level)
-  "Return face-name for LEVEL as a string 
\"context-coloring-level-LEVEL-face\".
-For example: \"context-coloring-level-1-face\". Automatically
-wraps around to reuse faces when levels get too deep."
-  (context-coloring-face-symbol
-   (or
-    ;; Has a face directly mapping to it.
-    (and (< level context-coloring-face-count)
-         level)
-    ;; After the number of available faces are used up, pretend the 0th
-    ;; face doesn't exist.
-    (+ 1
-       (mod (- level 1)
-            (- context-coloring-face-count 1))))))
+  "Returns the face name for LEVEL."
+  (context-coloring-face-symbol (min level context-coloring-face-count)))
 
 
 ;;; Colorization utilities
 
-(defun context-coloring-uncolorize-buffer ()
-  "Clears all coloring in the current buffer."
-  (remove-text-properties
-   (point-min)
-   (point-max)
-   `(face nil rear-nonsticky nil)))
-
 (defsubst context-coloring-colorize-region (start end level)
   "Colorizes characters from the 1-indexed START (inclusive) to
 END (exclusive) with the face corresponding to LEVEL."
   (add-text-properties
    start
    end
-   `(face ,(context-coloring-level-face level) rear-nonsticky t)))
+   `(face ,(context-coloring-level-face level))))
+
+(defsubst context-coloring-maybe-colorize-comments-and-strings ()
+  "Colorizes the current buffer's comments and strings if
+`context-coloring-comments-and-strings' is non-nil."
+  (when context-coloring-comments-and-strings
+    (save-excursion
+      (font-lock-fontify-syntactically-region (point-min) (point-max)))))
 
 
 ;;; js2-mode colorization
@@ -255,7 +181,8 @@ END (exclusive) with the face corresponding to LEVEL."
                enclosing-scope)
            (while (and current-scope
                        (js2-node-parent current-scope)
-                       (setq enclosing-scope (js2-node-get-enclosing-scope 
current-scope)))
+                       (setq enclosing-scope
+                             (js2-node-get-enclosing-scope current-scope)))
              (when (or context-coloring-js-block-scopes
                        (let ((type (js2-scope-type current-scope)))
                          (or (= type js2-SCRIPT)
@@ -296,10 +223,6 @@ generated by js2-mode."
      (lambda (node end-p)
        (when (null end-p)
          (cond
-          ((js2-comment-node-p node)
-           (context-coloring-js2-colorize-node
-            node
-            -1))
           ((js2-scope-p node)
            (context-coloring-js2-colorize-node
             node
@@ -318,16 +241,17 @@ generated by js2-mode."
                 node
                 (context-coloring-js2-scope-level defining-scope))))))
          ;; The `t' indicates to search children.
-         t)))))
+         t)))
+    (context-coloring-maybe-colorize-comments-and-strings)))
 
 
 ;;; Shell command scopification / colorization
 
 (defun context-coloring-apply-tokens (tokens)
   "Processes a vector of TOKENS to apply context-based coloring
-to the current buffer. Tokens are 3 integers: start, end,
-level. The vector is flat, with a new token occurring after every
-3rd element."
+to the current buffer.  Tokens are 3 integers: start, end, level.
+The vector is flat, with a new token occurring after every 3rd
+element."
   (with-silent-modifications
     (let ((i 0)
           (len (length tokens)))
@@ -336,7 +260,8 @@ level. The vector is flat, with a new token occurring after 
every
          (elt tokens i)
          (elt tokens (+ i 1))
          (elt tokens (+ i 2)))
-        (setq i (+ i 3))))))
+        (setq i (+ i 3))))
+    (context-coloring-maybe-colorize-comments-and-strings)))
 
 (defun context-coloring-parse-array (input)
   "Specialized JSON parser for a flat array of numbers."
@@ -393,24 +318,75 @@ Invokes CALLBACK when complete."
 
 ;;; Dispatch
 
-(defvar context-coloring-javascript-scopifier
-  `(:type shell-command
-          :executable "node"
-          :command ,(expand-file-name
-                     "./languages/javascript/bin/scopifier"
-                     context-coloring-path)))
-
-(defvar context-coloring-js2-colorizer
-  `(:type elisp
-          :colorizer context-coloring-js2-colorize))
-
-(defcustom context-coloring-dispatch-plist
-  `(js-mode ,context-coloring-javascript-scopifier
-            js2-mode ,context-coloring-js2-colorizer
-            js3-mode ,context-coloring-javascript-scopifier)
-  "Property list mapping major modes to scopification and
-colorization programs."
-  :group 'context-coloring)
+(defvar context-coloring-dispatch-hash-table (make-hash-table :test 'eq)
+  "Mapping of dispatch strategy names to their corresponding
+  property lists, which contain details about the strategies.")
+
+(defvar context-coloring-mode-hash-table (make-hash-table :test 'eq)
+  "Mapping of major mode names to dispatch property lists.")
+
+(defun context-coloring-select-dispatch (mode dispatch)
+  "Use DISPATCH for MODE."
+  (puthash
+   mode
+   (gethash
+    dispatch
+    context-coloring-dispatch-hash-table)
+   context-coloring-mode-hash-table))
+
+(defun context-coloring-define-dispatch (symbol &rest properties)
+  "Define a new dispatch named SYMBOL with PROPERTIES.
+
+A \"dispatch\" is a property list describing a strategy for
+coloring a buffer. There are three possible strategies: Parse and
+color in a single function (`:colorizer'), parse in a function
+that returns scope data (`:scopifier'), or parse with a shell
+command that returns scope data (`:command'). In the latter two
+cases, the scope data will be used to automatically color the
+buffer.
+
+PROPERTIES must include `:modes' and one of `:colorizer',
+`:scopifier' or `:command'.
+
+`:modes' - List of major modes this dispatch is valid for.
+
+`:colorizer' - Symbol referring to a function that parses and
+colors the buffer.
+
+`:scopifier' - Symbol referring to a function that parses the
+buffer a returns a flat vector of start, end and level data.
+
+`:executable' - Optional name of an executable required by
+`:command'.
+
+`:command' - Shell command to execute with the current buffer
+sent via stdin, and with a flat JSON array of start, end and
+level data returned via stdout."
+  (let ((modes (plist-get properties :modes))
+        (colorizer (plist-get properties :colorizer))
+        (scopifier (plist-get properties :scopifier))
+        (command (plist-get properties :command)))
+    (when (null modes)
+      (error "No mode defined for dispatch"))
+    (when (not (or colorizer
+                   scopifier
+                   command))
+      (error "No colorizer, scopifier or command defined for dispatch"))
+    (puthash symbol properties context-coloring-dispatch-hash-table)
+    (dolist (mode modes)
+      (when (null (gethash mode context-coloring-mode-hash-table))
+        (puthash mode properties context-coloring-mode-hash-table)))))
+
+(context-coloring-define-dispatch 'javascript-node
+  :modes '(js-mode js3-mode)
+  :executable "node"
+  :command (expand-file-name
+            "./languages/javascript/binaries/scopifier"
+            context-coloring-path))
+
+(context-coloring-define-dispatch 'javascript-js2
+  :modes '(js2-mode)
+  :colorizer 'context-coloring-js2-colorize)
 
 (defun context-coloring-dispatch (&optional callback)
   "Determines the optimal track for scopification / colorization
@@ -418,31 +394,25 @@ of the current buffer, then executes it.
 
 Invokes CALLBACK when complete. It is invoked synchronously for
 elisp tracks, and asynchronously for shell command tracks."
-  (let ((dispatch (plist-get context-coloring-dispatch-plist major-mode)))
+  (let ((dispatch (gethash major-mode context-coloring-mode-hash-table)))
     (if (null dispatch)
         (message "%s" "Context coloring is not available for this major mode"))
-    (let ((type (plist-get dispatch :type)))
+    (let (colorizer
+          scopifier
+          command
+          executable)
       (cond
-       ((eq type 'elisp)
-        (let ((colorizer (plist-get dispatch :colorizer))
-              (scopifier (plist-get dispatch :scopifier)))
-          (cond
-           (colorizer
-            (funcall colorizer)
-            (if callback (funcall callback)))
-           (scopifier
-            (context-coloring-apply-tokens (funcall scopifier))
-            (if callback (funcall callback)))
-           (t
-            (error "No `:colorizer' nor `:scopifier' specified for dispatch of 
`:type' elisp")))))
-       ((eq type 'shell-command)
-        (let ((executable (plist-get dispatch :executable))
-              (command (plist-get dispatch :command)))
-          (if (null command)
-              (error "No `:command' specified for dispatch of `:type' 
shell-command"))
-          (if (and (not (null executable))
-                   (null (executable-find executable)))
-              (message "Executable \"%s\" not found" executable))
+       ((setq colorizer (plist-get dispatch :colorizer))
+        (funcall colorizer)
+        (if callback (funcall callback)))
+       ((setq scopifier (plist-get dispatch :scopifier))
+        (context-coloring-apply-tokens (funcall scopifier))
+        (if callback (funcall callback)))
+       ((setq command (plist-get dispatch :command))
+        (setq executable (plist-get dispatch :executable))
+        (if (and (not (null executable))
+                 (null (executable-find executable)))
+            (message "Executable \"%s\" not found" executable)
           (context-coloring-scopify-shell-command command callback)))))))
 
 
@@ -461,17 +431,16 @@ Invokes CALLBACK when complete; see 
`context-coloring-dispatch'."
        (if callback (funcall callback))))))
 
 (defun context-coloring-change-function (_start _end _length)
-  "Registers a change so that a context-colored buffer can be
-colorized soon."
+  "Registers a change so that a buffer can be colorized soon."
   ;; Tokenization is obsolete if there was a change.
   (context-coloring-kill-scopifier)
   (setq context-coloring-changed t))
 
 (defun context-coloring-maybe-colorize ()
-  "Colorize unders certain conditions. This will run as an idle
-timer, so firstly the buffer must not be some other
-buffer. Additionally, the buffer must have changed, otherwise
-colorizing would be redundant."
+  "Colorize unders certain conditions.  This will run as an idle
+timer, so firstly the buffer must not be some other buffer.
+Additionally, the buffer must have changed, otherwise colorizing
+would be redundant."
   (when (and (eq context-coloring-buffer (window-buffer (selected-window)))
              context-coloring-changed)
     (setq context-coloring-changed nil)
@@ -515,8 +484,15 @@ colorizing would be redundant."
     (when (not (equal major-mode 'js2-mode))
       ;; Only recolor idly.
       (setq context-coloring-colorize-idle-timer
-            (run-with-idle-timer context-coloring-delay t 
'context-coloring-maybe-colorize)))))
+            (run-with-idle-timer
+             context-coloring-delay
+             t
+             'context-coloring-maybe-colorize)))))
 
 (provide 'context-coloring)
 
+;; Local Variables:
+;; eval: (when (fboundp 'rainbow-mode) (rainbow-mode 1))
+;; End:
+
 ;;; context-coloring.el ends here
diff --git a/languages/javascript/.jshintrc b/languages/javascript/.jshintrc
new file mode 100644
index 0000000..82211c2
--- /dev/null
+++ b/languages/javascript/.jshintrc
@@ -0,0 +1,24 @@
+{
+  "bitwise": true,
+  "camelcase": true,
+  "curly": true,
+  "devel": true,
+  "eqeqeq": true,
+  "forin": true,
+  "freeze": true,
+  "funcscope": true,
+  "immed": true,
+  "indent": 4,
+  "latedef": true,
+  "newcap": true,
+  "noarg": true,
+  "node": true,
+  "noempty": true,
+  "nonbsp": true,
+  "nonew": true,
+  "plusplus": true,
+  "quotmark": "single",
+  "strict": true,
+  "undef": true,
+  "unused": "strict"
+}
diff --git a/languages/javascript/.jslintrc b/languages/javascript/.jslintrc
deleted file mode 100644
index 03c17c5..0000000
--- a/languages/javascript/.jslintrc
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "node": true,
-  "nomen": true
-}
diff --git a/languages/javascript/bin/cli.js 
b/languages/javascript/binaries/cli.js
similarity index 100%
rename from languages/javascript/bin/cli.js
rename to languages/javascript/binaries/cli.js
diff --git a/languages/javascript/bin/scopifier 
b/languages/javascript/binaries/scopifier
similarity index 100%
rename from languages/javascript/bin/scopifier
rename to languages/javascript/binaries/scopifier
diff --git a/languages/javascript/lib/escope.js 
b/languages/javascript/libraries/escope.js
similarity index 100%
rename from languages/javascript/lib/escope.js
rename to languages/javascript/libraries/escope.js
diff --git a/languages/javascript/lib/esprima.js 
b/languages/javascript/libraries/esprima.js
similarity index 100%
rename from languages/javascript/lib/esprima.js
rename to languages/javascript/libraries/esprima.js
diff --git a/languages/javascript/lib/estraverse.js 
b/languages/javascript/libraries/estraverse.js
similarity index 100%
rename from languages/javascript/lib/estraverse.js
rename to languages/javascript/libraries/estraverse.js
diff --git a/languages/javascript/scopifier.js 
b/languages/javascript/scopifier.js
index 7a82570..becbcc7 100644
--- a/languages/javascript/scopifier.js
+++ b/languages/javascript/scopifier.js
@@ -1,7 +1,22 @@
+// Copyright (C) 2014 Jackson Ray Hamilton
+
+// 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 <http://www.gnu.org/licenses/>.
+
 'use strict';
 
-var escope = require('./lib/escope'),
-    esprima = require('./lib/esprima');
+var escope = require('./libraries/escope'),
+    esprima = require('./libraries/esprima');
 
 // Given code, returns an array of tokens for context-coloring.
 function scopifier(code) {
@@ -11,7 +26,6 @@ function scopifier(code) {
 
     var analyzedScopes,
         ast,
-        comment,
         definition,
         definitionsCount,
         definitionsIndex,
@@ -30,7 +44,6 @@ function scopifier(code) {
     // Gracefully handle parse errors by doing nothing.
     try {
         ast = esprima.parse(code, {
-            comment: true,
             range: true
         });
         analyzedScopes = escope.analyze(ast).scopes;
@@ -109,16 +122,6 @@ function scopifier(code) {
         }
     }
 
-    for (i = 0; i < ast.comments.length; i += 1) {
-        comment = ast.comments[i];
-        range = comment.range;
-        tokens.push(
-            range[0] + 1,
-            range[1] + 1,
-            -1
-        );
-    }
-
     return scopes.concat(tokens);
 }
 
diff --git a/lib/.dir-locals.el b/libraries/.dir-locals.el
similarity index 100%
rename from lib/.dir-locals.el
rename to libraries/.dir-locals.el
diff --git a/lib/ert-async.el b/libraries/ert-async.el
similarity index 100%
rename from lib/ert-async.el
rename to libraries/ert-async.el
diff --git a/lib/js2-mode.el b/libraries/js2-mode.el
similarity index 100%
rename from lib/js2-mode.el
rename to libraries/js2-mode.el
diff --git a/scopifier-example.png b/scopifier-example.png
deleted file mode 100644
index 1d690cb..0000000
Binary files a/scopifier-example.png and /dev/null differ
diff --git a/scopifier.png b/scopifier.png
new file mode 100644
index 0000000..1ec5d10
Binary files /dev/null and b/scopifier.png differ
diff --git a/screenshot.png b/screenshot.png
index fe45d9b..89665b7 100644
Binary files a/screenshot.png and b/screenshot.png differ
diff --git a/test/context-coloring-test.el b/test/context-coloring-test.el
index 52a93fb..93fea64 100644
--- a/test/context-coloring-test.el
+++ b/test/context-coloring-test.el
@@ -1,22 +1,44 @@
-;; -*- lexical-binding: t; -*-
+;;; test/context-coloring-test.el --- Tests for context coloring. -*- 
lexical-binding: t; -*-
 
-(defconst context-coloring-test-path
-  (file-name-directory (or load-file-name buffer-file-name)))
+;; Copyright (C) 2014 Jackson Ray Hamilton
+
+;; 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 <http://www.gnu.org/licenses/>.
 
-(defun context-coloring-test-resolve-path (path)
-  (expand-file-name path context-coloring-test-path))
+;;; Code:
+
+;;; Test running utilities
+
+(defconst context-coloring-test-path
+  (file-name-directory (or load-file-name buffer-file-name))
+  "This file's directory.")
 
-(defun get-string-from-file (path)
+(defun context-coloring-test-read-file (path)
+  "Read a file's contents into a string."
   (with-temp-buffer
-    (insert-file-contents path)
+    (insert-file-contents (expand-file-name path context-coloring-test-path))
     (buffer-string)))
 
-(defun context-coloring-test-read-file (path)
-  (get-string-from-file (context-coloring-test-resolve-path path)))
+(defun context-coloring-test-setup ()
+  "Preparation code to run before all tests."
+  (setq context-coloring-comments-and-strings nil))
 
 (defun context-coloring-test-cleanup ()
+  "Cleanup code to run after all tests."
+  (setq context-coloring-comments-and-strings t)
   (setq context-coloring-after-colorize-hook nil)
-  (setq context-coloring-js-block-scopes nil))
+  (setq context-coloring-js-block-scopes nil)
+  (context-coloring-set-colors-default))
 
 (defmacro context-coloring-test-with-fixture (fixture &rest body)
   "Evaluate BODY in a temporary buffer with the relative
@@ -24,12 +46,13 @@ FIXTURE."
   `(with-temp-buffer
      (unwind-protect
          (progn
+           (context-coloring-test-setup)
            (insert (context-coloring-test-read-file ,fixture))
            ,@body)
        (context-coloring-test-cleanup))))
 
 (defun context-coloring-test-with-temp-buffer-async (callback)
-  "Create a temporary buffer, and evaluate CALLBACK there. A
+  "Create a temporary buffer, and evaluate CALLBACK there.  A
 teardown callback is passed to CALLBACK for it to invoke when it
 is done."
   (let ((temp-buffer (make-symbol "temp-buffer")))
@@ -43,12 +66,15 @@ is done."
               (kill-buffer temp-buffer))
          (set-buffer previous-buffer))))))
 
-(defun context-coloring-test-with-fixture-async (fixture callback)
+(defun context-coloring-test-with-fixture-async (fixture callback &optional 
setup)
   "Evaluate CALLBACK in a temporary buffer with the relative
-FIXTURE. A teardown callback is passed to CALLBACK for it to
-invoke when it is done."
+FIXTURE.  A teardown callback is passed to CALLBACK for it to
+invoke when it is done.  An optional SETUP callback can be passed
+to run arbitrary code before the mode is invoked."
   (context-coloring-test-with-temp-buffer-async
    (lambda (done-with-temp-buffer)
+     (context-coloring-test-setup)
+     (if setup (funcall setup))
      (insert (context-coloring-test-read-file fixture))
      (funcall
       callback
@@ -56,7 +82,13 @@ invoke when it is done."
         (context-coloring-test-cleanup)
         (funcall done-with-temp-buffer))))))
 
-(defun context-coloring-test-js-mode (fixture callback)
+
+;;; Test defining utilities
+
+(defun context-coloring-test-js-mode (fixture callback &optional setup)
+  "Use FIXTURE as the subject matter for test logic in CALLBACK.
+Optionally, provide setup code to run before the mode is
+instantiated in SETUP."
   (context-coloring-test-with-fixture-async
    fixture
    (lambda (done-with-test)
@@ -64,9 +96,11 @@ invoke when it is done."
      (context-coloring-mode)
      (context-coloring-colorize
       (lambda ()
-        (funcall callback done-with-test))))))
+        (funcall callback done-with-test))))
+   setup))
 
 (defmacro context-coloring-test-js2-mode (fixture &rest body)
+  "Use FIXTURE as the subject matter for test logic in BODY."
   `(context-coloring-test-with-fixture
     ,fixture
     (require 'js2-mode)
@@ -76,34 +110,133 @@ invoke when it is done."
     (context-coloring-mode)
     ,@body))
 
+(defmacro context-coloring-test-deftest-js-mode (name)
+  "Define an asynchronous test for `js-mode' in the typical
+format."
+  (let ((test-name (intern (format "context-coloring-test-js-mode-%s" name)))
+        (fixture (format "./fixtures/%s.js" name))
+        (function-name (intern-soft (format "context-coloring-test-js-%s" 
name))))
+    `(ert-deftest-async ,test-name (done)
+                        (context-coloring-test-js-mode
+                         ,fixture
+                         (lambda (teardown)
+                           (unwind-protect
+                               (,function-name)
+                             (funcall teardown))
+                           (funcall done))))))
+
+(defmacro context-coloring-test-deftest-js2-mode (name)
+    "Define a test for `js2-mode' in the typical format."
+  (let ((test-name (intern (format "context-coloring-test-js2-mode-%s" name)))
+        (fixture (format "./fixtures/%s.js" name))
+        (function-name (intern-soft (format "context-coloring-test-js-%s" 
name))))
+    `(ert-deftest ,test-name ()
+       (context-coloring-test-js2-mode
+        ,fixture
+        (,function-name)))))
+
+
+;;; Assertion functions
+
+(defmacro context-coloring-test-assert-region (&rest body)
+  "Skeleton for asserting something about the face of points in a
+region.  Provides the free variables `i', `length', `point',
+`face' and `actual-level'."
+  `(let ((i 0)
+         (length (- end start)))
+     (while (< i length)
+       (let* ((point (+ i start))
+              (face (get-text-property point 'face))
+              actual-level)
+         ,@body)
+       (setq i (+ i 1)))))
+
 (defconst context-coloring-test-level-regexp
-  "context-coloring-level-\\([[:digit:]]+\\)-face")
+  "context-coloring-level-\\([[:digit:]]+\\)-face"
+  "Regular expression for extracting a level from a face.")
 
 (defun context-coloring-test-assert-region-level (start end level)
-  (let ((i 0)
-        (length (- end start)))
-    (while (< i length)
-      (let* ((point (+ i start))
-             (face (get-text-property point 'face))
-             actual-level)
-        (when (not (when face
-                     (let* ((face-string (symbol-name face))
-                            (matches (string-match 
context-coloring-test-level-regexp face-string)))
-                       (when matches
-                         (setq actual-level (string-to-number (substring 
face-string
-                                                                         
(match-beginning 1)
-                                                                         
(match-end 1))))
-                         (= level actual-level)))))
-          (ert-fail (format "Expected level in region [%s, %s), which is 
\"%s\", to be %s; but at point %s, it was %s"
-                            start end (buffer-substring-no-properties start 
end) level point actual-level))))
-      (setq i (+ i 1)))))
+  "Assert that all points in the range [START, END) are of level
+LEVEL."
+  (context-coloring-test-assert-region
+   (when (not (when face
+                (let* ((face-string (symbol-name face))
+                       (matches (string-match
+                                 context-coloring-test-level-regexp
+                                 face-string)))
+                  (when matches
+                    (setq actual-level (string-to-number
+                                        (substring face-string
+                                                   (match-beginning 1)
+                                                   (match-end 1))))
+                    (= level actual-level)))))
+     (ert-fail (format (concat "Expected level in region [%s, %s), "
+                               "which is \"%s\", to be %s; "
+                               "but at point %s, it was %s")
+                       start end
+                       (buffer-substring-no-properties start end) level
+                       point actual-level)))))
+
+(defun context-coloring-test-assert-region-face (start end expected-face)
+  "Assert that all points in the range [START, END) have the face
+EXPECTED-FACE."
+  (context-coloring-test-assert-region
+   (when (not (eq face expected-face))
+     (ert-fail (format (concat "Expected face in region [%s, %s), "
+                               "which is \"%s\", to be %s; "
+                               "but at point %s, it was %s")
+                       start end
+                       (buffer-substring-no-properties start end) expected-face
+                       point face)))))
+
+(defun context-coloring-test-assert-region-comment-delimiter (start end)
+  "Assert that all points in the range [START, END) have
+`font-lock-comment-delimiter-face'."
+  (context-coloring-test-assert-region-face
+   start end 'font-lock-comment-delimiter-face))
+
+(defun context-coloring-test-assert-region-comment (start end)
+    "Assert that all points in the range [START, END) have
+`font-lock-comment-face'."
+  (context-coloring-test-assert-region-face
+   start end 'font-lock-comment-face))
+
+(defun context-coloring-test-assert-region-string (start end)
+    "Assert that all points in the range [START, END) have
+`font-lock-string-face'."
+  (context-coloring-test-assert-region-face
+   start end 'font-lock-string-face))
 
 (defun context-coloring-test-assert-message (expected)
+  "Assert that the *Messages* buffer has message EXPECTED."
   (with-current-buffer "*Messages*"
-    (let ((messages (split-string (buffer-substring-no-properties (point-min) 
(point-max)) "\n")))
+    (let ((messages (split-string
+                     (buffer-substring-no-properties
+                      (point-min)
+                      (point-max))
+                     "\n")))
       (let ((message (car (nthcdr (- (length messages) 2) messages))))
         (should (equal message expected))))))
 
+(defun context-coloring-test-assert-face (level foreground)
+  "Assert that a face for LEVEL exists and that its `:foreground'
+is FOREGROUND."
+  (let* ((face (context-coloring-face-symbol level))
+         actual-foreground)
+    (when (not face)
+      (ert-fail (format (concat "Expected face for level `%s' to exist; "
+                                "but it didn't")
+                        level)))
+    (setq actual-foreground (face-attribute face :foreground))
+    (when (not (string-equal foreground actual-foreground))
+      (ert-fail (format (concat "Expected face for level `%s' "
+                                "to have foreground `%s'; but it was `%s'")
+                        level
+                        foreground actual-foreground)))))
+
+
+;;; The tests
+
 (ert-deftest context-coloring-test-unsupported-mode ()
   (context-coloring-test-with-fixture
    "./fixtures/function-scopes.js"
@@ -111,6 +244,32 @@ invoke when it is done."
    (context-coloring-test-assert-message
     "Context coloring is not available for this major mode")))
 
+(ert-deftest context-coloring-test-set-colors ()
+  ;; This test has an irreversible side-effect in that it defines faces beyond
+  ;; 7. Faces 0 through 7 are reset to their default states, so it might not
+  ;; matter, but be aware anyway.
+  (context-coloring-set-colors
+   "#000000"
+   "#111111"
+   "#222222"
+   "#333333"
+   "#444444"
+   "#555555"
+   "#666666"
+   "#777777"
+   "#888888"
+   "#999999")
+  (context-coloring-test-assert-face 0 "#000000")
+  (context-coloring-test-assert-face 1 "#111111")
+  (context-coloring-test-assert-face 2 "#222222")
+  (context-coloring-test-assert-face 3 "#333333")
+  (context-coloring-test-assert-face 4 "#444444")
+  (context-coloring-test-assert-face 5 "#555555")
+  (context-coloring-test-assert-face 6 "#666666")
+  (context-coloring-test-assert-face 7 "#777777")
+  (context-coloring-test-assert-face 8 "#888888")
+  (context-coloring-test-assert-face 9 "#999999"))
+
 (defun context-coloring-test-js-function-scopes ()
   (context-coloring-test-assert-region-level 1 9 0)
   (context-coloring-test-assert-region-level 9 23 1)
@@ -125,38 +284,16 @@ invoke when it is done."
   (context-coloring-test-assert-region-level 82 87 2)
   (context-coloring-test-assert-region-level 87 89 1))
 
-(ert-deftest-async context-coloring-test-js-mode-function-scopes (done)
-  (context-coloring-test-js-mode
-   "./fixtures/function-scopes.js"
-   (lambda (teardown)
-     (unwind-protect
-         (context-coloring-test-js-function-scopes)
-       (funcall teardown))
-     (funcall done))))
-
-(ert-deftest context-coloring-test-js2-mode-function-scopes ()
-  (context-coloring-test-js2-mode
-   "./fixtures/function-scopes.js"
-   (context-coloring-test-js-function-scopes)))
+(context-coloring-test-deftest-js-mode function-scopes)
+(context-coloring-test-deftest-js2-mode function-scopes)
 
 (defun context-coloring-test-js-global ()
   (context-coloring-test-assert-region-level 20 28 1)
   (context-coloring-test-assert-region-level 28 35 0)
   (context-coloring-test-assert-region-level 35 41 1))
 
-(ert-deftest-async context-coloring-test-js-mode-global (done)
-  (context-coloring-test-js-mode
-   "./fixtures/global.js"
-   (lambda (teardown)
-     (unwind-protect
-         (context-coloring-test-js-global)
-       (funcall teardown))
-     (funcall done))))
-
-(ert-deftest context-coloring-test-js2-mode-global ()
-  (context-coloring-test-js2-mode
-   "./fixtures/global.js"
-   (context-coloring-test-js-global)))
+(context-coloring-test-deftest-js-mode global)
+(context-coloring-test-deftest-js2-mode global)
 
 (defun context-coloring-test-js-block-scopes ()
   (context-coloring-test-assert-region-level 20 64 1)
@@ -167,10 +304,7 @@ invoke when it is done."
    (context-coloring-test-assert-region-level 41 42 1)
    (context-coloring-test-assert-region-level 42 64 2))
 
-(ert-deftest context-coloring-test-js2-mode-block-scopes ()
-  (context-coloring-test-js2-mode
-   "./fixtures/block-scopes.js"
-   (context-coloring-test-js-block-scopes)))
+(context-coloring-test-deftest-js2-mode block-scopes)
 
 (defun context-coloring-test-js-catch ()
   (context-coloring-test-assert-region-level 20 27 1)
@@ -182,36 +316,14 @@ invoke when it is done."
   (context-coloring-test-assert-region-level 102 117 3)
   (context-coloring-test-assert-region-level 117 123 2))
 
-(ert-deftest-async context-coloring-test-js-mode-catch (done)
-  (context-coloring-test-js-mode
-   "./fixtures/catch.js"
-   (lambda (teardown)
-     (unwind-protect
-         (context-coloring-test-js-catch)
-       (funcall teardown))
-     (funcall done))))
-
-(ert-deftest context-coloring-test-js2-mode-catch ()
-  (context-coloring-test-js2-mode
-   "./fixtures/catch.js"
-   (context-coloring-test-js-catch)))
+(context-coloring-test-deftest-js-mode catch)
+(context-coloring-test-deftest-js2-mode catch)
 
 (defun context-coloring-test-js-key-names ()
   (context-coloring-test-assert-region-level 20 63 1))
 
-(ert-deftest-async context-coloring-test-js-mode-key-names (done)
-  (context-coloring-test-js-mode
-   "./fixtures/key-names.js"
-   (lambda (teardown)
-     (unwind-protect
-         (context-coloring-test-js-key-names)
-       (funcall teardown))
-     (funcall done))))
-
-(ert-deftest context-coloring-test-js2-mode-key-names ()
-  (context-coloring-test-js2-mode
-   "./fixtures/key-names.js"
-   (context-coloring-test-js-key-names)))
+(context-coloring-test-deftest-js-mode key-names)
+(context-coloring-test-deftest-js2-mode key-names)
 
 (defun context-coloring-test-js-property-lookup ()
   (context-coloring-test-assert-region-level 20 26 0)
@@ -221,35 +333,41 @@ invoke when it is done."
   (context-coloring-test-assert-region-level 57 63 0)
   (context-coloring-test-assert-region-level 63 74 1))
 
-(ert-deftest-async context-coloring-test-js-mode-property-lookup (done)
-  (context-coloring-test-js-mode
-   "./fixtures/property-lookup.js"
-   (lambda (teardown)
-     (unwind-protect
-         (context-coloring-test-js-property-lookup)
-       (funcall teardown))
-     (funcall done))))
-
-(ert-deftest context-coloring-test-js2-mode-property-lookup ()
-  (context-coloring-test-js2-mode
-   "./fixtures/property-lookup.js"
-   (context-coloring-test-js-property-lookup)))
+(context-coloring-test-deftest-js-mode property-lookup)
+(context-coloring-test-deftest-js2-mode property-lookup)
 
 (defun context-coloring-test-js-key-values ()
   (context-coloring-test-assert-region-level 78 79 1))
 
-(ert-deftest-async context-coloring-test-js-mode-key-values (done)
+(context-coloring-test-deftest-js-mode key-values)
+(context-coloring-test-deftest-js2-mode key-values)
+
+(defun context-coloring-test-js-comments-and-strings ()
+  (context-coloring-test-assert-region-comment-delimiter 1 4)
+  (context-coloring-test-assert-region-comment 4 8)
+  (context-coloring-test-assert-region-comment-delimiter 9 12)
+  (context-coloring-test-assert-region-comment 12 19)
+  (context-coloring-test-assert-region-string 20 32)
+  (context-coloring-test-assert-region-level 32 33 0))
+
+(ert-deftest-async context-coloring-test-js-mode-comments-and-strings (done)
   (context-coloring-test-js-mode
-   "./fixtures/key-values.js"
+   "./fixtures/comments-and-strings.js"
    (lambda (teardown)
      (unwind-protect
-         (context-coloring-test-js-key-values)
+         (context-coloring-test-js-comments-and-strings)
        (funcall teardown))
-     (funcall done))))
+     (funcall done))
+   (lambda ()
+     (setq context-coloring-comments-and-strings t))))
 
-(ert-deftest context-coloring-test-js2-mode-key-values ()
+(ert-deftest context-coloring-test-js2-mode-comments-and-strings ()
   (context-coloring-test-js2-mode
-   "./fixtures/key-values.js"
-   (context-coloring-test-js-key-values)))
+   "./fixtures/comments-and-strings.js"
+   (setq context-coloring-comments-and-strings t)
+   (context-coloring-colorize)
+   (context-coloring-test-js-comments-and-strings)))
 
 (provide 'context-coloring-test)
+
+;;; context-coloring-test.el ends here
diff --git a/test/fixtures/comments-and-strings.js 
b/test/fixtures/comments-and-strings.js
new file mode 100644
index 0000000..9910b02
--- /dev/null
+++ b/test/fixtures/comments-and-strings.js
@@ -0,0 +1,3 @@
+// Foo.
+/* Bar. */
+'use strict';



reply via email to

[Prev in Thread] Current Thread [Next in Thread]