;; Copyright (C) 2014-2015 Free Software Foundation, Inc.
;; Author: Jackson Ray Hamilton <jackson@jacksonrayhamilton.com>
-;; Version: 6.5.0
+;; Version: 7.2.0
;; Keywords: convenience faces tools
-;; Package-Requires: ((emacs "24.3") (js2-mode "20150126"))
+;; Package-Requires: ((emacs "24.3") (js2-mode "20150713"))
;; URL: https://github.com/jacksonrayhamilton/context-coloring
;; This file is part of GNU Emacs.
;;; Faces
-;; Create placeholder faces for users to populate.
-(dotimes (level 25)
+(defun context-coloring-defface (level light dark tty)
+ "Define a face for LEVEL with LIGHT, DARK and TTY colors."
(let ((face (intern (format "context-coloring-level-%s-face" level)))
(doc (format "Context coloring face, level %s." level)))
+ (custom-declare-face
+ face
+ `((((type tty)) (:foreground ,tty))
+ (((background light)) (:foreground ,light))
+ (((background dark)) (:foreground ,dark)))
+ doc
+ :group 'context-coloring)))
+
+;; Provide some default colors based off Emacs's defaults.
+(context-coloring-defface 0 "#000000" "#ffffff" nil)
+(context-coloring-defface 1 "#008b8b" "#00ffff" "yellow")
+(context-coloring-defface 2 "#0000ff" "#87cefa" "green")
+(context-coloring-defface 3 "#483d8b" "#b0c4de" "cyan")
+(context-coloring-defface 4 "#a020f0" "#eedd82" "blue")
+(context-coloring-defface 5 "#a0522d" "#98fb98" "magenta")
+(context-coloring-defface 6 "#228b22" "#7fffd4" "red")
+(context-coloring-defface 7 "#3f3f3f" "#cdcdcd" nil)
+
+(defconst context-coloring-default-maximum-face 7
+ "Maximum face when there are no custom faces.")
+
+;; Create placeholder faces for users and theme authors.
+(dotimes (level 18)
+ (let* ((level (+ level 8))
+ (face (intern (format "context-coloring-level-%s-face" level)))
+ (doc (format "Context coloring face, level %s." level)))
(custom-declare-face face nil doc :group 'context-coloring)))
-(defvar context-coloring-maximum-face 24
- "Index of the highest face available for coloring.")
+(defvar-local context-coloring-maximum-face nil
+ "Dynamic index of the highest face available for coloring.")
(defsubst context-coloring-level-face (level)
- "Return the symbol for a face with LEVEL."
+ "Return symbol for face with LEVEL."
;; `concat' is faster than `format' here.
(intern-soft
(concat "context-coloring-level-" (number-to-string level) "-face")))
(defsubst context-coloring-bounded-level-face (level)
- "Return the symbol for a face with LEVEL, bounded by
-`context-coloring-maximum-face'."
+ "Return symbol for face with LEVEL, bounded by the maximum."
(context-coloring-level-face (min level context-coloring-maximum-face)))
+(defconst context-coloring-level-face-regexp
+ "context-coloring-level-\\([[:digit:]]+\\)-face"
+ "Extract a level from a face.")
+
+(defun context-coloring-theme-highest-level (theme)
+ "Return the highest coloring level for THEME, or -1."
+ (let* ((settings (get theme 'theme-settings))
+ (tail settings)
+ face-string
+ number
+ (found -1))
+ (while tail
+ (and (eq (nth 0 (car tail)) 'theme-face)
+ (setq face-string (symbol-name (nth 1 (car tail))))
+ (string-match
+ context-coloring-level-face-regexp
+ face-string)
+ (setq number (string-to-number
+ (substring face-string
+ (match-beginning 1)
+ (match-end 1))))
+ (> number found)
+ (setq found number))
+ (setq tail (cdr tail)))
+ found))
+
+(defun context-coloring-update-maximum-face ()
+ "Save the highest possible face for the current theme."
+ (let ((themes (append custom-enabled-themes '(user)))
+ (continue t)
+ theme
+ highest-level)
+ (while continue
+ (setq theme (car themes))
+ (setq themes (cdr themes))
+ (setq highest-level (context-coloring-theme-highest-level theme))
+ (setq continue (and themes (= highest-level -1))))
+ (setq context-coloring-maximum-face
+ (cond
+ ((= highest-level -1)
+ context-coloring-default-maximum-face)
+ (t
+ highest-level)))))
+
;;; Change detection
Increase this if your machine is high-performing. Decrease it if
it ain't."
+ :type 'float
:group 'context-coloring)
(make-obsolete-variable
;;; Colorization utilities
(defsubst context-coloring-colorize-region (start end level)
- "Color characters from the 1-indexed START point (inclusive) to
-the END point (exclusive) with the face corresponding to LEVEL."
+ "Color from START (inclusive) to END (exclusive) with LEVEL."
(add-text-properties
start
end
(defcustom context-coloring-syntactic-comments t
"If non-nil, also color comments using `font-lock'."
+ :type 'boolean
:group 'context-coloring)
(defcustom context-coloring-syntactic-strings t
"If non-nil, also color strings using `font-lock'."
+ :type 'boolean
:group 'context-coloring)
(defun context-coloring-font-lock-syntactic-comment-function (state)
- "Tell `font-lock' to color a comment but not a string according
-to STATE."
+ "Color a comment according to STATE."
(if (nth 3 state) nil font-lock-comment-face))
(defun context-coloring-font-lock-syntactic-string-function (state)
- "Tell `font-lock' to color a string but not a comment according
-to STATE."
+ "Color a string according to STATE."
(if (nth 3 state) font-lock-string-face nil))
(defsubst context-coloring-colorize-comments-and-strings (&optional min max)
- "Color the current buffer's comments or strings if
-`context-coloring-syntactic-comments' or
-`context-coloring-syntactic-strings' are non-nil. MIN defaults
-to the beginning of the buffer and MAX defaults to the end."
+ "Maybe color comments and strings in buffer from MIN to MAX.
+MIN defaults to beginning of buffer. MAX defaults to end."
(when (or context-coloring-syntactic-comments
context-coloring-syntactic-strings)
(let ((min (or min (point-min)))
(when (eq major-mode 'emacs-lisp-mode)
(font-lock-fontify-keywords-region min max))))))
+(defcustom context-coloring-initial-level 0
+ "Scope level at which to start coloring.
+
+If top-level variables and functions do not become global, but
+are scoped to a file (as in Node.js), set this to `1'."
+ :type 'integer
+ :safe #'integerp
+ :group 'context-coloring)
-;;; js2-mode colorization
+
+;;; JavaScript colorization
(defvar-local context-coloring-js2-scope-level-hash-table nil
"Associate `js2-scope' structures and with their scope
The block-scoped `let' and `const' are introduced in ES6. Enable
this for ES6 code; disable it elsewhere."
+ :type 'boolean
+ :safe #'booleanp
:group 'context-coloring)
(make-obsolete-variable
'context-coloring-javascript-block-scopes
"7.0.0")
-(defsubst context-coloring-js2-scope-level (scope)
- "Return the level of SCOPE."
+(defsubst context-coloring-js2-scope-level (scope initial)
+ "Return the level of SCOPE, starting from INITIAL."
(cond ((gethash scope context-coloring-js2-scope-level-hash-table))
(t
- (let ((level 0)
+ (let ((level initial)
(current-scope scope)
enclosing-scope)
(while (and current-scope
(puthash scope level context-coloring-js2-scope-level-hash-table)))))
(defsubst context-coloring-js2-local-name-node-p (node)
- "Determine if NODE is a `js2-name-node' representing a local
-variable."
+ "Determine if NODE represents a local variable."
(and (js2-name-node-p node)
(let ((parent (js2-node-parent node)))
(not (or (and (js2-object-prop-node-p parent)
context-coloring-point-max)
level)))
-(defun context-coloring-js2-colorize ()
- "Color the current buffer using the abstract syntax tree
-generated by `js2-mode'."
+(defun context-coloring-js2-colorize-ast ()
+ "Color the buffer using the `js2-mode' abstract syntax tree."
;; 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))
((js2-scope-p node)
(context-coloring-js2-colorize-node
node
- (context-coloring-js2-scope-level node)))
+ (context-coloring-js2-scope-level node context-coloring-initial-level)))
((context-coloring-js2-local-name-node-p node)
(let* ((enclosing-scope (js2-node-get-enclosing-scope node))
(defining-scope (js2-get-defining-scope
(when (not (eq defining-scope enclosing-scope))
(context-coloring-js2-colorize-node
node
- (context-coloring-js2-scope-level defining-scope))))))
+ ;; Use `0' as an initial level so global variables are always at
+ ;; the highest level (even if `context-coloring-initial-level'
+ ;; specifies an initial level for the rest of the code).
+ (context-coloring-js2-scope-level defining-scope 0))))))
;; The `t' indicates to search children.
t)))
(context-coloring-colorize-comments-and-strings)))
+(defconst context-coloring-node-comment-regexp
+ (concat
+ ;; Ensure the "//" or "/*" comment starts with the directive.
+ "\\(//[[:space:]]*\\|/\\*[[:space:]]*\\)"
+ ;; Support multiple directive formats.
+ "\\("
+ ;; JSLint and JSHint support a JSON-like format.
+ "\\(jslint\\|jshint\\)[[:space:]].*?node:[[:space:]]*true"
+ "\\|"
+ ;; ESLint just specifies the option name.
+ "eslint-env[[:space:]].*?node"
+ "\\)")
+ "Match a comment body hinting at a Node.js program.")
+
+;; TODO: Add ES6 module detection.
+(defun context-coloring-js2-top-level-local-p ()
+ "Guess whether top-level variables are local.
+For instance, the current file could be a Node.js program."
+ (or
+ ;; A shebang is a pretty obvious giveaway.
+ (string-equal
+ "node"
+ (save-excursion
+ (goto-char (point-min))
+ (when (looking-at auto-mode-interpreter-regexp)
+ (match-string 2))))
+ ;; Otherwise, perform static analysis.
+ (progn
+ (setq context-coloring-js2-scope-level-hash-table (make-hash-table :test #'eq))
+ (catch 'node-program-p
+ (js2-visit-ast
+ js2-mode-ast
+ (lambda (node end-p)
+ (when (null end-p)
+ (when
+ (cond
+ ;; Infer based on inline linter configuration.
+ ((js2-comment-node-p node)
+ (string-match-p
+ context-coloring-node-comment-regexp
+ (js2-node-string node)))
+ ;; Infer based on the prescence of certain variables.
+ ((and (js2-name-node-p node)
+ (let ((parent (js2-node-parent node)))
+ (not (and (js2-object-prop-node-p parent)
+ (eq node (js2-object-prop-node-left parent))))))
+ (let ((name (js2-name-node-name node))
+ (parent (js2-node-parent node)))
+ (and
+ (cond
+ ;; Check whether this is "exports.something" or
+ ;; "module.exports".
+ ((js2-prop-get-node-p parent)
+ (and
+ (eq node (js2-prop-get-node-left parent))
+ (or (string-equal name "exports")
+ (let* ((property (js2-prop-get-node-right parent))
+ (property-name (js2-name-node-name property)))
+ (and (string-equal name "module")
+ (string-equal property-name "exports"))))))
+ ;; Check whether it's a "require('module')" call.
+ ((js2-call-node-p parent)
+ (or (string-equal name "require"))))
+ (let* ((enclosing-scope (js2-node-get-enclosing-scope node))
+ (defining-scope (js2-get-defining-scope
+ enclosing-scope name)))
+ ;; The variable also must be global.
+ (null defining-scope))))))
+ (throw 'node-program-p t))
+ ;; The `t' indicates to search children.
+ t)))
+ ;; Default to returning nil from the catch body.
+ nil))))
+
+(defcustom context-coloring-javascript-detect-top-level-scope t
+ "If non-nil, detect when to use file-level scope."
+ :type 'boolean
+ :group 'context-coloring)
+
+(defun context-coloring-js2-colorize ()
+ "Color the buffer using the `js2-mode'."
+ (cond
+ ;; Increase the initial level if we should.
+ ((and context-coloring-javascript-detect-top-level-scope
+ (context-coloring-js2-top-level-local-p))
+ (let ((context-coloring-initial-level 1))
+ (context-coloring-js2-colorize-ast)))
+ (t
+ (context-coloring-js2-colorize-ast))))
+
;;; Emacs Lisp colorization
+(defconst context-coloring-WORD-CODE 2)
+(defconst context-coloring-SYMBOL-CODE 3)
+(defconst context-coloring-OPEN-PARENTHESIS-CODE 4)
+(defconst context-coloring-CLOSE-PARENTHESIS-CODE 5)
+(defconst context-coloring-EXPRESSION-PREFIX-CODE 6)
+(defconst context-coloring-STRING-QUOTE-CODE 7)
+(defconst context-coloring-ESCAPE-CODE 9)
+(defconst context-coloring-COMMENT-START-CODE 11)
+(defconst context-coloring-COMMENT-END-CODE 12)
+
+(defconst context-coloring-OCTOTHORPE-CHAR (string-to-char "#"))
+(defconst context-coloring-APOSTROPHE-CHAR (string-to-char "'"))
+(defconst context-coloring-OPEN-PARENTHESIS-CHAR (string-to-char "("))
+(defconst context-coloring-COMMA-CHAR (string-to-char ","))
+(defconst context-coloring-AT-CHAR (string-to-char "@"))
+(defconst context-coloring-BACKTICK-CHAR (string-to-char "`"))
+
+(defsubst context-coloring-get-syntax-code ()
+ "Get the syntax code at point."
+ (syntax-class
+ ;; Faster version of `syntax-after':
+ (aref (syntax-table) (char-after (point)))))
+
(defsubst context-coloring-forward-sws ()
"Move forward through whitespace and comments."
(while (forward-comment 1)))
(defsubst context-coloring-elisp-forward-sws ()
- "Move forward through whitespace and comments, colorizing
-comments along the way."
+ "Move through whitespace and comments, coloring comments."
(let ((start (point)))
(context-coloring-forward-sws)
(context-coloring-colorize-comments-and-strings start (point))))
(defsubst context-coloring-elisp-forward-sexp ()
- "Like `forward-sexp', but colorize comments and strings along
-the way."
+ "Skip/ignore missing sexps, coloring comments and strings."
(let ((start (point)))
- (forward-sexp)
+ (when (= (context-coloring-get-syntax-code)
+ context-coloring-EXPRESSION-PREFIX-CODE)
+ ;; `forward-sexp' does not skip an unfinished expression (e.g. when the
+ ;; name of a symbol or the parentheses of a list do not follow a single
+ ;; quote).
+ (forward-char))
+ (condition-case nil
+ (forward-sexp)
+ (scan-error (context-coloring-forward-sws)))
(context-coloring-elisp-colorize-comments-and-strings-in-region
start (point))))
-(defsubst context-coloring-get-syntax-code ()
- "Get the syntax code at point."
- (syntax-class
- ;; Faster version of `syntax-after':
- (aref (syntax-table) (char-after (point)))))
-
(defsubst context-coloring-exact-regexp (word)
"Create a regexp matching exactly WORD."
(concat "\\`" (regexp-quote word) "\\'"))
(context-coloring-exact-or-regexp
'("t" "nil" "." "?")))
"\\|")
- "Match words that might be considered symbols but can't be
-bound as variables.")
-
-(defconst context-coloring-WORD-CODE 2)
-(defconst context-coloring-SYMBOL-CODE 3)
-(defconst context-coloring-OPEN-PARENTHESIS-CODE 4)
-(defconst context-coloring-CLOSE-PARENTHESIS-CODE 5)
-(defconst context-coloring-EXPRESSION-PREFIX-CODE 6)
-(defconst context-coloring-STRING-QUOTE-CODE 7)
-(defconst context-coloring-ESCAPE-CODE 9)
-(defconst context-coloring-COMMENT-START-CODE 11)
-(defconst context-coloring-COMMENT-END-CODE 12)
-
-(defconst context-coloring-OCTOTHORPE-CHAR (string-to-char "#"))
-(defconst context-coloring-APOSTROPHE-CHAR (string-to-char "'"))
-(defconst context-coloring-OPEN-PARENTHESIS-CHAR (string-to-char "("))
-(defconst context-coloring-COMMA-CHAR (string-to-char ","))
-(defconst context-coloring-AT-CHAR (string-to-char "@"))
-(defconst context-coloring-BACKTICK-CHAR (string-to-char "`"))
+ "Match symbols that can't be bound as variables.")
(defsubst context-coloring-elisp-identifier-p (syntax-code)
"Check if SYNTAX-CODE is an elisp identifier constituent."
"Current number of sexps leading up to the next pause.")
(defsubst context-coloring-elisp-increment-sexp-count ()
- "Maybe check if the current parse should be interrupted as a
-result of pending user input."
+ "Maybe check if the user interrupted the current parse."
(setq context-coloring-elisp-sexp-count
(1+ context-coloring-elisp-sexp-count))
(when (and (zerop (% context-coloring-elisp-sexp-count
(member variable (plist-get scope :variables)))
(defsubst context-coloring-elisp-get-variable-level (variable)
- "Search up the scope chain for the first instance of VARIABLE
-and return its level, or 0 (global) if it isn't found."
+ "Return the level of VARIABLE, or 0 if it isn't found."
(let* ((scope-stack context-coloring-elisp-scope-stack)
scope
level)
variable))
(defsubst context-coloring-elisp-parse-bindable (callback)
- "Parse the symbol at point, and if the symbol can be bound,
-invoke CALLBACK with it."
+ "Parse the symbol at point.
+If the symbol can be bound, invoke CALLBACK with it."
(let* ((arg-string (buffer-substring-no-properties
(point)
(progn (context-coloring-elisp-forward-sexp)
(funcall callback arg-string))))
(defun context-coloring-elisp-parse-let-varlist (type)
- "Parse the list of variable initializers at point. If TYPE is
-`let', all the variables are bound after all their initializers
-are parsed; if TYPE is `let*', each variable is bound immediately
-after its own initializer is parsed."
+ "Parse the list of variable initializers at point.
+If TYPE is `let', all the variables are bound after all their
+initializers are parsed; if TYPE is `let*', each variable is
+bound immediately after its own initializer is parsed."
(let ((varlist '())
syntax-code)
;; Enter.
(forward-char)
+ (context-coloring-elisp-forward-sws)
(while (/= (setq syntax-code (context-coloring-get-syntax-code))
context-coloring-CLOSE-PARENTHESIS-CODE)
(cond
(let (syntax-code)
;; Enter.
(forward-char)
+ (context-coloring-elisp-forward-sws)
(while (/= (setq syntax-code (context-coloring-get-syntax-code))
context-coloring-CLOSE-PARENTHESIS-CODE)
(cond
(context-coloring-elisp-forward-sws))
(defun context-coloring-elisp-colorize-scope (callback)
- "Color the whole scope at point with its one color. Handle a
-header in CALLBACK."
+ "Color the whole scope at point with its one color.
+Handle a header in CALLBACK."
(let ((start (point))
(end (progn (forward-sexp)
(point))))
(funcall callback)))
(defun context-coloring-elisp-colorize-defun-like (callback)
- "Color the defun-like function at point, parsing the header
-with CALLBACK."
+ "Color the defun-like function at point.
+Parse the header with CALLBACK."
(context-coloring-elisp-colorize-scope
(lambda ()
(when (context-coloring-elisp-identifier-p (context-coloring-get-syntax-code))
(let (syntax-code)
;; Enter.
(forward-char)
+ (context-coloring-elisp-forward-sws)
(while (/= (setq syntax-code (context-coloring-get-syntax-code))
context-coloring-CLOSE-PARENTHESIS-CODE)
(cond
(context-coloring-elisp-forward-sws))))))
(defun context-coloring-elisp-colorize-lambda-like (callback)
- "Color the lambda-like function at point, parsing the header
-with CALLBACK."
+ "Color the lambda-like function at point.
+Parsing the header with CALLBACK."
(context-coloring-elisp-colorize-scope
(lambda ()
(context-coloring-elisp-parse-header callback))))
(lambda ()
(context-coloring-elisp-parse-let-varlist 'let*))))
+(defun context-coloring-elisp-colorize-macroexp-let2 ()
+ "Color the `macroexp-let2' at point."
+ (let (syntax-code
+ variable)
+ (context-coloring-elisp-colorize-scope
+ (lambda ()
+ (and
+ (progn
+ (setq syntax-code (context-coloring-get-syntax-code))
+ (context-coloring-elisp-identifier-p syntax-code))
+ (progn
+ (context-coloring-elisp-colorize-sexp)
+ (context-coloring-elisp-forward-sws)
+ (setq syntax-code (context-coloring-get-syntax-code))
+ (context-coloring-elisp-identifier-p syntax-code))
+ (progn
+ (context-coloring-elisp-parse-bindable
+ (lambda (parsed-variable)
+ (setq variable parsed-variable)))
+ (context-coloring-elisp-forward-sws)
+ (when variable
+ (context-coloring-elisp-add-variable variable))))))))
+
(defun context-coloring-elisp-colorize-cond ()
"Color the `cond' at point."
(let (syntax-code)
(puthash callee #'context-coloring-elisp-colorize-condition-case table))
(dolist (callee '("dolist" "dotimes"))
(puthash callee #'context-coloring-elisp-colorize-dolist table))
- (puthash "let" #'context-coloring-elisp-colorize-let table)
+ (dolist (callee '("let" "gv-letplace"))
+ (puthash callee #'context-coloring-elisp-colorize-let table))
(puthash "let*" #'context-coloring-elisp-colorize-let* table)
+ (puthash "macroexp-let2" #'context-coloring-elisp-colorize-macroexp-let2 table)
(puthash "lambda" #'context-coloring-elisp-colorize-lambda table)
(puthash "cond" #'context-coloring-elisp-colorize-cond table)
(puthash "defadvice" #'context-coloring-elisp-colorize-defadvice table)
(forward-char))
(defun context-coloring-elisp-colorize-expression-prefix ()
- "Color the expression prefix and the following expression at
-point. It could be a quoted or backquoted expression."
+ "Color the expression prefix and expression at point.
+It could be a quoted or backquoted expression."
(context-coloring-elisp-increment-sexp-count)
(cond
((/= (char-after) context-coloring-BACKTICK-CHAR)
(scan-error (progn))))))
(defun context-coloring-elisp-colorize ()
- "Color the current buffer, parsing elisp to determine its
-scopes and variables."
+ "Color the current Emacs Lisp buffer."
(interactive)
(context-coloring-elisp-colorize-guard
(lambda ()
;;; eval-expression colorization
+(defun context-coloring-eval-expression-match ()
+ "Determine expression start in `eval-expression'."
+ (string-match "\\`Eval: " (buffer-string)))
+
(defun context-coloring-eval-expression-colorize ()
"Color the `eval-expression' minibuffer prompt as elisp."
(interactive)
(lambda ()
(context-coloring-elisp-colorize-region-initially
(progn
- (string-match "\\`Eval: " (buffer-string))
+ (context-coloring-eval-expression-match)
(1+ (match-end 0)))
(point-max)))))
;;; Dispatch
(defvar context-coloring-dispatch-hash-table (make-hash-table :test #'eq)
- "Map dispatch strategy names to their corresponding property
-lists, which contain details about the strategies.")
+ "Map dispatch strategy names to their property lists.")
(defvar context-coloring-mode-hash-table (make-hash-table :test #'eq)
"Map major mode names to dispatch property lists.")
properties)) context-coloring-dispatch-predicates))))
(defun context-coloring-dispatch ()
- "Determine the optimal track for scopification / coloring of
-the current buffer, then execute it."
+ "Determine how to color the current buffer, and color it."
(let* ((dispatch (context-coloring-get-current-dispatch))
(colorizer (plist-get dispatch :colorizer)))
(catch 'interrupted
(defun context-coloring-colorize ()
"Color the current buffer by function context."
(interactive)
+ (context-coloring-update-maximum-face)
(context-coloring-dispatch))
(defun context-coloring-colorize-with-buffer (buffer)
;; rely on this predicate instead.
(defun context-coloring-eval-expression-predicate ()
"Non-nil if the minibuffer is for `eval-expression'."
- (eq this-command 'eval-expression))
+ ;; Kinda better than checking `this-command', because `this-command' changes.
+ (context-coloring-eval-expression-match))
(context-coloring-define-dispatch
'eval-expression
:setup #'context-coloring-setup-idle-change-detection
:teardown #'context-coloring-teardown-idle-change-detection)
+(defvar context-coloring-ignore-unavailable-predicates
+ (list
+ #'minibufferp)
+ "Cases when \"unavailable\" messages are silenced.
+Necessary in editing states where coloring is only sometimes
+permissible.")
+
+(defun context-coloring-ignore-unavailable-message-p ()
+ "Determine if the unavailable message should be silenced."
+ (let ((predicates context-coloring-ignore-unavailable-predicates)
+ (ignore-p nil))
+ (while (and predicates
+ (not ignore-p))
+ (setq ignore-p (funcall (pop predicates))))
+ ignore-p))
+
;;; Minor mode
The entire buffer is colored initially. Changes to the buffer
trigger recoloring.
-Certain custom themes have predefined colors from their palettes
-to use for coloring. See `context-coloring-theme-hash-table' for
-the supported themes. If the currently-enabled custom theme is
-not among these, you can define colors for it with
-`context-coloring-define-theme', which see.
+Define your own colors by customizing faces like
+`context-coloring-level-N-face', where N is a number starting
+from 0. If no face is found on a custom theme nor the `user'
+theme, the defaults are used.
New language / major mode support can be added with
`context-coloring-define-dispatch', which see.
;; Colorize once initially.
(let ((context-coloring-parse-interruptable-p nil))
(context-coloring-colorize))))
- (t
- (message "Context coloring is not available for this major mode")))))
+ ((not (context-coloring-ignore-unavailable-message-p))
+ (message "Context coloring is unavailable here")))))
(t
(let ((dispatch (context-coloring-get-current-dispatch)))
(when dispatch