+;;; Change detection
+
+(defvar-local context-coloring-changed-p nil
+ "Indication that the buffer has changed recently, which implies
+that it should be colored again by
+`context-coloring-colorize-idle-timer' if that timer is being
+used.")
+
+(defvar-local context-coloring-changed-start nil
+ "Beginning of last text that changed.")
+
+(defvar-local context-coloring-changed-end nil
+ "End of last text that changed.")
+
+(defvar-local context-coloring-changed-length nil
+ "Length of last text that changed.")
+
+(defun context-coloring-change-function (start end length)
+ "Register a change so that a buffer can be colorized soon."
+ ;; Tokenization is obsolete if there was a change.
+ (context-coloring-cancel-scopification)
+ (setq context-coloring-changed-start start)
+ (setq context-coloring-changed-end end)
+ (setq context-coloring-changed-length length)
+ (setq context-coloring-changed-p t))
+
+(defun context-coloring-maybe-colorize (buffer)
+ "Colorize the current buffer if it has changed."
+ (when (and (eq buffer (current-buffer))
+ context-coloring-changed-p)
+ (context-coloring-colorize)
+ (setq context-coloring-changed-p nil)
+ (setq context-coloring-changed-start nil)
+ (setq context-coloring-changed-end nil)
+ (setq context-coloring-changed-length nil)))
+
+(defvar-local context-coloring-colorize-idle-timer nil
+ "The currently-running idle timer.")
+
+(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.
+
+Supported modes: `js-mode', `js3-mode', `emacs-lisp-mode'"
+ :group 'context-coloring)
+
+(defun context-coloring-setup-idle-change-detection ()
+ "Setup idle change detection."
+ (add-hook
+ 'after-change-functions 'context-coloring-change-function nil t)
+ (add-hook
+ 'kill-buffer-hook 'context-coloring-teardown-idle-change-detection nil t)
+ (setq context-coloring-colorize-idle-timer
+ (run-with-idle-timer
+ context-coloring-delay
+ t
+ 'context-coloring-maybe-colorize
+ (current-buffer))))
+
+(defun context-coloring-teardown-idle-change-detection ()
+ "Teardown idle change detection."
+ (context-coloring-cancel-scopification)
+ (when context-coloring-colorize-idle-timer
+ (cancel-timer context-coloring-colorize-idle-timer))
+ (remove-hook
+ 'kill-buffer-hook 'context-coloring-teardown-idle-change-detection t)
+ (remove-hook
+ 'after-change-functions 'context-coloring-change-function t))
+
+