-;;; 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 <jackson@jacksonrayhamilton.com>
-;; 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.
;;; 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
"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
(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
;; `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 ()
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
(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.")
(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.
;;; 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
(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
(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))