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

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

[elpa] master 8a083d5 28/28: Merge commit '283a006be8e96c7e011dedddb460b


From: Jackson Ray Hamilton
Subject: [elpa] master 8a083d5 28/28: Merge commit '283a006be8e96c7e011dedddb460b289d335a9fb' from context-coloring
Date: Tue, 05 May 2015 11:10:28 +0000

branch: master
commit 8a083d5bfb1e4c97880879569a43d1eaa22f43db
Merge: 510f0ff 283a006
Author: Jackson Ray Hamilton <address@hidden>
Commit: Jackson Ray Hamilton <address@hidden>

    Merge commit '283a006be8e96c7e011dedddb460b289d335a9fb' from 
context-coloring
---
 packages/context-coloring/.gitignore               |    3 +-
 packages/context-coloring/.travis.yml              |    2 +
 packages/context-coloring/Cask                     |    9 +
 packages/context-coloring/Makefile                 |   39 ++--
 packages/context-coloring/README.md                |   61 ++---
 .../benchmark/context-coloring-benchmark.el        |    9 +-
 packages/context-coloring/context-coloring.el      |  104 +++++---
 packages/context-coloring/scripts/dependencies     |    2 -
 .../scripts/download-dependencies.el               |   61 -----
 packages/context-coloring/test/binaries/noop       |    5 +
 .../test/context-coloring-coverage.el              |  154 +++++++++++
 .../context-coloring/test/context-coloring-test.el |  276 ++++++++++++++++---
 .../test/fixtures/unterminated-comment.js          |    6 +
 13 files changed, 519 insertions(+), 212 deletions(-)

diff --git a/packages/context-coloring/.gitignore 
b/packages/context-coloring/.gitignore
index f090318..a269508 100644
--- a/packages/context-coloring/.gitignore
+++ b/packages/context-coloring/.gitignore
@@ -1,3 +1,4 @@
 *.elc
+.cask/
 /benchmark/logs/
-/libraries/
+/test/coverage/
diff --git a/packages/context-coloring/.travis.yml 
b/packages/context-coloring/.travis.yml
index 2dcc8a6..a732f67 100644
--- a/packages/context-coloring/.travis.yml
+++ b/packages/context-coloring/.travis.yml
@@ -15,6 +15,8 @@ install:
         sudo apt-get update -qq &&
         sudo apt-get install -qq emacs24 emacs24-el;
     fi
+  - curl -fsSL https://raw.github.com/cask/cask/master/go | python
+  - export PATH="/home/travis/.cask/bin:$PATH"
   - npm install -g scopifier
 
 script:
diff --git a/packages/context-coloring/Cask b/packages/context-coloring/Cask
new file mode 100644
index 0000000..db61c1c
--- /dev/null
+++ b/packages/context-coloring/Cask
@@ -0,0 +1,9 @@
+(source melpa)
+
+(package-file "context-coloring.el")
+
+(depends-on "js2-mode")
+
+(development
+ (depends-on "ert-async")
+ (depends-on "undercover"))
diff --git a/packages/context-coloring/Makefile 
b/packages/context-coloring/Makefile
index 3a6a0be..bd82b88 100644
--- a/packages/context-coloring/Makefile
+++ b/packages/context-coloring/Makefile
@@ -1,41 +1,48 @@
+CASK = cask
 EMACS = emacs
-DEPENDENCIES = libraries/ert-async.el libraries/js2-mode.el
+DEPENDENCIES = .cask/
 
 all: uncompile compile test
 
 bench: ${DEPENDENCIES}
-       ${EMACS} -Q \
+       ${CASK} exec ${EMACS} -Q \
        -L . \
-       -L libraries \
        -l context-coloring \
-       -l benchmark/context-coloring-benchmark \
+       -l benchmark/context-coloring-benchmark.el \
        -f context-coloring-benchmark-run
 
 compile: ${DEPENDENCIES}
-       ${EMACS} -Q -batch \
+       ${CASK} exec ${EMACS} -Q -batch \
        -L . \
-       -L libraries \
-       -f batch-byte-compile *.el libraries/*.el
+       -f batch-byte-compile *.el
 
 uncompile:
-       rm -f *.elc libraries/*.elc
+       rm -f *.elc
 
 clean: uncompile
-       rm -f ${DEPENDENCIES}
+       rm -rf ${DEPENDENCIES}
 
 ${DEPENDENCIES}:
-       ${EMACS} -Q -batch \
-       -l scripts/download-dependencies.el \
-       -f download-dependencies
+       ${CASK}
 
 test: ${DEPENDENCIES}
-       ${EMACS} -Q -batch \
+       ${CASK} exec ${EMACS} -Q -batch \
        -L . \
-       -L libraries \
        -l ert \
        -l ert-async \
-       -l context-coloring \
+       -l test/context-coloring-coverage.el \
+       -f context-coloring-coverage-ci-init \
+       -l test/context-coloring-test.el \
+       -f ert-run-tests-batch-and-exit
+
+cover: ${DEPENDENCIES}
+       ${CASK} exec ${EMACS} -Q -batch \
+       -L . \
+       -l ert \
+       -l ert-async \
+       -l test/context-coloring-coverage.el \
+       -f context-coloring-coverage-local-init \
        -l test/context-coloring-test.el \
        -f ert-run-tests-batch-and-exit
 
-.PHONY: all bench compile uncompile clean test
+.PHONY: all bench compile uncompile clean test cover
diff --git a/packages/context-coloring/README.md 
b/packages/context-coloring/README.md
index 7eeacf7..6c895de 100644
--- a/packages/context-coloring/README.md
+++ b/packages/context-coloring/README.md
@@ -1,32 +1,15 @@
-# Context Coloring [![Build 
Status](https://travis-ci.org/jacksonrayhamilton/context-coloring.png?branch=develop)](https://travis-ci.org/jacksonrayhamilton/context-coloring)
+# Context Coloring [![Build 
Status](https://travis-ci.org/jacksonrayhamilton/context-coloring.png?branch=master)](https://travis-ci.org/jacksonrayhamilton/context-coloring)
 [![Coverage 
Status](https://coveralls.io/repos/jacksonrayhamilton/context-coloring/badge.svg?branch=master)](https://coveralls.io/r/jacksonrayhamilton/context-coloring?branch=master)
 
 <p align="center">
   <img alt="Screenshot of JavaScript code highlighted by context." 
src="screenshot.png" title="Screenshot">
 </p>
 
-Highlights code according to function context.
+Highlights code by scope.  Top-level scopes are one color, second-level scopes
+are another color, and so on.  Variables retain the color of the scope in which
+they are defined.  A variable defined in an outer scope referenced by an inner
+scope is colored the same as the outer scope.
 
-- 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 are declared.
-
-Lexical scope information at-a-glance can assist a programmer in understanding
-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*.
+By default, comments and strings are still highlighted syntactically.
 
 ## Features
 
@@ -61,7 +44,7 @@ cd context-coloring/
 make compile
 ```
 
-- Add the following to your `~/.emacs` file:
+- Add the following to your init file:
 
 ```lisp
 (add-to-list 'load-path "~/.emacs.d/context-coloring")
@@ -76,7 +59,7 @@ npm install -g scopifier
 
 ## Usage
 
-Add the following to your `~/.emacs` file:
+Add the following to your init file:
 
 ```lisp
 ;; non-js2-mode users:
@@ -104,7 +87,7 @@ Add the following to your `~/.emacs` file:
 ### Color Schemes
 
 Color schemes for custom themes are automatically applied when those themes are
-active. Built-in theme support is available for: `ample`, `anti-zenburn`,
+active.  Built-in theme support is available for: `ample`, `anti-zenburn`,
 `grandshell`, `leuven`, `monokai`, `solarized`, `spacegray`, `tango` and
 `zenburn`.
 
@@ -131,30 +114,30 @@ See `C-h f context-coloring-define-theme` for more info 
on theme parameters.
 ## Extending
 
 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. (See `C-h f context-coloring-define-dispatch` 
for
-more info on dispatch strategies.)
+coloring dispatch strategy with `context-coloring-define-dispatch`.  Then the
+plugin should handle the rest.  (See `C-h f context-coloring-define-dispatch`
+for more info on dispatch strategies.)
 
 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
-represent a range of color. For instance, if I fed the following string of
-JavaScript code to a scopifier:
+writes a JSON array of numbers to stdout.  Every three numbers in the array
+represent a range of color.  For instance, if I fed the following string of
+JavaScript code to a scopifier
 
 ```js
 var a = function () {};
 ```
 
-Then the scopifier would produce the following array:
+then the scopifier would produce the following array
 
 ```js
 [1,24,0,9,23,1]
 ```
 
-Where, for every three numbers, the first number is a 1-indexed start 
[point][],
+where, for every three numbers, the first number is a 1-indexed start 
[point][],
 the second number is an exclusive end point, and the third number is a scope
-level. The result of applying level 0 coloring to the range &#91;1, 24) and 
then
-applying level 1 coloring to the range &#91;9, 23) would result in the 
following
-coloring:
+level.  The result of applying level 0 coloring to the range &#91;1, 24) and
+then 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.png" title="Screenshot">
@@ -184,11 +167,9 @@ print scopifier ARGF.read
 ```
 
 When a `--version` argument is passed, a scopifier should print its version
-number and exit. This allows context-coloring to determine if an update is
+number and exit.  This allows context-coloring to determine if an update is
 required.
 
-[linter]: http://jshint.com/about/
-[flycheck]: http://www.flycheck.org/
 [js2-mode]: https://github.com/mooz/js2-mode
 [node]: http://nodejs.org/download/
 [scopifier]: https://github.com/jacksonrayhamilton/scopifier
diff --git a/packages/context-coloring/benchmark/context-coloring-benchmark.el 
b/packages/context-coloring/benchmark/context-coloring-benchmark.el
index 2de5646..e020f6f 100644
--- a/packages/context-coloring/benchmark/context-coloring-benchmark.el
+++ b/packages/context-coloring/benchmark/context-coloring-benchmark.el
@@ -1,4 +1,4 @@
-;;; benchmark/context-coloring-benchmark.el --- Benchmarks for context 
coloring. -*- lexical-binding: t; -*-
+;;; context-coloring-benchmark.el --- Benchmarks for context coloring  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2014-2015  Free Software Foundation, Inc.
 
@@ -19,12 +19,9 @@
 
 ;;; Commentary:
 
-;; Benchmarks for context-coloring.
+;; Benchmarks for context coloring.
 
-;; `ert' instruments and benchmarks the package's functions, and the results 
are
-;; logged to `benchmark/logs'.
-
-;; To run, execute `make bench' from the project root.
+;; Use with `make bench'.
 
 ;;; Code:
 
diff --git a/packages/context-coloring/context-coloring.el 
b/packages/context-coloring/context-coloring.el
index cd1b97a..d73773a 100644
--- a/packages/context-coloring/context-coloring.el
+++ b/packages/context-coloring/context-coloring.el
@@ -1,11 +1,11 @@
-;;; context-coloring.el --- Syntax highlighting, except not for syntax. -*- 
lexical-binding: t; -*-
+;;; context-coloring.el --- Highlight by scope  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 2014-2015  Free Software Foundation, Inc.
 
 ;; Author: Jackson Ray Hamilton <address@hidden>
-;; URL: https://github.com/jacksonrayhamilton/context-coloring
-;; Keywords: context coloring syntax highlighting
-;; Version: 6.2.0
+;; Version: 6.2.1
+;; Keywords: convenience faces tools
+;; Homepage: https://github.com/jacksonrayhamilton/context-coloring
 ;; Package-Requires: ((emacs "24") (js2-mode "20150126"))
 
 ;; This file is part of GNU Emacs.
@@ -25,29 +25,20 @@
 
 ;;; Commentary:
 
-;; Highlights code according to function context.
+;; Highlights code by scope.  Top-level scopes are one color, second-level
+;; scopes are another color, and so on.  Variables retain the color of the 
scope
+;; in which they are defined.  A variable defined in an outer scope referenced
+;; by an inner scope is colored the same as the outer scope.
 
-;; - 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 are declared.
+;; By default, comments and strings are still highlighted syntactically.
 
-;; Lexical scope information at-a-glance can assist a programmer in
-;; understanding 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.
-
-;; To use, add the following to your ~/.emacs:
+;; To use with js2-mode, add the following to your init file:
 
 ;; (require 'context-coloring)
 ;; (add-hook 'js2-mode-hook 'context-coloring-mode)
 
-;; js-mode or js3-mode support requires Node.js 0.10+ and the scopifier
-;; executable.
+;; To use with js-mode or js3-mode, install Node.js 0.10+ and the scopifier
+;; executable:
 
 ;; $ npm install -g scopifier
 
@@ -68,6 +59,22 @@
   "Join a list of STRINGS with the string DELIMITER."
   (mapconcat 'identity strings delimiter))
 
+(defsubst context-coloring-trim-right (string)
+  "Remove leading whitespace from STRING."
+  (if (string-match "[ \t\n\r]+\\'" string)
+      (replace-match "" t t string)
+    string))
+
+(defsubst context-coloring-trim-left (string)
+  "Remove trailing whitespace from STRING."
+  (if (string-match "\\`[ \t\n\r]+" string)
+      (replace-match "" t t string)
+    string))
+
+(defsubst context-coloring-trim (string)
+  "Remove leading and trailing whitespace from STRING."
+  (context-coloring-trim-left (context-coloring-trim-right string)))
+
 
 ;;; Faces
 
@@ -89,12 +96,12 @@ backgrounds."
   (context-coloring-defface level nil "#3f3f3f" "#cdcdcd"))
 
 (context-coloring-defface 0 nil       "#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 1 "yellow"  "#008b8b" "#00ffff")
+(context-coloring-defface 2 "green"   "#0000ff" "#87cefa")
+(context-coloring-defface 3 "cyan"    "#483d8b" "#b0c4de")
+(context-coloring-defface 4 "blue"    "#a020f0" "#eedd82")
+(context-coloring-defface 5 "magenta" "#a0522d" "#98fb98")
+(context-coloring-defface 6 "red"     "#228b22" "#7fffd4")
 (context-coloring-defface-neutral 7)
 
 (defvar context-coloring-maximum-face nil
@@ -237,12 +244,20 @@ variable."
                        ;; `js2-prop-get-node', so this always works.
                        (eq node (js2-prop-get-node-right parent))))))))
 
+(defvar-local context-coloring-point-max nil
+  "Cached value of `point-max'.")
+
 (defsubst context-coloring-js2-colorize-node (node level)
   "Color NODE with the color for LEVEL."
   (let ((start (js2-node-abs-pos node)))
     (context-coloring-colorize-region
      start
-     (+ start (js2-node-len node)) ; End
+     (min
+      ;; End
+      (+ start (js2-node-len node))
+      ;; Somes nodes (like the ast when there is an unterminated multiline
+      ;; comment) will stretch to the value of `point-max'.
+      context-coloring-point-max)
      level)))
 
 (defun context-coloring-js2-colorize ()
@@ -250,6 +265,7 @@ variable."
 generated by `js2-mode'."
   ;; Reset the hash table; the old one could be obsolete.
   (setq context-coloring-js2-scope-level-hash-table (make-hash-table :test 
'eq))
+  (setq context-coloring-point-max (point-max))
   (with-silent-modifications
     (js2-visit-ast
      js2-mode-ast
@@ -298,8 +314,13 @@ element."
 
 (defun context-coloring-parse-array (array)
   "Parse ARRAY as a flat JSON array of numbers."
-  (vconcat
-   (mapcar 'string-to-number (split-string (substring array 1 -1) ","))))
+  (let ((braceless (substring (context-coloring-trim array) 1 -1)))
+    (cond
+     ((> (length braceless) 0)
+      (vconcat
+       (mapcar 'string-to-number (split-string braceless ","))))
+     (t
+      (vector)))))
 
 (defvar-local context-coloring-scopifier-process nil
   "The single scopifier process that can be running.")
@@ -375,15 +396,6 @@ Invoke CALLBACK when complete."
 (defvar context-coloring-mode-hash-table (make-hash-table :test 'eq)
   "Map 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.
 
@@ -479,12 +491,18 @@ elisp tracks, and asynchronously for shell command 
tracks."
 
 ;;; Colorization
 
+(defvar context-coloring-colorize-hook nil
+  "Hooks to run after coloring a buffer.")
+
 (defun context-coloring-colorize (&optional callback)
   "Color the current buffer by function context.
 
 Invoke CALLBACK when complete; see `context-coloring-dispatch'."
   (interactive)
-  (context-coloring-dispatch callback))
+  (context-coloring-dispatch
+   (lambda ()
+     (when callback (funcall callback))
+     (run-hooks 'context-coloring-colorize-hook))))
 
 (defvar-local context-coloring-changed nil
   "Indication that the buffer has changed recently, which implies
@@ -648,7 +666,9 @@ which must already exist and which *should* already be 
enabled."
   (let* ((properties (gethash theme context-coloring-theme-hash-table))
          (colors (plist-get properties :colors))
          (level -1))
-    (setq context-coloring-maximum-face (- (length colors) 1))
+    ;; Only clobber when we have to.
+    (when (custom-theme-enabled-p theme)
+      (setq context-coloring-maximum-face (- (length colors) 1)))
     (apply
      'custom-theme-set-faces
      theme
@@ -746,7 +766,7 @@ precedence, i.e. the car of `custom-enabled-themes'."
   (when (and (not (eq theme 'user)) ; Called internally by `enable-theme'.
              (custom-theme-p theme) ; Guard against non-existent themes.
              (context-coloring-theme-p theme))
-    (when (= (length custom-enabled-themes) 0)
+    (when (= (length custom-enabled-themes) 1)
       ;; Cache because we can't reliably figure it out in reverse.
       (setq context-coloring-original-maximum-face
             context-coloring-maximum-face))
diff --git a/packages/context-coloring/scripts/dependencies 
b/packages/context-coloring/scripts/dependencies
deleted file mode 100644
index c2a9107..0000000
--- a/packages/context-coloring/scripts/dependencies
+++ /dev/null
@@ -1,2 +0,0 @@
-https://raw.githubusercontent.com/mooz/js2-mode/master/js2-mode.el
-https://raw.githubusercontent.com/rejeep/ert-async.el/master/ert-async.el
diff --git a/packages/context-coloring/scripts/download-dependencies.el 
b/packages/context-coloring/scripts/download-dependencies.el
deleted file mode 100644
index 2ab24e2..0000000
--- a/packages/context-coloring/scripts/download-dependencies.el
+++ /dev/null
@@ -1,61 +0,0 @@
-;;; scripts/download-dependencies.el --- Get files for development. -*- 
lexical-binding: t; -*-
-
-;; Copyright (C) 2014-2015  Free Software Foundation, Inc.
-
-;; This file is part of GNU Emacs.
-
-;; 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/>.
-
-;; Download dependencies for development.
-
-;; Dependencies don't need to be version-controlled. They are also
-;; bleeding-edge, which is good because that is what most MELPA users are 
using.
-
-;;; Code:
-
-(defconst download-dependencies-directory
-  (file-name-directory (or load-file-name buffer-file-name))
-  "This file's directory.")
-
-(defun download-dependencies-resolve-path (path)
-  "Resolve a path relative to this file's directory."
-  (expand-file-name path download-dependencies-directory))
-
-(defun download-dependencies-strip-headers ()
-  "Remove the http headers included in the output of
-`url-retrieve-synchronously'."
-  (goto-char 1)
-  (kill-paragraph 1) ; The headers are 1 paragraph.  I hope.
-  (kill-line))       ; A line separates the headers from the file's content.
-
-(defun download-dependencies-get-dependencies ()
-  "Read the `dependencies' file as a list of URLs."
-  (with-temp-buffer
-    (insert-file-contents (download-dependencies-resolve-path 
"./dependencies"))
-    (split-string (buffer-substring-no-properties (point-min) (point-max)))))
-
-(defun download-dependencies ()
-  "Download dependencies for development."
-  (let ((files (download-dependencies-get-dependencies)))
-    (make-directory (download-dependencies-resolve-path "../libraries") t)
-    (dolist (file files)
-      (let* ((basename (file-name-nondirectory file))
-             (destination (download-dependencies-resolve-path
-                           (concat "../libraries/" basename))))
-        (unless (file-exists-p destination)
-          (with-current-buffer (url-retrieve-synchronously file)
-            (download-dependencies-strip-headers)
-            (write-file destination)))))))
-
-;;; download-dependencies.el ends here
diff --git a/packages/context-coloring/test/binaries/noop 
b/packages/context-coloring/test/binaries/noop
new file mode 100644
index 0000000..a35b551
--- /dev/null
+++ b/packages/context-coloring/test/binaries/noop
@@ -0,0 +1,5 @@
+#!/usr/bin/env node
+
+'use strict';
+
+console.log(JSON.stringify([]));
diff --git a/packages/context-coloring/test/context-coloring-coverage.el 
b/packages/context-coloring/test/context-coloring-coverage.el
new file mode 100644
index 0000000..2fe8fa9
--- /dev/null
+++ b/packages/context-coloring/test/context-coloring-coverage.el
@@ -0,0 +1,154 @@
+;;; context-coloring-coverage.el --- Test coverage for context coloring  -*- 
lexical-binding: t; -*-
+
+;; Copyright (C) 2014-2015  Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; 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/>.
+
+;;; Commentary:
+
+;; Test coverage support for context coloring.
+
+;; Use with `make cover'.
+
+;;; Code:
+
+(require 'json)
+(require 'undercover)
+
+
+(defconst context-coloring-coverage-directory
+  (file-name-directory (or load-file-name buffer-file-name))
+  "This file's directory.")
+
+(defun context-coloring-coverage-resolve-path (path)
+  "Resolve PATH from this file's directory."
+  (expand-file-name path context-coloring-coverage-directory))
+
+(defconst context-coloring-coverage-output-file-prefix
+  (format-time-string "%s"))
+
+(defconst context-coloring-coverage-output-directory
+  (context-coloring-coverage-resolve-path "./coverage/"))
+
+(defconst context-coloring-coverage-output-file
+  (concat context-coloring-coverage-output-directory
+          context-coloring-coverage-output-file-prefix ".json"))
+
+(defconst context-coloring-coverage-report-file
+  (concat context-coloring-coverage-output-directory
+          context-coloring-coverage-output-file-prefix ".txt"))
+
+(defun context-coloring-coverage-join (strings delimiter)
+  "Join a list of STRINGS with the string DELIMITER."
+  (mapconcat 'identity strings delimiter))
+
+(defun context-coloring-coverage-percentage (dividend divisor)
+  "Get the percentage of DIVIDEND / DIVISOR with precision 2."
+  (let ((percentage (/ (float (round (* (/ (float dividend) divisor) 10000))) 
100)))
+    (number-to-string
+     (cond
+      ((= (mod percentage 1) 0)
+       ;; Get an integer because we don't like dangling zeros.
+       (round percentage))
+      (t
+       percentage)))))
+
+(defun context-coloring-coverage-format-source-file (source-file)
+  "Generate a report for SOURCE-FILE's line coverage."
+  (let* ((source-lines (split-string (cdr (assq 'source source-file)) "\n"))
+         (coverage (cdr (assq 'coverage source-file)))
+         (results (list "Hits  | Source"
+                        (context-coloring-coverage-join (make-vector 80 "-") 
"")))
+         (lines-hit 0)
+         (lines-hittable 0)
+         hits
+         source-line)
+    (while coverage
+      (setq hits (car coverage))
+      (setq coverage (cdr coverage))
+      (setq source-line (car source-lines))
+      (setq source-lines (cdr source-lines))
+      (when (not (null hits))
+        (setq lines-hittable (+ lines-hittable 1))
+        (when (> hits 0)
+          (setq lines-hit (+ lines-hit 1))))
+      (setq results
+            (append results
+                    (list (format
+                           "%-5s %s %s"
+                           (if hits hits "N/A")
+                           (if (and hits (= hits 0)) "~" "|")
+                           source-line)))))
+    (setq results
+          (append results
+                  (list
+                   ""
+                   (format
+                    "Lines: %s / %s"
+                    lines-hit
+                    lines-hittable)
+                   (format
+                    "Coverage: %s%%"
+                    (context-coloring-coverage-percentage lines-hit 
lines-hittable)))))
+    (context-coloring-coverage-join results "\n")))
+
+(defun context-coloring-coverage-format (coverage-data)
+  "Generate reports for all files in COVERAGE-DATA."
+  (context-coloring-coverage-join
+   (mapcar
+    'context-coloring-coverage-format-source-file
+    (cdr (assq 'source_files coverage-data)))
+   "\n"))
+
+(defun context-coloring-coverage-local-init ()
+  "Initialize test coverage for local viewing."
+  (make-directory context-coloring-coverage-output-directory t)
+  (setq undercover-force-coverage t)
+  (setenv "COVERALLS_REPO_TOKEN" "noop")
+  (undercover "context-coloring.el"
+              (:report-file context-coloring-coverage-output-file))
+  (add-hook
+   'kill-emacs-hook
+   (lambda ()
+     (let (original-json-array-type
+           coverage-data
+           report)
+       (with-temp-buffer
+         (insert-file-contents-literally context-coloring-coverage-output-file)
+         (setq original-json-array-type json-array-type)
+         (setq json-array-type 'list)
+         (setq coverage-data
+               (json-read-from-string
+                (buffer-substring-no-properties (point-min) (point-max))))
+         (setq json-array-type original-json-array-type)
+         (setq report
+               (context-coloring-coverage-format coverage-data))
+         (setq report (concat report "\n")))
+       (princ report)
+       (with-temp-buffer
+         (insert report)
+         (write-file context-coloring-coverage-report-file))))
+   t)
+  (require 'context-coloring))
+
+(defun context-coloring-coverage-ci-init ()
+  "Initialize test coverage for continuous integration."
+  (undercover "context-coloring.el")
+  (require 'context-coloring))
+
+(provide 'context-coloring-coverage)
+
+;; context-coloring-coverage.el ends here
diff --git a/packages/context-coloring/test/context-coloring-test.el 
b/packages/context-coloring/test/context-coloring-test.el
index cbd2002..b9a43d9 100644
--- a/packages/context-coloring/test/context-coloring-test.el
+++ b/packages/context-coloring/test/context-coloring-test.el
@@ -1,4 +1,4 @@
-;;; test/context-coloring-test.el --- Tests for context coloring. -*- 
lexical-binding: t; -*-
+;;; context-coloring-test.el --- Tests for context coloring  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2014-2015  Free Software Foundation, Inc.
 
@@ -19,12 +19,9 @@
 
 ;;; Commentary:
 
-;; Tests for context-coloring.
+;; Tests for context coloring.
 
-;; Tests for both synchronous (elisp) and asynchronous (shell command) coloring
-;; are available.  Basic plugin functionality is also tested.
-
-;; To run, execute `make test' from the project root.
+;; Use with `make test'.
 
 ;;; Code:
 
@@ -55,7 +52,11 @@
   (setq context-coloring-syntactic-comments nil)
   (setq context-coloring-syntactic-strings nil)
   (setq context-coloring-js-block-scopes nil)
-  (setq context-coloring-check-scopifier-version-hook nil))
+  (setq context-coloring-colorize-hook nil)
+  (setq context-coloring-check-scopifier-version-hook nil)
+  (setq context-coloring-maximum-face 7)
+  (setq context-coloring-original-maximum-face
+        context-coloring-maximum-face))
 
 (defmacro context-coloring-test-with-fixture (fixture &rest body)
   "With the relative FIXTURE, evaluate BODY in a temporary
@@ -300,18 +301,153 @@ FOREGROUND.  Apply ARGUMENTS to
   (apply 'context-coloring-test-assert-face
          (append arguments '(t))))
 
+(defun context-coloring-test-assert-error (body error-message)
+  "Assert that BODY signals ERROR-MESSAGE."
+  (let ((error-signaled-p nil))
+    (condition-case err
+        (progn
+          (funcall body))
+      (error
+       (setq error-signaled-p t)
+       (when (not (string-equal (cadr err) error-message))
+         (ert-fail (format (concat "Expected the error \"%s\" to be thrown, "
+                                   "but instead it was \"%s\".")
+                           error-message
+                           (cadr err))))))
+    (when (not error-signaled-p)
+      (ert-fail "Expected an error to be thrown, but there wasn't."))))
+
+(defun context-coloring-test-assert-trimmed (result expected)
+  (when (not (string-equal result expected))
+    (ert-fail "Expected string to be trimmed, but it wasn't.")))
+
 
 ;;; The tests
 
+(ert-deftest context-coloring-test-trim ()
+  (context-coloring-test-assert-trimmed (context-coloring-trim "") "")
+  (context-coloring-test-assert-trimmed (context-coloring-trim " ") "")
+  (context-coloring-test-assert-trimmed (context-coloring-trim "a") "a")
+  (context-coloring-test-assert-trimmed (context-coloring-trim " a") "a")
+  (context-coloring-test-assert-trimmed (context-coloring-trim "a ") "a")
+  (context-coloring-test-assert-trimmed (context-coloring-trim " a ") "a"))
+
+(ert-deftest-async context-coloring-test-async-mode-startup (done)
+  (context-coloring-test-with-fixture-async
+   "./fixtures/empty"
+   (lambda (teardown)
+     (js-mode)
+     (add-hook
+      'context-coloring-colorize-hook
+      (lambda ()
+        ;; If this runs we are implicitly successful; this test only confirms
+        ;; that colorization occurs on mode startup.
+        (funcall teardown)
+        (funcall done)))
+     (context-coloring-mode))))
+
+(define-derived-mode
+  context-coloring-change-detection-mode
+  fundamental-mode
+  "Testing"
+  "Prevent `context-coloring-test-change-detection' from
+  having any unintentional side-effects on mode support.")
+
+;; Simply cannot figure out how to trigger an idle timer; would much rather 
test
+;; that.  But (current-idle-time) always returns nil in these tests.
+(ert-deftest-async context-coloring-test-change-detection (done)
+  (context-coloring-define-dispatch
+     'idle-change
+     :modes '(context-coloring-change-detection-mode)
+     :executable "node"
+     :command "node test/binaries/noop")
+  (context-coloring-test-with-fixture-async
+   "./fixtures/empty"
+   (lambda (teardown)
+     (context-coloring-change-detection-mode)
+     (add-hook
+      'context-coloring-colorize-hook
+      (lambda ()
+        (setq context-coloring-colorize-hook nil)
+        (add-hook
+         'context-coloring-colorize-hook
+         (lambda ()
+           (funcall teardown)
+           (funcall done)))
+        (insert " ")
+        (set-window-buffer (selected-window) (current-buffer))
+        (context-coloring-maybe-colorize)))
+     (context-coloring-mode))))
+
+(ert-deftest context-coloring-test-check-version ()
+  (when (not (context-coloring-check-version "2.1.3" "3.0.1"))
+    (ert-fail "Expected version 3.0.1 to satisfy 2.1.3, but it didn't."))
+  (when (context-coloring-check-version "3.0.1" "2.1.3")
+    (ert-fail "Expected version 2.1.3 not to satisfy 3.0.1, but it did.")))
+
 (ert-deftest context-coloring-test-unsupported-mode ()
   (context-coloring-test-with-fixture
-   "./fixtures/function-scopes.js"
+   "./fixtures/empty"
    (context-coloring-mode)
    (context-coloring-test-assert-message
     "Context coloring is not available for this major mode"
     "*Messages*")))
 
 (define-derived-mode
+  context-coloring-test-define-dispatch-error-mode
+  fundamental-mode
+  "Testing"
+  "Prevent `context-coloring-test-define-dispatch-error' from
+  having any unintentional side-effects on mode support.")
+
+(ert-deftest context-coloring-test-define-dispatch-error ()
+  (context-coloring-test-assert-error
+   (lambda ()
+     (context-coloring-define-dispatch
+      'define-dispatch-no-modes))
+   "No mode defined for dispatch")
+  (context-coloring-test-assert-error
+   (lambda ()
+     (context-coloring-define-dispatch
+      'define-dispatch-no-strategy
+      :modes '(context-coloring-test-define-dispatch-error-mode)))
+   "No colorizer, scopifier or command defined for dispatch"))
+
+(define-derived-mode
+  context-coloring-test-define-dispatch-scopifier-mode
+  fundamental-mode
+  "Testing"
+  "Prevent `context-coloring-test-define-dispatch-scopifier' from
+  having any unintentional side-effects on mode support.")
+
+(ert-deftest context-coloring-test-define-dispatch-scopifier ()
+  (context-coloring-define-dispatch
+   'define-dispatch-scopifier
+   :modes '(context-coloring-test-define-dispatch-scopifier-mode)
+   :scopifier (lambda () (vector)))
+  (with-temp-buffer
+    (context-coloring-test-define-dispatch-scopifier-mode)
+    (context-coloring-mode)
+    (context-coloring-colorize)))
+
+(define-derived-mode
+  context-coloring-test-missing-executable-mode
+  fundamental-mode
+  "Testing"
+  "Prevent `context-coloring-test-define-dispatch-scopifier' from
+  having any unintentional side-effects on mode support.")
+
+(ert-deftest context-coloring-test-missing-executable ()
+  (context-coloring-define-dispatch
+   'scopifier
+   :modes '(context-coloring-test-missing-executable-mode)
+   :command ""
+   :executable "__should_not_exist__")
+  (with-temp-buffer
+    (context-coloring-test-missing-executable-mode)
+    (context-coloring-mode)))
+
+(define-derived-mode
   context-coloring-test-unsupported-version-mode
   fundamental-mode
   "Testing"
@@ -326,7 +462,7 @@ FOREGROUND.  Apply ARGUMENTS to
    :command "node test/binaries/outta-date"
    :version "v2.1.3")
   (context-coloring-test-with-fixture-async
-   "./fixtures/function-scopes.js"
+   "./fixtures/empty"
    (lambda (teardown)
      (context-coloring-test-unsupported-version-mode)
      (add-hook
@@ -343,6 +479,35 @@ FOREGROUND.  Apply ARGUMENTS to
         (funcall done)))
      (context-coloring-mode))))
 
+(define-derived-mode
+  context-coloring-test-disable-mode-mode
+  fundamental-mode
+  "Testing"
+  "Prevent `context-coloring-test-disable-mode' from having any
+  unintentional side-effects on mode support.")
+
+(ert-deftest-async context-coloring-test-disable-mode (done)
+  (let (torn-down)
+    (context-coloring-define-dispatch
+     'disable-mode
+     :modes '(context-coloring-test-disable-mode-mode)
+     :executable "node"
+     :command "node test/binaries/noop"
+     :teardown (lambda ()
+                 (setq torn-down t)))
+    (context-coloring-test-with-fixture-async
+     "./fixtures/empty"
+     (lambda (teardown)
+       (unwind-protect
+           (progn
+             (context-coloring-test-disable-mode-mode)
+             (context-coloring-mode)
+             (context-coloring-mode -1)
+             (when (not torn-down)
+               (ert-fail "Expected teardown function to have been called, but 
it wasn't.")))
+         (funcall teardown))
+       (funcall done)))))
+
 (defvar context-coloring-test-theme-index 0
   "Unique index for unique theme names.")
 
@@ -450,12 +615,14 @@ test completes."
                        (format "context-coloring-test-define-theme-%s" name))))
     `(ert-deftest ,deftest-name ()
        (context-coloring-test-kill-buffer "*Warnings*")
+       (context-coloring-test-setup)
        (let ((theme (context-coloring-test-get-next-theme)))
          (unwind-protect
              (progn
                ,@body)
            ;; Always cleanup.
-           (disable-theme theme))))))
+           (disable-theme theme)
+           (context-coloring-test-cleanup))))))
 
 (defun context-coloring-test-deftheme (theme)
   "Dynamically define theme THEME."
@@ -532,6 +699,18 @@ theme THEME is signaled."
   (context-coloring-test-assert-face 0 "#cccccc")
   (context-coloring-test-assert-face 1 "#dddddd"))
 
+(context-coloring-test-deftest-define-theme pre-recede-delayed-application
+  (context-coloring-define-theme
+   theme
+   :recede t
+   :colors '("#aaaaaa"
+             "#bbbbbb"))
+  (context-coloring-test-deftheme theme)
+  (enable-theme theme)
+  (context-coloring-test-assert-no-message "*Warnings*")
+  (context-coloring-test-assert-face 0 "#aaaaaa")
+  (context-coloring-test-assert-face 1 "#bbbbbb"))
+
 (context-coloring-test-deftest-define-theme post-recede
   (context-coloring-test-deftheme theme)
   (custom-theme-set-faces
@@ -621,42 +800,45 @@ see that function."
          (append arguments '(t))))
 
 (context-coloring-test-deftest-define-theme disable-cascade
-  (context-coloring-test-deftheme theme)
-  (context-coloring-define-theme
-   theme
-   :colors '("#aaaaaa"
-             "#bbbbbb"))
-  (let ((second-theme (context-coloring-test-get-next-theme)))
-    (context-coloring-test-deftheme second-theme)
+  (let ((maximum-face-value 9999))
+    (setq context-coloring-maximum-face maximum-face-value)
+    (context-coloring-test-deftheme theme)
     (context-coloring-define-theme
-     second-theme
-     :colors '("#cccccc"
-               "#dddddd"
-               "#eeeeee"))
-    (let ((third-theme (context-coloring-test-get-next-theme)))
-      (context-coloring-test-deftheme third-theme)
+     theme
+     :colors '("#aaaaaa"
+               "#bbbbbb"))
+    (let ((second-theme (context-coloring-test-get-next-theme)))
+      (context-coloring-test-deftheme second-theme)
       (context-coloring-define-theme
-       third-theme
-       :colors '("#111111"
-                 "#222222"
-                 "#333333"
-                 "#444444"))
-      (enable-theme theme)
-      (enable-theme second-theme)
-      (enable-theme third-theme)
-      (disable-theme third-theme)
-      (context-coloring-test-assert-face 0 "#cccccc")
-      (context-coloring-test-assert-face 1 "#dddddd")
-      (context-coloring-test-assert-face 2 "#eeeeee")
-      (context-coloring-test-assert-maximum-face 2))
-    (disable-theme second-theme)
-    (context-coloring-test-assert-face 0 "#aaaaaa")
-    (context-coloring-test-assert-face 1 "#bbbbbb")
-    (context-coloring-test-assert-maximum-face 1))
-  (disable-theme theme)
-  (context-coloring-test-assert-not-face 0 "#aaaaaa")
-  (context-coloring-test-assert-not-face 1 "#bbbbbb")
-  (context-coloring-test-assert-not-maximum-face 1))
+       second-theme
+       :colors '("#cccccc"
+                 "#dddddd"
+                 "#eeeeee"))
+      (let ((third-theme (context-coloring-test-get-next-theme)))
+        (context-coloring-test-deftheme third-theme)
+        (context-coloring-define-theme
+         third-theme
+         :colors '("#111111"
+                   "#222222"
+                   "#333333"
+                   "#444444"))
+        (enable-theme theme)
+        (enable-theme second-theme)
+        (enable-theme third-theme)
+        (disable-theme third-theme)
+        (context-coloring-test-assert-face 0 "#cccccc")
+        (context-coloring-test-assert-face 1 "#dddddd")
+        (context-coloring-test-assert-face 2 "#eeeeee")
+        (context-coloring-test-assert-maximum-face 2))
+      (disable-theme second-theme)
+      (context-coloring-test-assert-face 0 "#aaaaaa")
+      (context-coloring-test-assert-face 1 "#bbbbbb")
+      (context-coloring-test-assert-maximum-face 1))
+    (disable-theme theme)
+    (context-coloring-test-assert-not-face 0 "#aaaaaa")
+    (context-coloring-test-assert-not-face 1 "#bbbbbb")
+    (context-coloring-test-assert-maximum-face
+     maximum-face-value)))
 
 (defun context-coloring-test-js-function-scopes ()
   "Test fixtures/functions-scopes.js."
@@ -800,6 +982,12 @@ see that function."
 (context-coloring-test-deftest-js2-mode syntactic-strings
   :fixture-name comments-and-strings)
 
+;; As long as `add-text-properties' doesn't signal an error, this test passes.
+(defun context-coloring-test-js-unterminated-comment ()
+  "Test unterminated multiline comments.")
+
+(context-coloring-test-deftest-js2-mode unterminated-comment)
+
 (provide 'context-coloring-test)
 
 ;;; context-coloring-test.el ends here
diff --git a/packages/context-coloring/test/fixtures/empty 
b/packages/context-coloring/test/fixtures/empty
new file mode 100644
index 0000000..e69de29
diff --git a/packages/context-coloring/test/fixtures/unterminated-comment.js 
b/packages/context-coloring/test/fixtures/unterminated-comment.js
new file mode 100644
index 0000000..94d4703
--- /dev/null
+++ b/packages/context-coloring/test/fixtures/unterminated-comment.js
@@ -0,0 +1,6 @@
+function a() {
+    /*
+    function b() {
+
+    }
+}



reply via email to

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