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

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

[elpa] master b8d75de 3/3: Merge branch 'master' of git.sv.gnu.org:/srv/


From: Alexey Veretennikov
Subject: [elpa] master b8d75de 3/3: Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs/elpa
Date: Wed, 17 Jun 2015 07:10:21 +0000

branch: master
commit b8d75de3664fa0a068ade1eb27e703850b4273d1
Merge: fd99dfe ac8f004
Author: Alexey Veretennikov <address@hidden>
Commit: Alexey Veretennikov <address@hidden>

    Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs/elpa
---
 packages/bug-hunter/bug-hunter.el                  |  236 +-
 packages/context-coloring/Makefile                 |    4 +
 packages/context-coloring/README.md                |   10 +-
 .../benchmark/context-coloring-benchmark.el        |  224 +-
 .../context-coloring/benchmark/fixtures/faces.el   | 2764 +++++++
 .../context-coloring/benchmark/fixtures/lisp.el    |  931 +++
 .../context-coloring/benchmark/fixtures/simple.el  | 7901 ++++++++++++++++++++
 .../context-coloring/benchmark/fixtures/subr.el    | 4801 ++++++++++++
 packages/context-coloring/context-coloring.el      | 1680 +++--
 .../test/context-coloring-coverage.el              |    9 +-
 .../context-coloring/test/context-coloring-test.el | 1797 +++---
 packages/context-coloring/test/fixtures/changed.el |    5 +
 packages/context-coloring/test/fixtures/cond.el    |    8 +
 .../test/fixtures/condition-case.el                |   10 +
 .../context-coloring/test/fixtures/defadvice.el    |    3 +
 packages/context-coloring/test/fixtures/defun.el   |    1 +
 packages/context-coloring/test/fixtures/dolist.el  |    3 +
 packages/context-coloring/test/fixtures/ignored.el |    2 +-
 packages/context-coloring/test/fixtures/let.el     |    3 +
 packages/context-coloring/test/fixtures/quote.el   |   13 +-
 packages/context-coloring/test/fixtures/sexp.el    |    4 +
 packages/context-coloring/test/fixtures/splice.el  |    2 +
 .../test/fixtures/unbalanced-parenthesis.el        |    2 +
 23 files changed, 18710 insertions(+), 1703 deletions(-)

diff --git a/packages/bug-hunter/bug-hunter.el 
b/packages/bug-hunter/bug-hunter.el
index 2d0fc50..0538ac6 100644
--- a/packages/bug-hunter/bug-hunter.el
+++ b/packages/bug-hunter/bug-hunter.el
@@ -4,7 +4,7 @@
 
 ;; Author: Artur Malabarba <address@hidden>
 ;; URL: http://github.com/Malabarba/elisp-bug-hunter
-;; Version: 0.2
+;; Version: 0.5
 ;; Keywords: lisp
 ;; Package-Requires: ((seq "1.3") (cl-lib "0.5"))
 
@@ -22,27 +22,46 @@
 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
-;;
-;; The Bug Hunter is an Emacs library that finds the source of an error or
-;; unexpected behavior inside an elisp configuration file (typically
-;; `init.el' or `.emacs').
+;; An Emacs library that finds the source of an error or unexpected
+;; behavior inside an elisp configuration file (typically `init.el' or
+;; `.emacs').
 ;;
 ;; Usage Examples
 ;; ==============
 ;;
+;; Automated error hunting
+;; ~~~~~~~~~~~~~~~~~~~~~~~
+;;
 ;;   If your Emacs init file signals an error during startup, but you don’t
 ;;   know why, simply issue
 ;;   ,----
-;;   | M-x bug-hunter-init-file RET RET
+;;   | M-x bug-hunter-init-file RET e
 ;;   `----
 ;;   and The Bug Hunter will find it for you. Note that your `init.el' (or
 ;;   `.emacs') must be idempotent for this to work.
 ;;
+;;
+;; Interactive hunt
+;; ~~~~~~~~~~~~~~~~
+;;
 ;;   If Emacs starts up without errors but something is not working as it
-;;   should, invoke the same command, but give it in an assertion.
-;;   Essentially, if you can write a snippet that detects the issue and
-;;   returns non-nil, just provide this snippet as the assertion and the
-;;   Bug Hunter will do a bisection search for you.
+;;   should, invoke the same command, but choose the interactive option:
+;;   ,----
+;;   | M-x bug-hunter-init-file RET i
+;;   `----
+;;   The Bug Hunter will start a separate Emacs frame several times, and
+;;   then it will ask you each time whether that frame presented the
+;;   problem you have. After doing this about 5--12 times, you’ll be given
+;;   the results.
+;;
+;;
+;; Assertion hunt
+;; ~~~~~~~~~~~~~~
+;;
+;;   The Bug Hunter can also find your issue based on an assertion.
+;;   Essentially, if you can write a code snippet that returns non-nil when
+;;   it detects the issue, just provide this snippet as the assertion and
+;;   the Bug Hunter will do the rest.
 ;;
 ;;   For example, let’s say there’s something in your init file that’s
 ;;   loading the `cl' library, and you don’t want that. You /know/ you’re
@@ -50,12 +69,12 @@
 ;;   package is responsible for this outrage?
 ;;
 ;;   ,----
-;;   | M-x bug-hunter-init-file RET (featurep 'cl) RET
+;;   | M-x bug-hunter-init-file RET a (featurep 'cl) RET
 ;;   `----
 ;;
 ;;   *That’s it!* You’ll be given a nice buffer reporting the results:
 ;;
-;;   - Are you getting obscure errors when trying to open /“.tex”/ files?
+;;   - Are you getting obscure errors when trying to open /".tex"/ files?
 ;;     - Don’t despair! Just use `(find-file "dummy.tex")' as the
 ;;       assertion.
 ;;   - Did `ox-html' stop working due to some arcane misconfiguration?
@@ -66,13 +85,26 @@
 ;;       you!
 ;;
 ;;   Finally, you can also use `bug-hunter-file' to hunt in other files.
-
+;;
+;;
+;; init.org and other literate-style configs
+;; =========================================
+;;
+;; Please see the full Readme on http://github.com/Malabarba/elisp-bug-hunter
 
 ;;; Code:
 (require 'seq)
 (require 'cl-lib)
 
-(defvar bug-hunter--assertion-reminder
+(defconst bug-hunter--interactive-explanation
+  "You have asked to do an interactive hunt, here's how it goes.
+1) I will start a new Emacs frame.
+2) You will try to reproduce your problem on the new frame.
+3) When you’re done, close that frame.
+4) I will ask you if you managed to reproduce the problem.
+5) We will repeat steps up to %s times, so hang tight!")
+
+(defconst bug-hunter--assertion-reminder
   "Remember, the assertion must be an expression that returns
 non-nil in your current (problematic) Emacs state, AND that
 returns nil on a clean Emacs instance."
@@ -133,6 +165,7 @@ R is passed to `format' and inserted."
 R is passed to `bug-hunter--report-print'."
   (declare (indent 1))
   (apply #'bug-hunter--report-print r)
+  (redisplay)
   (apply #'message r))
 
 (defun bug-hunter--report-user-error (&rest r)
@@ -140,18 +173,22 @@ R is passed to `bug-hunter--report-print'."
 R is passed to `bug-hunter--report-print'."
   (declare (indent 1))
   (apply #'bug-hunter--report-print r)
-  (bug-hunter--report-print "\xc")
+  (bug-hunter--report-print "\xc\n")
   (apply #'user-error r))
 
 (defvar compilation-error-regexp-alist)
-(defun bug-hunter--init-report-buffer ()
-  "Create and prepare the \"*Bug-Hunter Report*\" buffer."
-  (or (get-buffer "*Bug-Hunter Report*")
-      (with-current-buffer (get-buffer-create "*Bug-Hunter Report*")
-        (compilation-mode "Bug Hunt")
-        (set (make-local-variable 'compilation-error-regexp-alist)
-             '(comma))
-        (current-buffer))))
+(defun bug-hunter--init-report-buffer (assertion steps)
+  "Create and prepare the \"*Bug-Hunter Report*\" buffer.
+Also add some descriptions depending on ASSERTION."
+  (with-current-buffer (get-buffer-create "*Bug-Hunter Report*")
+    (let ((inhibit-read-only t))
+      (erase-buffer)
+      (compilation-mode "Bug Hunt")
+      (set (make-local-variable 'compilation-error-regexp-alist)
+           '(comma))
+      (pcase assertion
+        (`interactive (insert (format bug-hunter--interactive-explanation (+ 2 
steps))))))
+    (current-buffer)))
 
 (defun bug-hunter--pretty-format (value padding)
   "Return a VALUE as a string with PADDING spaces on the left."
@@ -207,42 +244,75 @@ the file."
   (when expression
     (bug-hunter--report "  Caused by the following expression:\n%s"
       (bug-hunter--pretty-format expression 4)))
-  (bug-hunter--report "\xc")
+  (bug-hunter--report "\xc\n")
   `[,error ,line ,column ,expression])
 
 
 ;;; Execution functions
-(defun bug-hunter--run-form (form)
-  "Run FORM with \"emacs -Q\" and return the result."
+(defun bug-hunter--print-to-temp (sexp)
+  "Print SEXP to a temp file and return the file name."
+  (let ((print-length nil)
+        (print-level nil)
+        (file (make-temp-file "bug-hunter")))
+    (with-temp-file file
+      (print sexp (current-buffer)))
+    file))
+
+(defun bug-hunter--run-emacs (file &rest args)
+  "Start an Emacs process to run FILE and return the output buffer.
+ARGS are passed before \"-l FILE\"."
   (let ((out-buf (generate-new-buffer "*Bug-Hunter Command*"))
         (exec (file-truename (expand-file-name invocation-name
-                                               invocation-directory)))
-        (file-name (make-temp-file "bug-hunter")))
+                                               invocation-directory))))
+    (apply #'call-process exec nil out-buf nil
+           (append args (list "-l" file)))
+    out-buf))
+
+(defun bug-hunter--run-form (form)
+  "Run FORM with \"emacs -Q\" and return the result."
+  (let ((file-name (bug-hunter--print-to-temp (list 'prin1 form))))
     (unwind-protect
-        (let ((print-length nil)
-              (print-level nil))
-          (with-temp-file file-name
-            (print (list 'prin1 form) (current-buffer)))
-          (call-process exec nil out-buf nil
-                        "-Q" "--batch" "-l" file-name)
-          (with-current-buffer out-buf
-            (goto-char (point-max))
-            (forward-sexp -1)
-            (prog1 (read (current-buffer))
-              (kill-buffer (current-buffer)))))
+        (with-current-buffer (bug-hunter--run-emacs file-name "-Q" "--batch")
+          (goto-char (point-max))
+          (forward-sexp -1)
+          (prog1 (read (current-buffer))
+            (kill-buffer (current-buffer))))
       (delete-file file-name))))
 
+(defun bug-hunter--run-form-interactively (form)
+  "Run FORM in a graphical frame and ask user about the outcome."
+  (let ((file-name (bug-hunter--print-to-temp (list 'prin1 form))))
+    (unwind-protect
+        (bug-hunter--run-emacs file-name "-Q")
+      (delete-file file-name))
+    (y-or-n-p "Did you find the problem/bug in this instance? ")))
+
+(defun bug-hunter--wrap-forms-for-eval (forms)
+  "Return FORMS wrapped in initialization code."
+  `(let ((server-name (make-temp-file "bug-hunter-temp-server-file")))
+     (delete-file server-name)
+     (if site-run-file (load site-run-file t t))
+     (run-hooks 'before-init-hook)
+     ,@forms
+     (package-initialize)
+     (run-hooks 'after-init-hook)))
+
 (defun bug-hunter--run-and-test (forms assertion)
   "Execute FORMS in the background and test ASSERTION.
-See `bug-hunter' for a description on the ASSERTION."
-  (bug-hunter--run-form
-   `(condition-case er
-        (let ((server-name (make-temp-file "bug-hunter-temp-server-file")))
-          (delete-file server-name)
-          ,@forms
-          (run-hooks 'after-init-hook)
-          ,assertion)
-      (error (cons 'bug-caught er)))))
+See `bug-hunter' for a description on the ASSERTION.
+
+If ASSERTION is 'interactive, the form is run through
+`bug-hunter--run-form-interactively'.  Otherwise, a slightly
+modified version of the form combined with ASSERTION is run
+through `bug-hunter--run-form'."
+  (if (eq assertion 'interactive)
+      (bug-hunter--run-form-interactively
+       (bug-hunter--wrap-forms-for-eval forms))
+    (bug-hunter--run-form
+     `(condition-case er
+          ,(append (bug-hunter--wrap-forms-for-eval forms)
+                   (list assertion))
+        (error (cons 'bug-caught er))))))
 
 
 
@@ -290,7 +360,6 @@ ASSERTION's return value.
 If ASSERTION is nil, n is the position of the first form to
 signal an error and value is (bug-caught . ERROR-SIGNALED)."
   (let ((bug-hunter--i 0)
-        (bug-hunter--estimate (ceiling (log (length forms) 2)))
         (bug-hunter--current-head nil))
     (condition-case-unless-debug nil
         (apply #'bug-hunter--bisect assertion nil (bug-hunter--split forms))
@@ -318,10 +387,16 @@ Bug hunter will refuse to hunt if (i) an error is 
signaled or the
 assertion is triggered while running emacs -Q, or (ii) no errors
 are signaled and the assertion is not triggered after all EXPRs
 are evaluated."
-  (pop-to-buffer (bug-hunter--init-report-buffer))
   (let ((expressions (unless (eq (car-safe rich-forms) 'bug-caught)
-                       (mapcar #'car rich-forms))))
+                       (mapcar #'car rich-forms)))
+        (bug-hunter--estimate (ceiling (log (length rich-forms) 2))))
+    ;; Prepare buffer, and make sure they've seen it.
+    (switch-to-buffer (bug-hunter--init-report-buffer assertion 
bug-hunter--estimate))
+    (when (eq assertion 'interactive)
+      (read-char-choice "Please the instructions above and type 6 when ready. 
" '(?6)))
+
     (cond
+     ;; Check for errors when reading the init file.
      ((not expressions)
       (apply #'bug-hunter--report-error (cdr rich-forms))
       (apply #'vector (cdr rich-forms)))
@@ -368,34 +443,49 @@ There's nothing more I can do here.")
                (list 'assertion-triggered ret)
                (car linecol) (cadr linecol) expression)))))))))
 
+(defconst bug-hunter--hunt-type-prompt
+  "To bisect interactively, type i
+To use automatic error detection, type e
+To provide a lisp assertion, type a
+=> ")
+
 (defun bug-hunter--read-from-minibuffer ()
   "Read a list of expressions from the minibuffer.
-Wraps them in a progn if necessary."
-  (require 'simple)
-  (let ((exprs
-         (with-temp-buffer
-           ;; Copied from `read--expression'.
-           (let ((minibuffer-completing-symbol t))
-             (minibuffer-with-setup-hook
-                 (lambda ()
-                   (add-hook 'completion-at-point-functions
-                             #'elisp-completion-at-point nil t)
-                   (run-hooks 'eval-expression-minibuffer-setup-hook))
-               (insert
-                (read-from-minibuffer
-                 "Expression that returns nil if all is well (optional): "
-                 nil read-expression-map nil 'read-expression-history))))
-           (goto-char (point-min))
-           (mapcar #'car (bug-hunter--read-buffer)))))
-    (if (cdr exprs)
-        (cons #'progn exprs)
-      (car exprs))))
+Wraps them in a progn if necessary to always return a single
+form.
+
+The user may decide to not provide input, in which case
+'interactive is returned.  Note, this is different from the user
+typing `RET' at an empty prompt, in which case nil is returned."
+  (pcase (read-char-choice bug-hunter--hunt-type-prompt '(?i ?e ?a))
+    (`?i 'interactive)
+    (`?e nil)
+    (_
+     (require 'simple)
+     (let ((exprs
+            (with-temp-buffer
+              ;; Copied from `read--expression'.
+              (let ((minibuffer-completing-symbol t))
+                (minibuffer-with-setup-hook
+                    (lambda ()
+                      (add-hook 'completion-at-point-functions
+                                #'elisp-completion-at-point nil t)
+                      (run-hooks 'eval-expression-minibuffer-setup-hook))
+                  (insert
+                   (read-from-minibuffer
+                    "Provide an assertion.  This is a lisp expression that 
returns nil if (and only if) everything is fine:\n => "
+                    nil read-expression-map nil 'read-expression-history))))
+              (goto-char (point-min))
+              (mapcar #'car (bug-hunter--read-buffer)))))
+       (if (cdr exprs)
+           (cons #'progn exprs)
+         (car exprs))))))
 
 ;;;###autoload
 (defun bug-hunter-file (file &optional assertion)
   "Bisect FILE while testing ASSERTION.
 All sexps in FILE are read and passed to `bug-hunter-hunt' as a
-list.  See `bug-hunter-hunt' for how to use assertion."
+list.  See `bug-hunter-hunt' for how to use ASSERTION."
   (interactive
    (list
     (read-file-name "File to bisect: "
@@ -411,7 +501,7 @@ list.  See `bug-hunter-hunt' for how to use assertion."
   "Test ASSERTION throughout `user-init-file'.
 All sexps inside `user-init-file' are read and passed to
 `bug-hunter-hunt' as a list.  See `bug-hunter-hunt' for how to use
-assertion."
+ASSERTION."
   (interactive (list (bug-hunter--read-from-minibuffer)))
   (bug-hunter-file user-init-file assertion))
 
diff --git a/packages/context-coloring/Makefile 
b/packages/context-coloring/Makefile
index bd82b88..0b37043 100644
--- a/packages/context-coloring/Makefile
+++ b/packages/context-coloring/Makefile
@@ -1,6 +1,8 @@
 CASK = cask
 EMACS = emacs
 DEPENDENCIES = .cask/
+SCOPIFIER_PORT = $$(lsof -t -i :6969)
+KILL_SCOPIFIER = if [ -n "${SCOPIFIER_PORT}" ]; then kill ${SCOPIFIER_PORT}; fi
 
 all: uncompile compile test
 
@@ -26,6 +28,7 @@ ${DEPENDENCIES}:
        ${CASK}
 
 test: ${DEPENDENCIES}
+       ${KILL_SCOPIFIER}
        ${CASK} exec ${EMACS} -Q -batch \
        -L . \
        -l ert \
@@ -36,6 +39,7 @@ test: ${DEPENDENCIES}
        -f ert-run-tests-batch-and-exit
 
 cover: ${DEPENDENCIES}
+       ${KILL_SCOPIFIER}
        ${CASK} exec ${EMACS} -Q -batch \
        -L . \
        -l ert \
diff --git a/packages/context-coloring/README.md 
b/packages/context-coloring/README.md
index 39c15cf..40506e7 100644
--- a/packages/context-coloring/README.md
+++ b/packages/context-coloring/README.md
@@ -15,10 +15,12 @@ By default, comments and strings are still highlighted 
syntactically.
 
 - Light and dark (customizable) color schemes.
 - JavaScript support:
-  - Very fast for files under 1000 lines.
   - Script, function and block scopes (and even `catch` block scopes).
+  - Very fast for files under 1000 lines.
 - Emacs Lisp support:
-  - `defun`, `lambda`, `let`, `let*`, quotes, backticks, commas.
+  - `defun`, `lambda`, `let`, `let*`, `cond`, `condition-case`, `defadvice`,
+    `dolist`, `quote`, `backquote` and backquote splicing.
+  - Instantaneous lazy coloring, 8000 lines-per-second full coloring.
 
 ## Installation
 
@@ -84,8 +86,8 @@ Add the following to your init file:
   comments using `font-lock`.
 - `context-coloring-syntactic-strings` (default: `t`): If non-nil, also color
   strings using `font-lock`.
-- `context-coloring-delay` (default: `0.25`; supported modes: `js-mode`,
-  `js3-mode`, `emacs-lisp-mode`): Delay between a buffer update and
+- `context-coloring-default-delay` (default: `0.25`; supported modes: 
`js-mode`,
+  `js3-mode`): Default (sometimes overridden) delay between a buffer update and
   colorization.
 - `context-coloring-js-block-scopes` (default: `nil`; supported modes:
   `js2-mode`): If non-nil, also color block scopes in the scope hierarchy in
diff --git a/packages/context-coloring/benchmark/context-coloring-benchmark.el 
b/packages/context-coloring/benchmark/context-coloring-benchmark.el
index e020f6f..c2dd653 100644
--- a/packages/context-coloring/benchmark/context-coloring-benchmark.el
+++ b/packages/context-coloring/benchmark/context-coloring-benchmark.el
@@ -37,50 +37,94 @@
   "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 to RESULT-FILE for fixture FIXTURE."
-  (elp-results)
-  (let ((results-buffer (current-buffer)))
-    (with-temp-buffer
-      (insert (concat fixture "\n"))
-      (prepend-to-buffer results-buffer (point-min) (point-max)))
-    (with-temp-buffer
-      (insert "\n")
-      (append-to-buffer results-buffer (point-min) (point-max))))
-  (make-directory (context-coloring-benchmark-resolve-path "./logs") t)
-  (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)
-      (progn
-        (context-coloring-benchmark-next-tick stop))
-    (context-coloring-benchmark-next-tick
+(defun context-coloring-benchmark-next-tick (callback)
+  "Run CALLBACK in the next turn of the event loop."
+  (run-with-timer nil nil callback))
+
+(defun context-coloring-benchmark-series (sequence callback)
+  "Call each function in SEQUENCE, then call CALLBACK.  Each
+function is passed a single callback parameter for it to call
+when it is done."
+  (cond
+   ((null sequence)
+    (funcall callback))
+   (t
+    (funcall
+     (car sequence)
      (lambda ()
-       (funcall
-        continue
-        (car list)
+       (context-coloring-benchmark-next-tick
         (lambda ()
-          (context-coloring-benchmark-next (cdr list) continue stop)))))))
-
-(defun context-coloring-benchmark-async (title setup teardown fixtures 
callback)
+          (context-coloring-benchmark-series
+           (cdr sequence)
+           callback))))))))
+
+(defun context-coloring-benchmark-mapc (sequence iteratee callback)
+  "For each element in SEQUENCE, call ITERATEE, finally call
+CALLBACK.  ITERATEE is passed the current element and a callback
+for it to call when it is done."
+  (cond
+   ((null sequence)
+    (funcall callback))
+   (t
+    (funcall
+     iteratee
+     (car sequence)
+     (lambda ()
+       (context-coloring-benchmark-next-tick
+        (lambda ()
+          (context-coloring-benchmark-mapc
+           (cdr sequence)
+           iteratee
+           callback))))))))
+
+(defun context-coloring-benchmark-log-results (result-file fixture statistics)
+  "Log benchmarking results to RESULT-FILE for fixture FIXTURE
+with STATISTICS."
+  (let ((results (prog1
+                     (progn
+                       (elp-results)
+                       (buffer-substring-no-properties (point-min) 
(point-max)))
+                   (kill-buffer))))
+    (make-directory (context-coloring-benchmark-resolve-path "./logs") t)
+    (append-to-file
+     (with-temp-buffer
+       (goto-char (point-min))
+       (insert (format "For fixture \"%s\":\n" fixture))
+       (insert "\n")
+       (insert "General statistics:\n")
+       (insert (format "File size: %s bytes\n" (plist-get statistics 
:file-size)))
+       (insert (format "Lines: %s\n" (plist-get statistics :lines)))
+       (insert (format "Words: %s\n" (plist-get statistics :words)))
+       (insert (format "Colorization times: %s\n"
+                       (context-coloring-join
+                        (mapcar (lambda (number)
+                                  (format "%.4f" number))
+                                (plist-get statistics :colorization-times)) ", 
")))
+       (insert (format "Average colorization time: %.4f\n"
+                       (plist-get statistics :average-colorization-time)))
+       (insert "\n")
+       (insert "Function statistics:\n")
+       (insert "(Function Name / Call Count / Elapsed Time / Average Time):\n")
+       (insert results)
+       (insert "\n")
+       (buffer-substring-no-properties (point-min) (point-max)))
+     nil result-file)))
+
+(defun context-coloring-benchmark (title setup teardown fixtures callback)
   "Execute a benchmark titled TITLE with SETUP and TEARDOWN
 callbacks.  Measure the performance of all FIXTURES, calling
 CALLBACK when all are done."
   (funcall setup)
+  (elp-instrument-package "context-coloring-")
   (let ((result-file (context-coloring-benchmark-resolve-path
                       (format "./logs/results-%s-%s.log"
                               title (format-time-string "%s")))))
-    (context-coloring-benchmark-next
+    (context-coloring-benchmark-mapc
      fixtures
-     (lambda (path next)
+     (lambda (path callback)
        (let ((fixture (context-coloring-benchmark-resolve-path path))
+             colorization-start-time
+             (colorization-times '())
              advice)
          (setq
           advice
@@ -90,21 +134,31 @@ CALLBACK when all are done."
                original-function
                (lambda ()
                  (setq count (+ count 1))
+                 (push (- (float-time) colorization-start-time) 
colorization-times)
                  ;; Test 5 times.
-                 (if (= count 5)
-                     (progn
-                       (advice-remove 'context-coloring-colorize advice)
-                       (kill-buffer)
-                       (context-coloring-benchmark-log-results
-                        result-file
-                        fixture)
-                       (funcall next))
-                   (funcall 'context-coloring-colorize)))))))
-         (advice-add 'context-coloring-colorize :around advice)
+                 (cond
+                  ((= count 5)
+                   (advice-remove #'context-coloring-colorize advice)
+                   (context-coloring-benchmark-log-results
+                    result-file
+                    fixture
+                    (list
+                     :file-size (nth 7 (file-attributes fixture))
+                     :lines (count-lines (point-min) (point-max))
+                     :words (count-words (point-min) (point-max))
+                     :colorization-times colorization-times
+                     :average-colorization-time (/ (apply #'+ 
colorization-times) 5)))
+                   (kill-buffer)
+                   (funcall callback))
+                  (t
+                   (setq colorization-start-time (float-time))
+                   (context-coloring-colorize))))))))
+         (advice-add #'context-coloring-colorize :around advice)
+         (setq colorization-start-time (float-time))
          (find-file fixture)))
      (lambda ()
        (funcall teardown)
-       (when callback (funcall callback))))))
+       (funcall callback)))))
 
 (defconst context-coloring-benchmark-js-fixtures
   '("./fixtures/jquery-2.1.1.js"
@@ -113,56 +167,66 @@ CALLBACK when all are done."
     "./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
+  (context-coloring-benchmark
    "js-mode"
-   'context-coloring-benchmark-js-mode-setup
-   'context-coloring-benchmark-js-mode-teardown
+   (lambda ()
+     "Preparation logic for `js-mode'."
+     (add-hook 'js-mode-hook #'context-coloring-mode))
+   (lambda ()
+     "Cleanup logic for `js-mode'."
+     (remove-hook 'js-mode-hook #'context-coloring-mode))
    context-coloring-benchmark-js-fixtures
    callback))
 
-(defun context-coloring-benchmark-js2-mode-setup ()
-  "Preparation logic for `js2-mode'."
-  (setq js2-mode-show-parse-errors nil)
-  (setq js2-mode-show-strict-warnings nil)
-  (add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
-  (add-hook 'js2-mode-hook 'context-coloring-mode)
-  (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))
-  (setq js2-mode-show-strict-warnings t)
-  (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
+  (context-coloring-benchmark
    "js2-mode"
-   'context-coloring-benchmark-js2-mode-setup
-   'context-coloring-benchmark-js2-mode-teardown
+   (lambda ()
+     "Preparation logic for `js2-mode'."
+     (setq js2-mode-show-parse-errors nil)
+     (setq js2-mode-show-strict-warnings nil)
+     (add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
+     (add-hook 'js2-mode-hook #'context-coloring-mode))
+   (lambda ()
+     "Cleanup logic for `js2-mode'."
+     (remove-hook 'js2-mode-hook #'context-coloring-mode)
+     (setq auto-mode-alist (delete '("\\.js\\'" . js2-mode)
+                                   auto-mode-alist))
+     (setq js2-mode-show-strict-warnings t)
+     (setq js2-mode-show-parse-errors t))
    context-coloring-benchmark-js-fixtures
    callback))
 
+(defconst context-coloring-benchmark-emacs-lisp-fixtures
+  '("./fixtures/lisp.el"
+    "./fixtures/faces.el"
+    "./fixtures/subr.el"
+    "./fixtures/simple.el")
+  "Arbitrary Emacs Lisp files for performance scrutiny.")
+
+(defun context-coloring-benchmark-emacs-lisp-mode-run (callback)
+  "Benchmark `emacs-lisp-mode', then call CALLBACK."
+  (context-coloring-benchmark
+   "emacs-lisp-mode"
+   (lambda ()
+     "Preparation logic for `emacs-lisp-mode'."
+     (add-hook 'emacs-lisp-mode-hook #'context-coloring-mode))
+   (lambda ()
+     "Cleanup logic for `emacs-lisp-mode'."
+     (remove-hook 'emacs-lisp-mode-hook #'context-coloring-mode))
+   context-coloring-benchmark-emacs-lisp-fixtures
+   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)
-   (lambda (function next)
-     (funcall function next))
+  (context-coloring-benchmark-series
+   (list
+    #'context-coloring-benchmark-js-mode-run
+    #'context-coloring-benchmark-js2-mode-run
+    #'context-coloring-benchmark-emacs-lisp-mode-run)
    (lambda ()
      (kill-emacs))))
 
diff --git a/packages/context-coloring/benchmark/fixtures/faces.el 
b/packages/context-coloring/benchmark/fixtures/faces.el
new file mode 100644
index 0000000..5176bed
--- /dev/null
+++ b/packages/context-coloring/benchmark/fixtures/faces.el
@@ -0,0 +1,2764 @@
+;;; faces.el --- Lisp faces
+
+;; Copyright (C) 1992-1996, 1998-2015 Free Software Foundation, Inc.
+
+;; Maintainer: address@hidden
+;; Keywords: internal
+;; Package: emacs
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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.
+
+;; GNU Emacs 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 GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(defcustom term-file-prefix (purecopy "term/")
+  "If non-nil, Emacs startup performs terminal-specific initialization.
+It does this by: (load (concat term-file-prefix (getenv \"TERM\")))
+
+You may set this variable to nil in your init file if you do not wish
+the terminal-initialization file to be loaded."
+  :type '(choice (const :tag "No terminal-specific initialization" nil)
+                (string :tag "Name of directory with term files"))
+  :group 'terminals)
+
+(declare-function xw-defined-colors "term/common-win" (&optional frame))
+
+(defvar help-xref-stack-item)
+
+(defvar face-name-history nil
+  "History list for some commands that read face names.
+Maximum length of the history list is determined by the value
+of `history-length', which see.")
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Font selection.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defgroup font-selection nil
+  "Influencing face font selection."
+  :group 'faces)
+
+
+(defcustom face-font-selection-order
+  '(:width :height :weight :slant)
+  "A list specifying how face font selection chooses fonts.
+Each of the four symbols `:width', `:height', `:weight', and `:slant'
+must appear once in the list, and the list must not contain any other
+elements.  Font selection first tries to find a best matching font
+for those face attributes that appear before in the list.  For
+example, if `:slant' appears before `:height', font selection first
+tries to find a font with a suitable slant, even if this results in
+a font height that isn't optimal."
+  :tag "Font selection order"
+  :type '(list symbol symbol symbol symbol)
+  :group 'font-selection
+  :set #'(lambda (symbol value)
+          (set-default symbol value)
+          (internal-set-font-selection-order value)))
+
+
+;; In the absence of Fontconfig support, Monospace and Sans Serif are
+;; unavailable, and we fall back on the courier and helv families,
+;; which are generally available.
+(defcustom face-font-family-alternatives
+  (mapcar (lambda (arg) (mapcar 'purecopy arg))
+  '(("Monospace" "courier" "fixed")
+    ("courier" "CMU Typewriter Text" "fixed")
+    ("Sans Serif" "helv" "helvetica" "arial" "fixed")
+    ("helv" "helvetica" "arial" "fixed")))
+  "Alist of alternative font family names.
+Each element has the form (FAMILY ALTERNATIVE1 ALTERNATIVE2 ...).
+If fonts of family FAMILY can't be loaded, try ALTERNATIVE1, then
+ALTERNATIVE2 etc."
+  :tag "Alternative font families to try"
+  :type '(repeat (repeat string))
+  :group 'font-selection
+  :set #'(lambda (symbol value)
+          (set-default symbol value)
+          (internal-set-alternative-font-family-alist value)))
+
+
+;; This is defined originally in xfaces.c.
+(defcustom face-font-registry-alternatives
+  (mapcar (lambda (arg) (mapcar 'purecopy arg))
+  (if (featurep 'w32)
+      '(("iso8859-1" "ms-oemlatin")
+       ("gb2312.1980" "gb2312" "gbk" "gb18030")
+       ("jisx0208.1990" "jisx0208.1983" "jisx0208.1978")
+       ("ksc5601.1989" "ksx1001.1992" "ksc5601.1987")
+       ("muletibetan-2" "muletibetan-0"))
+    '(("gb2312.1980" "gb2312.80&gb8565.88" "gbk" "gb18030")
+      ("jisx0208.1990" "jisx0208.1983" "jisx0208.1978")
+      ("ksc5601.1989" "ksx1001.1992" "ksc5601.1987")
+      ("muletibetan-2" "muletibetan-0"))))
+  "Alist of alternative font registry names.
+Each element has the form (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...).
+If fonts of registry REGISTRY can be loaded, font selection
+tries to find a best matching font among all fonts of registry
+REGISTRY, ALTERNATIVE1, ALTERNATIVE2, and etc."
+  :tag "Alternative font registries to try"
+  :type '(repeat (repeat string))
+  :version "21.1"
+  :group 'font-selection
+  :set #'(lambda (symbol value)
+          (set-default symbol value)
+          (internal-set-alternative-font-registry-alist value)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Creation, copying.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defun face-list ()
+  "Return a list of all defined faces."
+  (mapcar #'car face-new-frame-defaults))
+
+(defun make-face (face &optional no-init-from-resources)
+  "Define a new face with name FACE, a symbol.
+Do not call this directly from Lisp code; use `defface' instead.
+
+If FACE is already known as a face, leave it unmodified.  Return FACE.
+
+NO-INIT-FROM-RESOURCES has been deprecated and is no longer used
+and will go away.  Handling of conditional X resources application
+has been pushed down to make-x-resource-internal itself."
+  (interactive (list (read-from-minibuffer
+                     "Make face: " nil nil t 'face-name-history)))
+  (unless (facep face)
+    ;; Make frame-local faces (this also makes the global one).
+    (dolist (frame (frame-list))
+      (internal-make-lisp-face face frame))
+    ;; Add the face to the face menu.
+    (when (fboundp 'facemenu-add-new-face)
+      (facemenu-add-new-face face))
+    ;; Define frame-local faces for all frames from X resources.
+    (make-face-x-resource-internal face))
+  face)
+
+;; Handling of whether to apply X resources or not, has been pushed down
+;; to make-face-x-resource-internal itself, thus the optional arg is no
+;; longer evaluated at all and going away.
+(set-advertised-calling-convention 'make-face '(face) "24.4")
+
+(defun make-empty-face (face)
+  "Define a new, empty face with name FACE.
+Do not call this directly from Lisp code; use `defface' instead."
+  (interactive (list (read-from-minibuffer
+                     "Make empty face: " nil nil t 'face-name-history)))
+  (make-face face))
+
+(defun copy-face (old-face new-face &optional frame new-frame)
+  "Define a face named NEW-FACE, which is a copy of OLD-FACE.
+This function does not copy face customization data, so NEW-FACE
+will not be made customizable.  Most Lisp code should not call
+this function; use `defface' with :inherit instead.
+
+If NEW-FACE already exists as a face, modify it to be like
+OLD-FACE.  If NEW-FACE doesn't already exist, create it.
+
+If the optional argument FRAME is a frame, change NEW-FACE on
+FRAME only.  If FRAME is t, copy the frame-independent default
+specification for OLD-FACE to NEW-FACE.  If FRAME is nil, copy
+the defaults as well as the faces on each existing frame.
+
+If the optional fourth argument NEW-FRAME is given, copy the
+information from face OLD-FACE on frame FRAME to NEW-FACE on
+frame NEW-FRAME.  In this case, FRAME must not be nil."
+  (let ((inhibit-quit t))
+    (if (null frame)
+       (progn
+         (when new-frame
+           (error "Copying face %s from all frames to one frame"
+                  old-face))
+         (make-empty-face new-face)
+         (dolist (frame (frame-list))
+           (copy-face old-face new-face frame))
+         (copy-face old-face new-face t))
+      (make-empty-face new-face)
+      (internal-copy-lisp-face old-face new-face frame new-frame))
+    new-face))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Predicates, type checks.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun facep (face)
+  "Return non-nil if FACE is a face name; nil otherwise.
+A face name can be a string or a symbol."
+  (internal-lisp-face-p face))
+
+
+(defun check-face (face)
+  "Signal an error if FACE doesn't name a face.
+Value is FACE."
+  (unless (facep face)
+    (error "Not a face: %s" face))
+  face)
+
+
+;; The ID returned is not to be confused with the internally used IDs
+;; of realized faces.  The ID assigned to Lisp faces is used to
+;; support faces in display table entries.
+
+(defun face-id (face &optional _frame)
+  "Return the internal ID of face with name FACE.
+If FACE is a face-alias, return the ID of the target face.
+The optional argument FRAME is ignored, since the internal face ID
+of a face name is the same for all frames."
+  (check-face face)
+  (or (get face 'face)
+      (face-id (get face 'face-alias))))
+
+(defun face-equal (face1 face2 &optional frame)
+  "Non-nil if faces FACE1 and FACE2 are equal.
+Faces are considered equal if all their attributes are equal.
+If the optional argument FRAME is given, report on FACE1 and FACE2 in that 
frame.
+If FRAME is t, report on the defaults for FACE1 and FACE2 (for new frames).
+If FRAME is omitted or nil, use the selected frame."
+  (internal-lisp-face-equal-p face1 face2 frame))
+
+
+(defun face-differs-from-default-p (face &optional frame)
+  "Return non-nil if FACE displays differently from the default face.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame."
+  (let ((attrs
+        (delq :inherit (mapcar 'car face-attribute-name-alist)))
+       (differs nil))
+    (while (and attrs (not differs))
+      (let* ((attr (pop attrs))
+            (attr-val (face-attribute face attr frame t)))
+       (when (and
+              (not (eq attr-val 'unspecified))
+              (display-supports-face-attributes-p (list attr attr-val)
+                                                  frame))
+         (setq differs attr))))
+    differs))
+
+
+(defun face-nontrivial-p (face &optional frame)
+  "True if face FACE has some non-nil attribute.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame."
+  (not (internal-lisp-face-empty-p face frame)))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Setting face attributes from X resources.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defcustom face-x-resources
+  (mapcar
+   (lambda (arg)
+     ;; FIXME; can we purecopy some of the conses too?
+     (cons (car arg)
+          (cons (purecopy (car (cdr arg))) (purecopy (cdr (cdr arg))))))
+  '((:family (".attributeFamily" . "Face.AttributeFamily"))
+    (:foundry (".attributeFoundry" . "Face.AttributeFoundry"))
+    (:width (".attributeWidth" . "Face.AttributeWidth"))
+    (:height (".attributeHeight" . "Face.AttributeHeight"))
+    (:weight (".attributeWeight" . "Face.AttributeWeight"))
+    (:slant (".attributeSlant" . "Face.AttributeSlant"))
+    (:foreground (".attributeForeground" . "Face.AttributeForeground"))
+    (:distant-foreground
+     (".attributeDistantForeground" . "Face.AttributeDistantForeground"))
+    (:background (".attributeBackground" . "Face.AttributeBackground"))
+    (:overline (".attributeOverline" . "Face.AttributeOverline"))
+    (:strike-through (".attributeStrikeThrough" . 
"Face.AttributeStrikeThrough"))
+    (:box (".attributeBox" . "Face.AttributeBox"))
+    (:underline (".attributeUnderline" . "Face.AttributeUnderline"))
+    (:inverse-video (".attributeInverse" . "Face.AttributeInverse"))
+    (:stipple
+     (".attributeStipple" . "Face.AttributeStipple")
+     (".attributeBackgroundPixmap" . "Face.AttributeBackgroundPixmap"))
+    (:bold (".attributeBold" . "Face.AttributeBold"))
+    (:italic (".attributeItalic" . "Face.AttributeItalic"))
+    (:font (".attributeFont" . "Face.AttributeFont"))
+    (:inherit (".attributeInherit" . "Face.AttributeInherit"))))
+  "List of X resources and classes for face attributes.
+Each element has the form (ATTRIBUTE ENTRY1 ENTRY2...) where ATTRIBUTE is
+the name of a face attribute, and each ENTRY is a cons of the form
+\(RESOURCE . CLASS) with RESOURCE being the resource and CLASS being the
+X resource class for the attribute."
+  :type '(repeat (cons symbol (repeat (cons string string))))
+  :group 'faces)
+
+
+(declare-function internal-face-x-get-resource "xfaces.c"
+                 (resource class &optional frame))
+
+(declare-function internal-set-lisp-face-attribute-from-resource "xfaces.c"
+                 (face attr value &optional frame))
+
+(defun set-face-attribute-from-resource (face attribute resource class frame)
+  "Set FACE's ATTRIBUTE from X resource RESOURCE, class CLASS on FRAME.
+Value is the attribute value specified by the resource, or nil
+if not present.  This function displays a message if the resource
+specifies an invalid attribute."
+  (let* ((face-name (face-name face))
+        (value (internal-face-x-get-resource (concat face-name resource)
+                                             class frame)))
+    (when value
+      (condition-case ()
+         (internal-set-lisp-face-attribute-from-resource
+          face attribute (downcase value) frame)
+       (error
+        (message "Face %s, frame %s: invalid attribute %s %s from X resource"
+                 face-name frame attribute value))))
+    value))
+
+
+(defun set-face-attributes-from-resources (face frame)
+  "Set attributes of FACE from X resources for FRAME."
+  (when (memq (framep frame) '(x w32))
+    (dolist (definition face-x-resources)
+      (let ((attribute (car definition)))
+       (dolist (entry (cdr definition))
+         (set-face-attribute-from-resource face attribute (car entry)
+                                           (cdr entry) frame))))))
+
+
+(defun make-face-x-resource-internal (face &optional frame)
+  "Fill frame-local FACE on FRAME from X resources.
+FRAME nil or not specified means do it for all frames.
+
+If `inhibit-x-resources' is non-nil, this function does nothing."
+  (unless inhibit-x-resources
+    (dolist (frame (if (null frame) (frame-list) (list frame)))
+      ;; `x-create-frame' already took care of correctly handling
+      ;; the reverse video case-- do _not_ touch the default face
+      (unless (and (eq face 'default)
+                  (frame-parameter frame 'reverse))
+        (set-face-attributes-from-resources face frame)))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Retrieving face attributes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun face-name (face)
+  "Return the name of face FACE."
+  (symbol-name (check-face face)))
+
+
+(defun face-all-attributes (face &optional frame)
+  "Return an alist stating the attributes of FACE.
+Each element of the result has the form (ATTR-NAME . ATTR-VALUE).
+If FRAME is omitted or nil the value describes the default attributes,
+but if you specify FRAME, the value describes the attributes
+of FACE on FRAME."
+  (mapcar (lambda (pair)
+           (let ((attr (car pair)))
+             (cons attr (face-attribute face attr (or frame t)))))
+         face-attribute-name-alist))
+
+(defun face-attribute (face attribute &optional frame inherit)
+  "Return the value of FACE's ATTRIBUTE on FRAME.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.
+
+If INHERIT is nil, only attributes directly defined by FACE are considered,
+  so the return value may be `unspecified', or a relative value.
+If INHERIT is non-nil, FACE's definition of ATTRIBUTE is merged with the
+  faces specified by its `:inherit' attribute; however the return value
+  may still be `unspecified' or relative.
+If INHERIT is a face or a list of faces, then the result is further merged
+  with that face (or faces), until it becomes specified and absolute.
+
+To ensure that the return value is always specified and absolute, use a
+value of `default' for INHERIT; this will resolve any unspecified or
+relative values by merging with the `default' face (which is always
+completely specified)."
+  (let ((value (internal-get-lisp-face-attribute face attribute frame)))
+    (when (and inherit (face-attribute-relative-p attribute value))
+      ;; VALUE is relative, so merge with inherited faces
+      (let ((inh-from (face-attribute face :inherit frame)))
+       (unless (or (null inh-from) (eq inh-from 'unspecified))
+          (condition-case nil
+              (setq value
+                    (face-attribute-merged-with attribute value inh-from 
frame))
+            ;; The `inherit' attribute may point to non existent faces.
+            (error nil)))))
+    (when (and inherit
+              (not (eq inherit t))
+              (face-attribute-relative-p attribute value))
+      ;; We should merge with INHERIT as well
+      (setq value (face-attribute-merged-with attribute value inherit frame)))
+    value))
+
+(defun face-attribute-merged-with (attribute value faces &optional frame)
+  "Merges ATTRIBUTE, initially VALUE, with faces from FACES until absolute.
+FACES may be either a single face or a list of faces.
+\[This is an internal function.]"
+  (cond ((not (face-attribute-relative-p attribute value))
+        value)
+       ((null faces)
+        value)
+       ((consp faces)
+        (face-attribute-merged-with
+         attribute
+         (face-attribute-merged-with attribute value (car faces) frame)
+         (cdr faces)
+         frame))
+       (t
+        (merge-face-attribute attribute
+                              value
+                              (face-attribute faces attribute frame t)))))
+
+
+(defmacro face-attribute-specified-or (value &rest body)
+  "Return VALUE, unless it's `unspecified', in which case evaluate BODY and 
return the result."
+  (let ((temp (make-symbol "value")))
+    `(let ((,temp ,value))
+       (if (not (eq ,temp 'unspecified))
+          ,temp
+        ,@body))))
+
+(defun face-foreground (face &optional frame inherit)
+  "Return the foreground color name of FACE, or nil if unspecified.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.
+
+If INHERIT is nil, only a foreground color directly defined by FACE is
+  considered, so the return value may be nil.
+If INHERIT is t, and FACE doesn't define a foreground color, then any
+  foreground color that FACE inherits through its `:inherit' attribute
+  is considered as well; however the return value may still be nil.
+If INHERIT is a face or a list of faces, then it is used to try to
+  resolve an unspecified foreground color.
+
+To ensure that a valid color is always returned, use a value of
+`default' for INHERIT; this will resolve any unspecified values by
+merging with the `default' face (which is always completely specified)."
+  (face-attribute-specified-or (face-attribute face :foreground frame inherit)
+                              nil))
+
+(defun face-background (face &optional frame inherit)
+  "Return the background color name of FACE, or nil if unspecified.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.
+
+If INHERIT is nil, only a background color directly defined by FACE is
+  considered, so the return value may be nil.
+If INHERIT is t, and FACE doesn't define a background color, then any
+  background color that FACE inherits through its `:inherit' attribute
+  is considered as well; however the return value may still be nil.
+If INHERIT is a face or a list of faces, then it is used to try to
+  resolve an unspecified background color.
+
+To ensure that a valid color is always returned, use a value of
+`default' for INHERIT; this will resolve any unspecified values by
+merging with the `default' face (which is always completely specified)."
+  (face-attribute-specified-or (face-attribute face :background frame inherit)
+                              nil))
+
+(defun face-stipple (face &optional frame inherit)
+ "Return the stipple pixmap name of FACE, or nil if unspecified.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.
+
+If INHERIT is nil, only a stipple directly defined by FACE is
+  considered, so the return value may be nil.
+If INHERIT is t, and FACE doesn't define a stipple, then any stipple
+  that FACE inherits through its `:inherit' attribute is considered as
+  well; however the return value may still be nil.
+If INHERIT is a face or a list of faces, then it is used to try to
+  resolve an unspecified stipple.
+
+To ensure that a valid stipple or nil is always returned, use a value of
+`default' for INHERIT; this will resolve any unspecified values by merging
+with the `default' face (which is always completely specified)."
+  (face-attribute-specified-or (face-attribute face :stipple frame inherit)
+                              nil))
+
+
+(defalias 'face-background-pixmap 'face-stipple)
+
+
+(defun face-underline-p (face &optional frame inherit)
+ "Return non-nil if FACE specifies a non-nil underlining.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.
+Optional argument INHERIT is passed to `face-attribute'."
+ (face-attribute-specified-or
+  (face-attribute face :underline frame inherit) nil))
+
+
+(defun face-inverse-video-p (face &optional frame inherit)
+ "Return non-nil if FACE specifies a non-nil inverse-video.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.
+Optional argument INHERIT is passed to `face-attribute'."
+ (eq (face-attribute face :inverse-video frame inherit) t))
+
+
+(defun face-bold-p (face &optional frame inherit)
+  "Return non-nil if the font of FACE is bold on FRAME.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.
+Optional argument INHERIT is passed to `face-attribute'.
+Use `face-attribute' for finer control."
+  (let ((bold (face-attribute face :weight frame inherit)))
+    (memq bold '(semi-bold bold extra-bold ultra-bold))))
+
+
+(defun face-italic-p (face &optional frame inherit)
+  "Return non-nil if the font of FACE is italic on FRAME.
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame.
+Optional argument INHERIT is passed to `face-attribute'.
+Use `face-attribute' for finer control."
+  (let ((italic (face-attribute face :slant frame inherit)))
+    (memq italic '(italic oblique))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Face documentation.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun face-documentation (face)
+  "Get the documentation string for FACE.
+If FACE is a face-alias, get the documentation for the target face."
+  (let ((alias (get face 'face-alias)))
+    (if alias
+        (let ((doc (get alias 'face-documentation)))
+         (format "%s is an alias for the face `%s'.%s" face alias
+                  (if doc (format "\n%s" doc)
+                    "")))
+      (get face 'face-documentation))))
+
+
+(defun set-face-documentation (face string)
+  "Set the documentation string for FACE to STRING."
+  ;; Perhaps the text should go in DOC.
+  (put face 'face-documentation (purecopy string)))
+
+
+(defalias 'face-doc-string 'face-documentation)
+(defalias 'set-face-doc-string 'set-face-documentation)
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Setting face attributes.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defun set-face-attribute (face frame &rest args)
+  "Set attributes of FACE on FRAME from ARGS.
+This function overrides the face attributes specified by FACE's
+face spec.  It is mostly intended for internal use only.
+
+If FRAME is nil, set the attributes for all existing frames, as
+well as the default for new frames.  If FRAME is t, change the
+default for new frames only.
+
+ARGS must come in pairs ATTRIBUTE VALUE.  ATTRIBUTE must be a
+valid face attribute name.  All attributes can be set to
+`unspecified'; this fact is not further mentioned below.
+
+The following attributes are recognized:
+
+`:family'
+
+VALUE must be a string specifying the font family
+\(e.g. \"Monospace\") or a fontset.
+
+`:foundry'
+
+VALUE must be a string specifying the font foundry,
+e.g. ``adobe''.  If a font foundry is specified, wild-cards `*'
+and `?' are allowed.
+
+`:width'
+
+VALUE specifies the relative proportionate width of the font to use.
+It must be one of the symbols `ultra-condensed', `extra-condensed',
+`condensed', `semi-condensed', `normal', `semi-expanded', `expanded',
+`extra-expanded', or `ultra-expanded'.
+
+`:height'
+
+VALUE specifies the relative or absolute height of the font.  An
+absolute height is an integer, and specifies font height in units
+of 1/10 pt.  A relative height is either a floating point number,
+which specifies a scaling factor for the underlying face height;
+or a function that takes a single argument (the underlying face
+height) and returns the new height.  Note that for the `default'
+face, you must specify an absolute height (since there is nothing
+for it to be relative to).
+
+`:weight'
+
+VALUE specifies the weight of the font to use.  It must be one of the
+symbols `ultra-bold', `extra-bold', `bold', `semi-bold', `normal',
+`semi-light', `light', `extra-light', `ultra-light'.
+
+`:slant'
+
+VALUE specifies the slant of the font to use.  It must be one of the
+symbols `italic', `oblique', `normal', `reverse-italic', or
+`reverse-oblique'.
+
+`:foreground', `:background'
+
+VALUE must be a color name, a string.
+
+`:underline'
+
+VALUE specifies whether characters in FACE should be underlined.
+If VALUE is t, underline with foreground color of the face.
+If VALUE is a string, underline with that color.
+If VALUE is nil, explicitly don't underline.
+
+Otherwise, VALUE must be a property list of the form:
+
+`(:color COLOR :style STYLE)'.
+
+COLOR can be a either a color name string or `foreground-color'.
+STYLE can be either `line' or `wave'.
+If a keyword/value pair is missing from the property list, a
+default value will be used for the value.
+The default value of COLOR is the foreground color of the face.
+The default value of STYLE is `line'.
+
+`:overline'
+
+VALUE specifies whether characters in FACE should be overlined.  If
+VALUE is t, overline with foreground color of the face.  If VALUE is a
+string, overline with that color.  If VALUE is nil, explicitly don't
+overline.
+
+`:strike-through'
+
+VALUE specifies whether characters in FACE should be drawn with a line
+striking through them.  If VALUE is t, use the foreground color of the
+face.  If VALUE is a string, strike-through with that color.  If VALUE
+is nil, explicitly don't strike through.
+
+`:box'
+
+VALUE specifies whether characters in FACE should have a box drawn
+around them.  If VALUE is nil, explicitly don't draw boxes.  If
+VALUE is t, draw a box with lines of width 1 in the foreground color
+of the face.  If VALUE is a string, the string must be a color name,
+and the box is drawn in that color with a line width of 1.  Otherwise,
+VALUE must be a property list of the form `(:line-width WIDTH
+:color COLOR :style STYLE)'.  If a keyword/value pair is missing from
+the property list, a default value will be used for the value, as
+specified below.  WIDTH specifies the width of the lines to draw; it
+defaults to 1.  If WIDTH is negative, the absolute value is the width
+of the lines, and draw top/bottom lines inside the characters area,
+not around it.  COLOR is the name of the color to draw in, default is
+the foreground color of the face for simple boxes, and the background
+color of the face for 3D boxes.  STYLE specifies whether a 3D box
+should be draw.  If STYLE is `released-button', draw a box looking
+like a released 3D button.  If STYLE is `pressed-button' draw a box
+that appears like a pressed button.  If STYLE is nil, the default if
+the property list doesn't contain a style specification, draw a 2D
+box.
+
+`:inverse-video'
+
+VALUE specifies whether characters in FACE should be displayed in
+inverse video.  VALUE must be one of t or nil.
+
+`:stipple'
+
+If VALUE is a string, it must be the name of a file of pixmap data.
+The directories listed in the `x-bitmap-file-path' variable are
+searched.  Alternatively, VALUE may be a list of the form (WIDTH
+HEIGHT DATA) where WIDTH and HEIGHT are the size in pixels, and DATA
+is a string containing the raw bits of the bitmap.  VALUE nil means
+explicitly don't use a stipple pattern.
+
+For convenience, attributes `:family', `:foundry', `:width',
+`:height', `:weight', and `:slant' may also be set in one step
+from an X font name:
+
+`:font'
+
+Set font-related face attributes from VALUE.  VALUE must be a
+valid font name or font object.  Setting this attribute will also
+set the `:family', `:foundry', `:width', `:height', `:weight',
+and `:slant' attributes.
+
+`:inherit'
+
+VALUE is the name of a face from which to inherit attributes, or
+a list of face names.  Attributes from inherited faces are merged
+into the face like an underlying face would be, with higher
+priority than underlying faces.
+
+For backward compatibility, the keywords `:bold' and `:italic'
+can be used to specify weight and slant respectively.  This usage
+is considered obsolete.  For these two keywords, the VALUE must
+be either t or nil.  A value of t for `:bold' is equivalent to
+setting `:weight' to `bold', and a value of t for `:italic' is
+equivalent to setting `:slant' to `italic'.  But if `:weight' is
+specified in the face spec, `:bold' is ignored, and if `:slant'
+is specified, `:italic' is ignored."
+  (setq args (purecopy args))
+  (let ((where (if (null frame) 0 frame))
+       (spec args)
+       family foundry)
+    ;; If we set the new-frame defaults, this face is modified outside Custom.
+    (if (memq where '(0 t))
+       (put (or (get face 'face-alias) face) 'face-modified t))
+    ;; If family and/or foundry are specified, set it first.  Certain
+    ;; face attributes, e.g. :weight semi-condensed, are not supported
+    ;; in every font.  See bug#1127.
+    (while spec
+      (cond ((eq (car spec) :family)
+            (setq family (cadr spec)))
+           ((eq (car spec) :foundry)
+            (setq foundry (cadr spec))))
+      (setq spec (cddr spec)))
+    (when (or family foundry)
+      (when (and (stringp family)
+                (string-match "\\([^-]*\\)-\\([^-]*\\)" family))
+       (unless foundry
+         (setq foundry (match-string 1 family)))
+       (setq family (match-string 2 family)))
+      (when (or (stringp family) (eq family 'unspecified))
+       (internal-set-lisp-face-attribute face :family (purecopy family)
+                                         where))
+      (when (or (stringp foundry) (eq foundry 'unspecified))
+       (internal-set-lisp-face-attribute face :foundry (purecopy foundry)
+                                         where)))
+    (while args
+      (unless (memq (car args) '(:family :foundry))
+       (internal-set-lisp-face-attribute face (car args)
+                                         (purecopy (cadr args))
+                                         where))
+      (setq args (cddr args)))))
+
+(defun make-face-bold (face &optional frame _noerror)
+  "Make the font of FACE be bold, if possible.
+FRAME nil or not specified means change face on all frames.
+Argument NOERROR is ignored and retained for compatibility.
+Use `set-face-attribute' for finer control of the font weight."
+  (interactive (list (read-face-name "Make which face bold"
+                                     (face-at-point t))))
+  (set-face-attribute face frame :weight 'bold))
+
+
+(defun make-face-unbold (face &optional frame _noerror)
+  "Make the font of FACE be non-bold, if possible.
+FRAME nil or not specified means change face on all frames.
+Argument NOERROR is ignored and retained for compatibility."
+  (interactive (list (read-face-name "Make which face non-bold"
+                                     (face-at-point t))))
+  (set-face-attribute face frame :weight 'normal))
+
+
+(defun make-face-italic (face &optional frame _noerror)
+  "Make the font of FACE be italic, if possible.
+FRAME nil or not specified means change face on all frames.
+Argument NOERROR is ignored and retained for compatibility.
+Use `set-face-attribute' for finer control of the font slant."
+  (interactive (list (read-face-name "Make which face italic"
+                                     (face-at-point t))))
+  (set-face-attribute face frame :slant 'italic))
+
+
+(defun make-face-unitalic (face &optional frame _noerror)
+  "Make the font of FACE be non-italic, if possible.
+FRAME nil or not specified means change face on all frames.
+Argument NOERROR is ignored and retained for compatibility."
+  (interactive (list (read-face-name "Make which face non-italic"
+                                     (face-at-point t))))
+  (set-face-attribute face frame :slant 'normal))
+
+
+(defun make-face-bold-italic (face &optional frame _noerror)
+  "Make the font of FACE be bold and italic, if possible.
+FRAME nil or not specified means change face on all frames.
+Argument NOERROR is ignored and retained for compatibility.
+Use `set-face-attribute' for finer control of font weight and slant."
+  (interactive (list (read-face-name "Make which face bold-italic"
+                                     (face-at-point t))))
+  (set-face-attribute face frame :weight 'bold :slant 'italic))
+
+
+(defun set-face-font (face font &optional frame)
+  "Change font-related attributes of FACE to those of FONT (a string).
+FRAME nil or not specified means change face on all frames.
+This sets the attributes `:family', `:foundry', `:width',
+`:height', `:weight', and `:slant'.  When called interactively,
+prompt for the face and font."
+  (interactive (read-face-and-attribute :font))
+  (set-face-attribute face frame :font font))
+
+
+;; Implementation note: Emulating gray background colors with a
+;; stipple pattern is now part of the face realization process, and is
+;; done in C depending on the frame on which the face is realized.
+
+(defun set-face-background (face color &optional frame)
+  "Change the background color of face FACE to COLOR (a string).
+FRAME nil or not specified means change face on all frames.
+COLOR can be a system-defined color name (see `list-colors-display')
+or a hex spec of the form #RRGGBB.
+When called interactively, prompts for the face and color."
+  (interactive (read-face-and-attribute :background))
+  (set-face-attribute face frame :background (or color 'unspecified)))
+
+
+(defun set-face-foreground (face color &optional frame)
+  "Change the foreground color of face FACE to COLOR (a string).
+FRAME nil or not specified means change face on all frames.
+COLOR can be a system-defined color name (see `list-colors-display')
+or a hex spec of the form #RRGGBB.
+When called interactively, prompts for the face and color."
+  (interactive (read-face-and-attribute :foreground))
+  (set-face-attribute face frame :foreground (or color 'unspecified)))
+
+
+(defun set-face-stipple (face stipple &optional frame)
+  "Change the stipple pixmap of face FACE to STIPPLE.
+FRAME nil or not specified means change face on all frames.
+STIPPLE should be a string, the name of a file of pixmap data.
+The directories listed in the `x-bitmap-file-path' variable are searched.
+
+Alternatively, STIPPLE may be a list of the form (WIDTH HEIGHT DATA)
+where WIDTH and HEIGHT are the size in pixels,
+and DATA is a string, containing the raw bits of the bitmap."
+  (interactive (read-face-and-attribute :stipple))
+  (set-face-attribute face frame :stipple (or stipple 'unspecified)))
+
+
+(defun set-face-underline (face underline &optional frame)
+  "Specify whether face FACE is underlined.
+UNDERLINE nil means FACE explicitly doesn't underline.
+UNDERLINE t means FACE underlines with its foreground color.
+If UNDERLINE is a string, underline with that color.
+
+UNDERLINE may also be a list of the form (:color COLOR :style STYLE),
+where COLOR is a string or `foreground-color', and STYLE is either
+`line' or `wave'.  :color may be omitted, which means to use the
+foreground color.  :style may be omitted, which means to use a line.
+
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' to ``unspecify'' underlining."
+  (interactive (read-face-and-attribute :underline))
+  (set-face-attribute face frame :underline underline))
+
+(define-obsolete-function-alias 'set-face-underline-p
+                                'set-face-underline "24.3")
+
+
+(defun set-face-inverse-video (face inverse-video-p &optional frame)
+  "Specify whether face FACE is in inverse video.
+INVERSE-VIDEO-P non-nil means FACE displays explicitly in inverse video.
+INVERSE-VIDEO-P nil means FACE explicitly is not in inverse video.
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' to ``unspecify'' the inverse video attribute."
+  (interactive
+   (let ((list (read-face-and-attribute :inverse-video)))
+     (list (car list) (if (cadr list) t))))
+  (set-face-attribute face frame :inverse-video inverse-video-p))
+
+(define-obsolete-function-alias 'set-face-inverse-video-p
+                                'set-face-inverse-video "24.4")
+
+(defun set-face-bold (face bold-p &optional frame)
+  "Specify whether face FACE is bold.
+BOLD-P non-nil means FACE should explicitly display bold.
+BOLD-P nil means FACE should explicitly display non-bold.
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' or `modify-face' for finer control."
+  (if (null bold-p)
+      (make-face-unbold face frame)
+    (make-face-bold face frame)))
+
+(define-obsolete-function-alias 'set-face-bold-p 'set-face-bold "24.4")
+
+
+(defun set-face-italic (face italic-p &optional frame)
+  "Specify whether face FACE is italic.
+ITALIC-P non-nil means FACE should explicitly display italic.
+ITALIC-P nil means FACE should explicitly display non-italic.
+FRAME nil or not specified means change face on all frames.
+Use `set-face-attribute' or `modify-face' for finer control."
+  (if (null italic-p)
+      (make-face-unitalic face frame)
+    (make-face-italic face frame)))
+
+(define-obsolete-function-alias 'set-face-italic-p 'set-face-italic "24.4")
+
+
+(defalias 'set-face-background-pixmap 'set-face-stipple)
+
+
+(defun invert-face (face &optional frame)
+  "Swap the foreground and background colors of FACE.
+If FRAME is omitted or nil, it means change face on all frames.
+If FACE specifies neither foreground nor background color,
+set its foreground and background to the background and foreground
+of the default face.  Value is FACE."
+  (interactive (list (read-face-name "Invert face" (face-at-point t))))
+  (let ((fg (face-attribute face :foreground frame))
+       (bg (face-attribute face :background frame)))
+    (if (not (and (eq fg 'unspecified) (eq bg 'unspecified)))
+       (set-face-attribute face frame :foreground bg :background fg)
+      (set-face-attribute face frame
+                         :foreground
+                         (face-attribute 'default :background frame)
+                         :background
+                         (face-attribute 'default :foreground frame))))
+  face)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Interactively modifying faces.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar crm-separator) ; from crm.el
+
+(defun read-face-name (prompt &optional default multiple)
+  "Read one or more face names, prompting with PROMPT.
+PROMPT should not end in a space or a colon.
+
+Return DEFAULT if the user enters the empty string.
+If DEFAULT is non-nil, it should be a single face or a list of face names
+\(symbols or strings).  In the latter case, return the `car' of DEFAULT
+\(if MULTIPLE is nil, see below), or DEFAULT (if MULTIPLE is non-nil).
+
+If MULTIPLE is non-nil, this function uses `completing-read-multiple'
+to read multiple faces with \"[ \\t]*,[ \\t]*\" as the separator regexp
+and it returns a list of face names.  Otherwise, it reads and returns
+a single face name."
+  (if (and default (not (stringp default)))
+      (setq default
+            (cond ((symbolp default)
+                   (symbol-name default))
+                  (multiple
+                   (mapconcat (lambda (f) (if (symbolp f) (symbol-name f) f))
+                              default ", "))
+                  ;; If we only want one, and the default is more than one,
+                  ;; discard the unwanted ones.
+                  (t (symbol-name (car default))))))
+  (when (and default (not multiple))
+    (require 'crm)
+    ;; For compatibility with `completing-read-multiple' use `crm-separator'
+    ;; to define DEFAULT if MULTIPLE is nil.
+    (setq default (car (split-string default crm-separator t))))
+
+  (let ((prompt (if default
+                    (format "%s (default `%s'): " prompt default)
+                  (format "%s: " prompt)))
+        aliasfaces nonaliasfaces faces)
+    ;; Build up the completion tables.
+    (mapatoms (lambda (s)
+                (if (facep s)
+                    (if (get s 'face-alias)
+                        (push (symbol-name s) aliasfaces)
+                      (push (symbol-name s) nonaliasfaces)))))
+    (if multiple
+        (progn
+          (dolist (face (completing-read-multiple
+                         prompt
+                         (completion-table-in-turn nonaliasfaces aliasfaces)
+                         nil t nil 'face-name-history default))
+            ;; Ignore elements that are not faces
+            ;; (for example, because DEFAULT was "all faces")
+            (if (facep face) (push (intern face) faces)))
+          (nreverse faces))
+      (let ((face (completing-read
+                   prompt
+                   (completion-table-in-turn nonaliasfaces aliasfaces)
+                   nil t nil 'face-name-history default)))
+        (if (facep face) (intern face))))))
+
+;; Not defined without X, but behind window-system test.
+(defvar x-bitmap-file-path)
+
+(defun face-valid-attribute-values (attribute &optional frame)
+  "Return valid values for face attribute ATTRIBUTE.
+The optional argument FRAME is used to determine available fonts
+and colors.  If it is nil or not specified, the selected frame is used.
+Value is an alist of (NAME . VALUE) if ATTRIBUTE expects a value out
+of a set of discrete values.  Value is `integerp' if ATTRIBUTE expects
+an integer value."
+  (let ((valid
+         (pcase attribute
+           (`:family
+            (if (window-system frame)
+                (mapcar (lambda (x) (cons x x))
+                        (font-family-list))
+             ;; Only one font on TTYs.
+             (list (cons "default" "default"))))
+           (`:foundry
+           (list nil))
+          (`:width
+           (mapcar #'(lambda (x) (cons (symbol-name (aref x 1)) (aref x 1)))
+                   font-width-table))
+           (`:weight
+           (mapcar #'(lambda (x) (cons (symbol-name (aref x 1)) (aref x 1)))
+                   font-weight-table))
+          (`:slant
+           (mapcar #'(lambda (x) (cons (symbol-name (aref x 1)) (aref x 1)))
+                   font-slant-table))
+          (`:inverse-video
+           (mapcar #'(lambda (x) (cons (symbol-name x) x))
+                   (internal-lisp-face-attribute-values attribute)))
+           ((or `:underline `:overline `:strike-through `:box)
+            (if (window-system frame)
+                (nconc (mapcar #'(lambda (x) (cons (symbol-name x) x))
+                               (internal-lisp-face-attribute-values attribute))
+                       (mapcar #'(lambda (c) (cons c c))
+                               (defined-colors frame)))
+             (mapcar #'(lambda (x) (cons (symbol-name x) x))
+                     (internal-lisp-face-attribute-values attribute))))
+           ((or `:foreground `:background)
+            (mapcar #'(lambda (c) (cons c c))
+                    (defined-colors frame)))
+           (`:height
+            'integerp)
+           (`:stipple
+            (and (memq (window-system frame) '(x ns)) ; No stipple on w32
+                 (mapcar #'list
+                         (apply #'nconc
+                                (mapcar (lambda (dir)
+                                          (and (file-readable-p dir)
+                                               (file-directory-p dir)
+                                               (directory-files dir)))
+                                        x-bitmap-file-path)))))
+           (`:inherit
+            (cons '("none" . nil)
+                  (mapcar #'(lambda (c) (cons (symbol-name c) c))
+                          (face-list))))
+           (_
+            (error "Internal error")))))
+    (if (and (listp valid) (not (memq attribute '(:inherit))))
+       (nconc (list (cons "unspecified" 'unspecified)) valid)
+      valid)))
+
+
+(defconst face-attribute-name-alist
+  '((:family . "font family")
+    (:foundry . "font foundry")
+    (:width . "character set width")
+    (:height . "height in 1/10 pt")
+    (:weight . "weight")
+    (:slant . "slant")
+    (:underline . "underline")
+    (:overline . "overline")
+    (:strike-through . "strike-through")
+    (:box . "box")
+    (:inverse-video . "inverse-video display")
+    (:foreground . "foreground color")
+    (:background . "background color")
+    (:stipple . "background stipple")
+    (:inherit . "inheritance"))
+  "An alist of descriptive names for face attributes.
+Each element has the form (ATTRIBUTE-NAME . DESCRIPTION) where
+ATTRIBUTE-NAME is a face attribute name (a keyword symbol), and
+DESCRIPTION is a descriptive name for ATTRIBUTE-NAME.")
+
+
+(defun face-descriptive-attribute-name (attribute)
+  "Return a descriptive name for ATTRIBUTE."
+  (cdr (assq attribute face-attribute-name-alist)))
+
+
+(defun face-read-string (face default name &optional completion-alist)
+  "Interactively read a face attribute string value.
+FACE is the face whose attribute is read.  If non-nil, DEFAULT is the
+default string to return if no new value is entered.  NAME is a
+descriptive name of the attribute for prompting.  COMPLETION-ALIST is an
+alist of valid values, if non-nil.
+
+Entering nothing accepts the default string DEFAULT.
+Value is the new attribute value."
+  ;; Capitalize NAME (we don't use `capitalize' because that capitalizes
+  ;; each word in a string separately).
+  (setq name (concat (upcase (substring name 0 1)) (substring name 1)))
+  (let* ((completion-ignore-case t)
+        (value (completing-read
+                (if default
+                    (format "%s for face `%s' (default %s): "
+                            name face default)
+                  (format "%s for face `%s': " name face))
+                completion-alist nil nil nil nil default)))
+    (if (equal value "") default value)))
+
+
+(defun face-read-integer (face default name)
+  "Interactively read an integer face attribute value.
+FACE is the face whose attribute is read.  DEFAULT is the default
+value to return if no new value is entered.  NAME is a descriptive
+name of the attribute for prompting.  Value is the new attribute value."
+  (let ((new-value
+        (face-read-string face
+                          (format "%s" default)
+                          name
+                          (list (cons "unspecified" 'unspecified)))))
+    (cond ((equal new-value "unspecified")
+          'unspecified)
+         ((member new-value '("unspecified-fg" "unspecified-bg"))
+          new-value)
+         (t
+          (string-to-number new-value)))))
+
+
+;; FIXME this does allow you to enter the list forms of :box,
+;; :stipple, or :underline, because face-valid-attribute-values does
+;; not return those forms.
+(defun read-face-attribute (face attribute &optional frame)
+  "Interactively read a new value for FACE's ATTRIBUTE.
+Optional argument FRAME nil or unspecified means read an attribute value
+of a global face.  Value is the new attribute value."
+  (let* ((old-value (face-attribute face attribute frame))
+        (attribute-name (face-descriptive-attribute-name attribute))
+        (valid (face-valid-attribute-values attribute frame))
+        new-value)
+    ;; Represent complex attribute values as strings by printing them
+    ;; out.  Stipple can be a vector; (WIDTH HEIGHT DATA).  Box can be
+    ;; a list `(:width WIDTH :color COLOR)' or `(:width WIDTH :shadow
+    ;; SHADOW)'.  Underline can be `(:color COLOR :style STYLE)'.
+    (and (memq attribute '(:box :stipple :underline))
+        (or (consp old-value)
+            (vectorp old-value))
+        (setq old-value (prin1-to-string old-value)))
+    (cond ((listp valid)
+          (let ((default
+                  (or (car (rassoc old-value valid))
+                      (format "%s" old-value))))
+            (setq new-value
+                  (face-read-string face default attribute-name valid))
+            (if (equal new-value default)
+                ;; Nothing changed, so don't bother with all the stuff
+                ;; below.  In particular, this avoids a non-tty color
+                ;; from being canonicalized for a tty when the user
+                ;; just uses the default.
+                (setq new-value old-value)
+              ;; Terminal frames can support colors that don't appear
+              ;; explicitly in VALID, using color approximation code
+              ;; in tty-colors.el.
+              (when (and (memq attribute '(:foreground :background))
+                         (not (memq (window-system frame) '(x w32 ns)))
+                         (not (member new-value
+                                      '("unspecified"
+                                        "unspecified-fg" "unspecified-bg"))))
+                (setq new-value (car (tty-color-desc new-value frame))))
+              (when (assoc new-value valid)
+                (setq new-value (cdr (assoc new-value valid)))))))
+         ((eq valid 'integerp)
+          (setq new-value (face-read-integer face old-value attribute-name)))
+         (t (error "Internal error")))
+    ;; Convert stipple and box value text we read back to a list or
+    ;; vector if it looks like one.  This makes the assumption that a
+    ;; pixmap file name won't start with an open-paren.
+    (and (memq attribute '(:stipple :box :underline))
+        (stringp new-value)
+        (string-match-p "^[[(]" new-value)
+        (setq new-value (read new-value)))
+    new-value))
+
+(declare-function fontset-list "fontset.c" ())
+(declare-function x-list-fonts "xfaces.c"
+                 (pattern &optional face frame maximum width))
+
+(defun read-face-font (face &optional frame)
+  "Read the name of a font for FACE on FRAME.
+If optional argument FRAME is nil or omitted, use the selected frame."
+  (let ((completion-ignore-case t))
+    (completing-read (format "Set font attributes of face `%s' from font: " 
face)
+                    (append (fontset-list) (x-list-fonts "*" nil frame)))))
+
+
+(defun read-all-face-attributes (face &optional frame)
+  "Interactively read all attributes for FACE.
+If optional argument FRAME is nil or omitted, use the selected frame.
+Value is a property list of attribute names and new values."
+  (let (result)
+    (dolist (attribute face-attribute-name-alist result)
+      (setq result (cons (car attribute)
+                        (cons (read-face-attribute face (car attribute) frame)
+                              result))))))
+
+(defun modify-face (&optional face foreground background stipple
+                             bold-p italic-p underline inverse-p frame)
+  "Modify attributes of faces interactively.
+If optional argument FRAME is nil or omitted, modify the face used
+for newly created frame, i.e. the global face.
+For non-interactive use, `set-face-attribute' is preferred.
+When called from Lisp, if FACE is nil, all arguments but FRAME are ignored
+and the face and its settings are obtained by querying the user."
+  (interactive)
+  (if face
+      (set-face-attribute face frame
+                         :foreground (or foreground 'unspecified)
+                         :background (or background 'unspecified)
+                         :stipple stipple
+                         :weight (if bold-p 'bold 'normal)
+                         :slant (if italic-p 'italic 'normal)
+                         :underline underline
+                         :inverse-video inverse-p)
+    (setq face (read-face-name "Modify face" (face-at-point t)))
+    (apply #'set-face-attribute face frame
+          (read-all-face-attributes face frame))))
+
+(defun read-face-and-attribute (attribute &optional frame)
+  "Read face name and face attribute value.
+ATTRIBUTE is the attribute whose new value is read.
+FRAME nil or unspecified means read attribute value of global face.
+Value is a list (FACE NEW-VALUE) where FACE is the face read
+\(a symbol), and NEW-VALUE is value read."
+  (cond ((eq attribute :font)
+        (let* ((prompt "Set font-related attributes of face")
+               (face (read-face-name prompt (face-at-point t)))
+               (font (read-face-font face frame)))
+          (list face font)))
+       (t
+        (let* ((attribute-name (face-descriptive-attribute-name attribute))
+               (prompt (format "Set %s of face" attribute-name))
+               (face (read-face-name prompt (face-at-point t)))
+               (new-value (read-face-attribute face attribute frame)))
+          (list face new-value)))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Listing faces.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defconst list-faces-sample-text
+  "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+  "Text string to display as the sample text for `list-faces-display'.")
+
+
+;; The name list-faces would be more consistent, but let's avoid a
+;; conflict with Lucid, which uses that name differently.
+
+(defvar help-xref-stack)
+(defun list-faces-display (&optional regexp)
+  "List all faces, using the same sample text in each.
+The sample text is a string that comes from the variable
+`list-faces-sample-text'.
+
+If REGEXP is non-nil, list only those faces with names matching
+this regular expression.  When called interactively with a prefix
+argument, prompt for a regular expression using `read-regexp'."
+  (interactive (list (and current-prefix-arg
+                          (read-regexp "List faces matching regexp"))))
+  (let ((all-faces (zerop (length regexp)))
+       (frame (selected-frame))
+       (max-length 0)
+       faces line-format
+       disp-frame window face-name)
+    ;; We filter and take the max length in one pass
+    (setq faces
+         (delq nil
+               (mapcar (lambda (f)
+                         (let ((s (symbol-name f)))
+                           (when (or all-faces (string-match-p regexp s))
+                             (setq max-length (max (length s) max-length))
+                             f)))
+                       (sort (face-list) #'string-lessp))))
+    (unless faces
+      (error "No faces matching \"%s\"" regexp))
+    (setq max-length (1+ max-length)
+         line-format (format "%%-%ds" max-length))
+    (with-help-window "*Faces*"
+      (with-current-buffer standard-output
+       (setq truncate-lines t)
+       (insert
+        (substitute-command-keys
+         (concat
+          "\\<help-mode-map>Use "
+          (if (display-mouse-p) "\\[help-follow-mouse] or ")
+          "\\[help-follow] on a face name to customize it\n"
+          "or on its sample text for a description of the face.\n\n")))
+       (setq help-xref-stack nil)
+       (dolist (face faces)
+         (setq face-name (symbol-name face))
+         (insert (format line-format face-name))
+         ;; Hyperlink to a customization buffer for the face.  Using
+         ;; the help xref mechanism may not be the best way.
+         (save-excursion
+           (save-match-data
+             (search-backward face-name)
+             (setq help-xref-stack-item `(list-faces-display ,regexp))
+             (help-xref-button 0 'help-customize-face face)))
+         (let ((beg (point))
+               (line-beg (line-beginning-position)))
+           (insert list-faces-sample-text)
+           ;; Hyperlink to a help buffer for the face.
+           (save-excursion
+             (save-match-data
+               (search-backward list-faces-sample-text)
+               (help-xref-button 0 'help-face face)))
+           (insert "\n")
+           (put-text-property beg (1- (point)) 'face face)
+           ;; Make all face commands default to the proper face
+           ;; anywhere in the line.
+           (put-text-property line-beg (1- (point)) 'read-face-name face)
+           ;; If the sample text has multiple lines, line up all of them.
+           (goto-char beg)
+           (forward-line 1)
+           (while (not (eobp))
+             (insert-char ?\s max-length)
+             (forward-line 1))))
+       (goto-char (point-min))))
+    ;; If the *Faces* buffer appears in a different frame,
+    ;; copy all the face definitions from FRAME,
+    ;; so that the display will reflect the frame that was selected.
+    (setq window (get-buffer-window (get-buffer "*Faces*") t))
+    (setq disp-frame (if window (window-frame window)
+                      (car (frame-list))))
+    (or (eq frame disp-frame)
+       (dolist (face (face-list))
+         (copy-face face face frame disp-frame)))))
+
+
+(defun describe-face (face &optional frame)
+  "Display the properties of face FACE on FRAME.
+Interactively, FACE defaults to the faces of the character after point
+and FRAME defaults to the selected frame.
+
+If the optional argument FRAME is given, report on face FACE in that frame.
+If FRAME is t, report on the defaults for face FACE (for new frames).
+If FRAME is omitted or nil, use the selected frame."
+  (interactive (list (read-face-name "Describe face"
+                                     (or (face-at-point t) 'default)
+                                     t)))
+  (let* ((attrs '((:family . "Family")
+                 (:foundry . "Foundry")
+                 (:width . "Width")
+                 (:height . "Height")
+                 (:weight . "Weight")
+                 (:slant . "Slant")
+                 (:foreground . "Foreground")
+                 (:distant-foreground . "DistantForeground")
+                 (:background . "Background")
+                 (:underline . "Underline")
+                 (:overline . "Overline")
+                 (:strike-through . "Strike-through")
+                 (:box . "Box")
+                 (:inverse-video . "Inverse")
+                 (:stipple . "Stipple")
+                 (:font . "Font")
+                 (:fontset . "Fontset")
+                 (:inherit . "Inherit")))
+       (max-width (apply #'max (mapcar #'(lambda (x) (length (cdr x)))
+                                       attrs))))
+    (help-setup-xref (list #'describe-face face)
+                    (called-interactively-p 'interactive))
+    (unless face
+      (setq face 'default))
+    (if (not (listp face))
+       (setq face (list face)))
+    (with-help-window (help-buffer)
+      (with-current-buffer standard-output
+       (dolist (f face)
+         (if (stringp f) (setq f (intern f)))
+         ;; We may get called for anonymous faces (i.e., faces
+         ;; expressed using prop-value plists).  Those can't be
+         ;; usefully customized, so ignore them.
+         (when (symbolp f)
+           (insert "Face: " (symbol-name f))
+           (if (not (facep f))
+               (insert "   undefined face.\n")
+             (let ((customize-label "customize this face")
+                   file-name)
+               (insert (concat " (" (propertize "sample" 'font-lock-face f) 
")"))
+               (princ (concat " (" customize-label ")\n"))
+               ;; FIXME not sure how much of this belongs here, and
+               ;; how much in `face-documentation'.  The latter is
+               ;; not used much, but needs to return nil for
+               ;; undocumented faces.
+               (let ((alias (get f 'face-alias))
+                     (face f)
+                     obsolete)
+                 (when alias
+                   (setq face alias)
+                   (insert
+                    (format "\n  %s is an alias for the face `%s'.\n%s"
+                            f alias
+                            (if (setq obsolete (get f 'obsolete-face))
+                                (format "  This face is obsolete%s; use `%s' 
instead.\n"
+                                        (if (stringp obsolete)
+                                            (format " since %s" obsolete)
+                                          "")
+                                        alias)
+                              ""))))
+                 (insert "\nDocumentation:\n"
+                         (or (face-documentation face)
+                             "Not documented as a face.")
+                         "\n\n"))
+               (with-current-buffer standard-output
+                 (save-excursion
+                   (re-search-backward
+                    (concat "\\(" customize-label "\\)") nil t)
+                   (help-xref-button 1 'help-customize-face f)))
+               (setq file-name (find-lisp-object-file-name f 'defface))
+               (when file-name
+                 (princ "Defined in `")
+                 (princ (file-name-nondirectory file-name))
+                 (princ "'")
+                 ;; Make a hyperlink to the library.
+                 (save-excursion
+                   (re-search-backward "`\\([^`']+\\)'" nil t)
+                   (help-xref-button 1 'help-face-def f file-name))
+                 (princ ".")
+                 (terpri)
+                 (terpri))
+               (dolist (a attrs)
+                 (let ((attr (face-attribute f (car a) frame)))
+                   (insert (make-string (- max-width (length (cdr a))) ?\s)
+                           (cdr a) ": " (format "%s" attr))
+                   (if (and (eq (car a) :inherit)
+                            (not (eq attr 'unspecified)))
+                       ;; Make a hyperlink to the parent face.
+                       (save-excursion
+                         (re-search-backward ": \\([^:]+\\)" nil t)
+                         (help-xref-button 1 'help-face attr)))
+                   (insert "\n")))))
+           (terpri)))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Face specifications (defface).
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Parameter FRAME Is kept for call compatibility to with previous
+;; face implementation.
+
+(defun face-attr-construct (face &optional _frame)
+  "Return a `defface'-style attribute list for FACE.
+Value is a property list of pairs ATTRIBUTE VALUE for all specified
+face attributes of FACE where ATTRIBUTE is the attribute name and
+VALUE is the specified value of that attribute.
+Argument FRAME is ignored and retained for compatibility."
+  (let (result)
+    (dolist (entry face-attribute-name-alist result)
+      (let* ((attribute (car entry))
+            (value (face-attribute face attribute)))
+       (unless (eq value 'unspecified)
+         (setq result (nconc (list attribute value) result)))))))
+
+
+(defun face-spec-set-match-display (display frame)
+  "Non-nil if DISPLAY matches FRAME.
+DISPLAY is part of a spec such as can be used in `defface'.
+If FRAME is nil, the current FRAME is used."
+  (let* ((conjuncts display)
+        conjunct req options
+        ;; t means we have succeeded against all the conjuncts in
+        ;; DISPLAY that have been tested so far.
+        (match t))
+    (if (eq conjuncts t)
+       (setq conjuncts nil))
+    (while (and conjuncts match)
+      (setq conjunct (car conjuncts)
+           conjuncts (cdr conjuncts)
+           req (car conjunct)
+           options (cdr conjunct)
+           match (cond ((eq req 'type)
+                        (or (memq (window-system frame) options)
+                            (and (memq 'graphic options)
+                                 (memq (window-system frame) '(x w32 ns)))
+                            ;; FIXME: This should be revisited to use
+                            ;; display-graphic-p, provided that the
+                            ;; color selection depends on the number
+                            ;; of supported colors, and all defface's
+                            ;; are changed to look at number of colors
+                            ;; instead of (type graphic) etc.
+                            (if (null (window-system frame))
+                                (memq 'tty options)
+                              (or (and (memq 'motif options)
+                                       (featurep 'motif))
+                                  (and (memq 'gtk options)
+                                       (featurep 'gtk))
+                                  (and (memq 'lucid options)
+                                       (featurep 'x-toolkit)
+                                       (not (featurep 'motif))
+                                       (not (featurep 'gtk)))
+                                  (and (memq 'x-toolkit options)
+                                       (featurep 'x-toolkit))))))
+                       ((eq req 'min-colors)
+                        (>= (display-color-cells frame) (car options)))
+                       ((eq req 'class)
+                        (memq (frame-parameter frame 'display-type) options))
+                       ((eq req 'background)
+                        (memq (frame-parameter frame 'background-mode)
+                              options))
+                       ((eq req 'supports)
+                        (display-supports-face-attributes-p options frame))
+                       (t (error "Unknown req `%S' with options `%S'"
+                                 req options)))))
+    match))
+
+
+(defun face-spec-choose (spec &optional frame no-match-retval)
+  "Return the proper attributes for FRAME, out of SPEC.
+
+If no match is found or SPEC is nil, return nil, unless NO-MATCH-RETVAL
+is given, in which case return its value instead."
+  (unless frame
+    (setq frame (selected-frame)))
+  (let ((tail spec)
+       result defaults match-found)
+    (while tail
+      (let* ((entry (pop tail))
+            (display (car entry))
+            (attrs (cdr entry))
+            thisval)
+       ;; Get the attributes as actually specified by this alternative.
+       (setq thisval
+             (if (null (cdr attrs)) ;; was (listp (car attrs))
+                 ;; Old-style entry, the attribute list is the
+                 ;; first element.
+                 (car attrs)
+               attrs))
+
+       ;; If the condition is `default', that sets the default
+       ;; for following conditions.
+       (if (eq display 'default)
+           (setq defaults thisval)
+         ;; Otherwise, if it matches, use it.
+         (when (face-spec-set-match-display display frame)
+           (setq result thisval
+                 tail nil
+                 match-found t)))))
+    ;; If defaults have been found, it's safe to just append those to the 
result
+    ;; list (which at this point will be either nil or contain actual specs) 
and
+    ;; return it to the caller. Since there will most definitely be something 
to
+    ;; return in this case, there's no need to know/check if a match was found.
+    (if defaults
+       (append result defaults)
+      (if match-found
+         result
+       no-match-retval))))
+
+
+(defun face-spec-reset-face (face &optional frame)
+  "Reset all attributes of FACE on FRAME to unspecified."
+  (apply 'set-face-attribute face frame
+        (if (eq face 'default)
+            ;; For the default face, avoid making any attribute
+            ;; unspecified.  Instead, set attributes to default values
+            ;; (see also realize_default_face in xfaces.c).
+            (append
+             '(:underline nil :overline nil :strike-through nil
+               :box nil :inverse-video nil :stipple nil :inherit nil)
+             ;; `display-graphic-p' is unavailable when running
+             ;; temacs, prior to loading frame.el.
+             (when (fboundp 'display-graphic-p)
+               (unless (display-graphic-p frame)
+                 `(:family "default" :foundry "default" :width normal
+                   :height 1 :weight normal :slant normal
+                   :foreground ,(if (frame-parameter nil 'reverse)
+                                    "unspecified-bg"
+                                  "unspecified-fg")
+                   :background ,(if (frame-parameter nil 'reverse)
+                                    "unspecified-fg"
+                                  "unspecified-bg")))))
+          ;; For all other faces, unspecify all attributes.
+          (apply 'append
+                 (mapcar (lambda (x) (list (car x) 'unspecified))
+                         face-attribute-name-alist)))))
+
+(defun face-spec-set (face spec &optional spec-type)
+  "Set the face spec SPEC for FACE.
+See `defface' for the format of SPEC.
+
+The appearance of each face is controlled by its specs (set via
+this function), and by the internal frame-specific face
+attributes (set via `set-face-attribute').
+
+This function also defines FACE as a valid face name if it is not
+already one, and (re)calculates its attributes on existing
+frames.
+
+The argument SPEC-TYPE determines which spec to set:
+  nil or `face-override-spec' means the override spec (which is
+    usually what you want if calling this function outside of
+    Custom code);
+  `customized-face' or `saved-face' means the customized spec or
+    the saved custom spec;
+  `face-defface-spec' means the default spec
+    (usually set only via `defface');
+  `reset' means to ignore SPEC, but clear the `customized-face'
+    and `face-override-spec' specs;
+Any other value means not to set any spec, but to run the
+function for its other effects."
+  (if (get face 'face-alias)
+      (setq face (get face 'face-alias)))
+  ;; Save SPEC to the relevant symbol property.
+  (unless spec-type
+    (setq spec-type 'face-override-spec))
+  (if (memq spec-type '(face-defface-spec face-override-spec
+                       customized-face saved-face))
+      (put face spec-type spec))
+  (if (memq spec-type '(reset saved-face))
+      (put face 'customized-face nil))
+  ;; Setting the face spec via Custom empties out any override spec,
+  ;; similar to how setting a variable via Custom changes its values.
+  (if (memq spec-type '(customized-face saved-face reset))
+      (put face 'face-override-spec nil))
+  ;; If we reset the face based on its custom spec, it is unmodified
+  ;; as far as Custom is concerned.
+  (unless (eq face 'face-override-spec)
+    (put face 'face-modified nil))
+  ;; Initialize the face if it does not exist, then recalculate.
+  (make-empty-face face)
+  (dolist (frame (frame-list))
+    (face-spec-recalc face frame)))
+
+(defun face-spec-recalc (face frame)
+  "Reset the face attributes of FACE on FRAME according to its specs.
+The following sources are applied in this order:
+
+  face reset to default values if it's the default face, otherwise set
+  to unspecified (through `face-spec-reset-face')
+   |
+  (theme and user customization)
+    or: if none of the above exist, and none match the current frame or
+        inherited from the defface spec instead of overwriting it
+        entirely, the following is applied instead:
+  (defface default spec)
+  (X resources (if applicable))
+   |
+  defface override spec"
+  (while (get face 'face-alias)
+    (setq face (get face 'face-alias)))
+  (face-spec-reset-face face frame)
+  ;; If FACE is customized or themed, set the custom spec from
+  ;; `theme-face' records.
+  (let ((theme-faces (get face 'theme-face))
+       (no-match-found 0)
+       spec theme-face-applied)
+    (if theme-faces
+       (dolist (elt (reverse theme-faces))
+         (setq spec (face-spec-choose (cadr elt) frame no-match-found))
+         (unless (eq spec no-match-found)
+           (face-spec-set-2 face frame spec)
+           (setq theme-face-applied t))))
+    ;; If there was a spec applicable to FRAME, that overrides the
+    ;; defface spec entirely (rather than inheriting from it).  If
+    ;; there was no spec applicable to FRAME, apply the defface spec
+    ;; as well as any applicable X resources.
+    (unless theme-face-applied
+      (setq spec (face-spec-choose (face-default-spec face) frame))
+      (face-spec-set-2 face frame spec)
+      (make-face-x-resource-internal face frame))
+    (setq spec (face-spec-choose (get face 'face-override-spec) frame))
+    (face-spec-set-2 face frame spec)))
+
+(defun face-spec-set-2 (face frame spec)
+  "Set the face attributes of FACE on FRAME according to SPEC."
+  (let (attrs)
+    (while spec
+      (when (assq (car spec) face-x-resources)
+       (push (car spec) attrs)
+       (push (cadr spec) attrs))
+      (setq spec (cddr spec)))
+    (apply 'set-face-attribute face frame (nreverse attrs))))
+
+(defun face-attr-match-p (face attrs &optional frame)
+  "Return t if attributes of FACE match values in plist ATTRS.
+Optional parameter FRAME is the frame whose definition of FACE
+is used.  If nil or omitted, use the selected frame."
+  (unless frame
+    (setq frame (selected-frame)))
+  (let* ((list face-attribute-name-alist)
+        (match t)
+        (bold (and (plist-member attrs :bold)
+                   (not (plist-member attrs :weight))))
+        (italic (and (plist-member attrs :italic)
+                     (not (plist-member attrs :slant))))
+        (plist (if (or bold italic)
+                   (copy-sequence attrs)
+                 attrs)))
+    ;; Handle the Emacs 20 :bold and :italic properties.
+    (if bold
+       (plist-put plist :weight (if bold 'bold 'normal)))
+    (if italic
+       (plist-put plist :slant (if italic 'italic 'normal)))
+    (while (and match list)
+      (let* ((attr (caar list))
+            (specified-value
+             (if (plist-member plist attr)
+                 (plist-get plist attr)
+               'unspecified))
+            (value-now (face-attribute face attr frame)))
+       (setq match (equal specified-value value-now))
+       (setq list (cdr list))))
+    match))
+
+(defsubst face-spec-match-p (face spec &optional frame)
+  "Return t if FACE, on FRAME, matches what SPEC says it should look like."
+  (face-attr-match-p face (face-spec-choose spec frame) frame))
+
+(defsubst face-default-spec (face)
+  "Return the default face-spec for FACE, ignoring any user customization.
+If there is no default for FACE, return nil."
+  (get face 'face-defface-spec))
+
+(defsubst face-user-default-spec (face)
+  "Return the user's customized face-spec for FACE, or the default if none.
+If there is neither a user setting nor a default for FACE, return nil."
+  (or (get face 'customized-face)
+      (get face 'saved-face)
+      (face-default-spec face)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Frame-type independent color support.
+;;; We keep the old x-* names as aliases for back-compatibility.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun defined-colors (&optional frame)
+  "Return a list of colors supported for a particular frame.
+The argument FRAME specifies which frame to try.
+The value may be different for frames on different display types.
+If FRAME doesn't support colors, the value is nil.
+If FRAME is nil, that stands for the selected frame."
+  (if (memq (framep (or frame (selected-frame))) '(x w32 ns))
+      (xw-defined-colors frame)
+    (mapcar 'car (tty-color-alist frame))))
+(defalias 'x-defined-colors 'defined-colors)
+
+(declare-function xw-color-defined-p "xfns.c" (color &optional frame))
+
+(defun color-defined-p (color &optional frame)
+  "Return non-nil if COLOR is supported on frame FRAME.
+COLOR should be a string naming a color (e.g. \"white\"), or a
+string specifying a color's RGB components (e.g. \"#ff12ec\"), or
+the symbol `unspecified'.
+
+This function returns nil if COLOR is the symbol `unspecified',
+or one of the strings \"unspecified-fg\" or \"unspecified-bg\".
+
+If FRAME is omitted or nil, use the selected frame."
+  (unless (member color '(unspecified "unspecified-bg" "unspecified-fg"))
+    (if (member (framep (or frame (selected-frame))) '(x w32 ns))
+       (xw-color-defined-p color frame)
+      (numberp (tty-color-translate color frame)))))
+(defalias 'x-color-defined-p 'color-defined-p)
+
+(declare-function xw-color-values "xfns.c" (color &optional frame))
+
+(defun color-values (color &optional frame)
+  "Return a description of the color named COLOR on frame FRAME.
+COLOR should be a string naming a color (e.g. \"white\"), or a
+string specifying a color's RGB components (e.g. \"#ff12ec\").
+
+Return a list of three integers, (RED GREEN BLUE), each between 0
+and either 65280 or 65535 (the maximum depends on the system).
+Use `color-name-to-rgb' if you want RGB floating-point values
+normalized to 1.0.
+
+If FRAME is omitted or nil, use the selected frame.
+If FRAME cannot display COLOR, the value is nil.
+
+COLOR can also be the symbol `unspecified' or one of the strings
+\"unspecified-fg\" or \"unspecified-bg\", in which case the
+return value is nil."
+  (cond
+   ((member color '(unspecified "unspecified-fg" "unspecified-bg"))
+    nil)
+   ((memq (framep (or frame (selected-frame))) '(x w32 ns))
+    (xw-color-values color frame))
+   (t
+    (tty-color-values color frame))))
+
+(defalias 'x-color-values 'color-values)
+
+(declare-function xw-display-color-p "xfns.c" (&optional terminal))
+
+(defun display-color-p (&optional display)
+  "Return t if DISPLAY supports color.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display."
+  (if (memq (framep-on-display display) '(x w32 ns))
+      (xw-display-color-p display)
+    (tty-display-color-p display)))
+(defalias 'x-display-color-p 'display-color-p)
+
+(declare-function x-display-grayscale-p "xfns.c" (&optional terminal))
+
+(defun display-grayscale-p (&optional display)
+  "Return non-nil if frames on DISPLAY can display shades of gray.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display."
+  (let ((frame-type (framep-on-display display)))
+    (cond
+     ((memq frame-type '(x w32 ns))
+      (x-display-grayscale-p display))
+     (t
+      (> (tty-color-gray-shades display) 2)))))
+
+(defun read-color (&optional prompt convert-to-RGB allow-empty-name msg)
+  "Read a color name or RGB triplet.
+Completion is available for color names, but not for RGB triplets.
+
+RGB triplets have the form \"#RRGGBB\".  Each of the R, G, and B
+components can have one to four digits, but all three components
+must have the same number of digits.  Each digit is a hex value
+between 0 and F; either upper case or lower case for A through F
+are acceptable.
+
+In addition to standard color names and RGB hex values, the
+following are available as color candidates.  In each case, the
+corresponding color is used.
+
+ * `foreground at point'   - foreground under the cursor
+ * `background at point'   - background under the cursor
+
+Optional arg PROMPT is the prompt; if nil, use a default prompt.
+
+Interactively, or with optional arg CONVERT-TO-RGB-P non-nil,
+convert an input color name to an RGB hex string.  Return the RGB
+hex string.
+
+If optional arg ALLOW-EMPTY-NAME is non-nil, the user is allowed
+to enter an empty color name (the empty string).
+
+Interactively, or with optional arg MSG non-nil, print the
+resulting color name in the echo area."
+  (interactive "i\np\ni\np")    ; Always convert to RGB interactively.
+  (let* ((completion-ignore-case t)
+        (colors (or facemenu-color-alist
+                    (append '("foreground at point" "background at point")
+                            (if allow-empty-name '(""))
+                            (defined-colors))))
+        (color (completing-read
+                (or prompt "Color (name or #RGB triplet): ")
+                ;; Completing function for reading colors, accepting
+                ;; both color names and RGB triplets.
+                (lambda (string pred flag)
+                  (cond
+                   ((null flag) ; Try completion.
+                    (or (try-completion string colors pred)
+                        (if (color-defined-p string)
+                            string)))
+                   ((eq flag t) ; List all completions.
+                    (or (all-completions string colors pred)
+                        (if (color-defined-p string)
+                            (list string))))
+                   ((eq flag 'lambda) ; Test completion.
+                    (or (member string colors)
+                        (color-defined-p string)))))
+                nil t)))
+
+    ;; Process named colors.
+    (when (member color colors)
+      (cond ((string-equal color "foreground at point")
+            (setq color (foreground-color-at-point)))
+           ((string-equal color "background at point")
+            (setq color (background-color-at-point))))
+      (when (and convert-to-RGB
+                (not (string-equal color "")))
+       (let ((components (x-color-values color)))
+         (unless (string-match-p 
"^#\\(?:[a-fA-F0-9][a-fA-F0-9][a-fA-F0-9]\\)+$" color)
+           (setq color (format "#%04X%04X%04X"
+                               (logand 65535 (nth 0 components))
+                               (logand 65535 (nth 1 components))
+                               (logand 65535 (nth 2 components))))))))
+    (when msg (message "Color: `%s'" color))
+    color))
+
+(defun face-at-point (&optional thing multiple)
+  "Return the face of the character after point.
+If it has more than one face, return the first one.
+If THING is non-nil try first to get a face name from the buffer.
+IF MULTIPLE is non-nil, return a list of all faces.
+Return nil if there is no face."
+  (let (faces)
+    (if thing
+        ;; Try to get a face name from the buffer.
+        (let ((face (intern-soft (thing-at-point 'symbol))))
+          (if (facep face)
+              (push face faces))))
+    ;; Add the named faces that the `read-face-name' or `face' property uses.
+    (let ((faceprop (or (get-char-property (point) 'read-face-name)
+                        (get-char-property (point) 'face))))
+      (cond ((facep faceprop)
+             (push faceprop faces))
+            ((and (listp faceprop)
+                  ;; Don't treat an attribute spec as a list of faces.
+                  (not (keywordp (car faceprop)))
+                  (not (memq (car faceprop)
+                             '(foreground-color background-color))))
+             (dolist (face faceprop)
+               (if (facep face)
+                   (push face faces))))))
+    (setq faces (delete-dups (nreverse faces)))
+    (if multiple faces (car faces))))
+
+(defun foreground-color-at-point ()
+  "Return the foreground color of the character after point."
+  ;; `face-at-point' alone is not sufficient.  It only gets named faces.
+  ;; Need also pick up any face properties that are not associated with named 
faces.
+  (let ((face (or (face-at-point)
+                 (get-char-property (point) 'read-face-name)
+                 (get-char-property (point) 'face))))
+    (cond ((and face (symbolp face))
+          (let ((value (face-foreground face nil 'default)))
+            (if (member value '("unspecified-fg" "unspecified-bg"))
+                nil
+              value)))
+         ((consp face)
+          (cond ((memq 'foreground-color face) (cdr (memq 'foreground-color 
face)))
+                ((memq ':foreground face) (cadr (memq ':foreground face)))))
+         (t nil))))                    ; Invalid face value.
+
+(defun background-color-at-point ()
+  "Return the background color of the character after point."
+  ;; `face-at-point' alone is not sufficient.  It only gets named faces.
+  ;; Need also pick up any face properties that are not associated with named 
faces.
+  (let ((face (or (face-at-point)
+                 (get-char-property (point) 'read-face-name)
+                 (get-char-property (point) 'face))))
+    (cond ((and face (symbolp face))
+          (let ((value (face-background face nil 'default)))
+            (if (member value '("unspecified-fg" "unspecified-bg"))
+                nil
+              value)))
+         ((consp face)
+          (cond ((memq 'background-color face) (cdr (memq 'background-color 
face)))
+                ((memq ':background face) (cadr (memq ':background face)))))
+         (t nil))))                    ; Invalid face value.
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Frame creation.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(declare-function x-display-list "xfns.c" ())
+(declare-function x-open-connection "xfns.c"
+                 (display &optional xrm-string must-succeed))
+(declare-function x-get-resource "frame.c"
+                 (attribute class &optional component subclass))
+(declare-function x-parse-geometry "frame.c" (string))
+(defvar x-display-name)
+
+(defun x-handle-named-frame-geometry (parameters)
+  "Add geometry parameters for a named frame to parameter list PARAMETERS.
+Value is the new parameter list."
+  ;; Note that `x-resource-name' has a global meaning.
+  (let ((x-resource-name (cdr (assq 'name parameters))))
+    (when x-resource-name
+      ;; Before checking X resources, we must have an X connection.
+      (or (window-system)
+         (x-display-list)
+         (x-open-connection (or (cdr (assq 'display parameters))
+                                x-display-name)))
+      (let (res-geometry parsed)
+       (and (setq res-geometry (x-get-resource "geometry" "Geometry"))
+            (setq parsed (x-parse-geometry res-geometry))
+            (setq parameters
+                  (append parameters parsed
+                          ;; If the resource specifies a position,
+                          ;; take note of that.
+                          (if (or (assq 'top parsed) (assq 'left parsed))
+                              '((user-position . t) (user-size . t)))))))))
+  parameters)
+
+
+(defun x-handle-reverse-video (frame parameters)
+  "Handle the reverse-video frame parameter and X resource.
+`x-create-frame' does not handle this one."
+  (when (cdr (or (assq 'reverse parameters)
+                (let ((resource (x-get-resource "reverseVideo"
+                                                "ReverseVideo")))
+                  (if resource
+                      (cons nil (member (downcase resource)
+                                        '("on" "true")))))))
+      (let* ((params (frame-parameters frame))
+            (bg (cdr (assq 'foreground-color params)))
+            (fg (cdr (assq 'background-color params))))
+       (modify-frame-parameters frame
+                                (list (cons 'foreground-color fg)
+                                      (cons 'background-color bg)))
+       (if (equal bg (cdr (assq 'border-color params)))
+           (modify-frame-parameters frame
+                                    (list (cons 'border-color fg))))
+       (if (equal bg (cdr (assq 'mouse-color params)))
+           (modify-frame-parameters frame
+                                    (list (cons 'mouse-color fg))))
+       (if (equal bg (cdr (assq 'cursor-color params)))
+           (modify-frame-parameters frame
+                                    (list (cons 'cursor-color fg)))))))
+
+(declare-function x-create-frame "xfns.c" (parms))
+(declare-function x-setup-function-keys "term/common-win" (frame))
+
+(defun x-create-frame-with-faces (&optional parameters)
+  "Create and return a frame with frame parameters PARAMETERS.
+If PARAMETERS specify a frame name, handle X geometry resources
+for that name.  If PARAMETERS includes a `reverse' parameter, or
+the X resource ``reverseVideo'' is present, handle that."
+  (setq parameters (x-handle-named-frame-geometry parameters))
+  (let* ((params (copy-tree parameters))
+        (visibility-spec (assq 'visibility parameters))
+        (delayed-params '(foreground-color background-color font
+                          border-color cursor-color mouse-color
+                          visibility scroll-bar-foreground
+                          scroll-bar-background))
+        frame success)
+    (dolist (param delayed-params)
+      (setq params (assq-delete-all param params)))
+    (setq frame (x-create-frame `((visibility . nil) . ,params)))
+    (unwind-protect
+       (progn
+         (x-setup-function-keys frame)
+         (x-handle-reverse-video frame parameters)
+         (frame-set-background-mode frame t)
+         (face-set-after-frame-default frame parameters)
+         (if (null visibility-spec)
+             (make-frame-visible frame)
+           (modify-frame-parameters frame (list visibility-spec)))
+         (setq success t))
+      (unless success
+       (delete-frame frame)))
+    frame))
+
+(defun face-set-after-frame-default (frame &optional parameters)
+  "Initialize the frame-local faces of FRAME.
+Calculate the face definitions using the face specs, custom theme
+settings, X resources, and `face-new-frame-defaults'.
+Finally, apply any relevant face attributes found amongst the
+frame parameters in PARAMETERS."
+  (let ((window-system-p (memq (window-system frame) '(x w32))))
+    ;; The `reverse' is so that `default' goes first.
+    (dolist (face (nreverse (face-list)))
+      (condition-case ()
+         (progn
+           ;; Initialize faces from face spec and custom theme.
+           (face-spec-recalc face frame)
+           ;; Apply attributes specified by face-new-frame-defaults
+           (internal-merge-in-global-face face frame))
+       ;; Don't let invalid specs prevent frame creation.
+       (error nil))))
+
+  ;; Apply attributes specified by frame parameters.
+  (let ((face-params '((foreground-color default :foreground)
+                      (background-color default :background)
+                       (font default :font)
+                      (border-color border :background)
+                      (cursor-color cursor :background)
+                      (scroll-bar-foreground scroll-bar :foreground)
+                      (scroll-bar-background scroll-bar :background)
+                      (mouse-color mouse :background))))
+    (dolist (param face-params)
+      (let* ((param-name (nth 0 param))
+            (value (cdr (assq param-name parameters))))
+       (if value
+           (set-face-attribute (nth 1 param) frame
+                               (nth 2 param) value))))))
+
+(defun tty-handle-reverse-video (frame parameters)
+  "Handle the reverse-video frame parameter for terminal frames."
+  (when (cdr (assq 'reverse parameters))
+    (let* ((params (frame-parameters frame))
+          (bg (cdr (assq 'foreground-color params)))
+          (fg (cdr (assq 'background-color params))))
+      (modify-frame-parameters frame
+                              (list (cons 'foreground-color fg)
+                                    (cons 'background-color bg)))
+      (if (equal bg (cdr (assq 'mouse-color params)))
+         (modify-frame-parameters frame
+                                  (list (cons 'mouse-color fg))))
+      (if (equal bg (cdr (assq 'cursor-color params)))
+         (modify-frame-parameters frame
+                                  (list (cons 'cursor-color fg)))))))
+
+
+(defun tty-create-frame-with-faces (&optional parameters)
+  "Create and return a frame from optional frame parameters PARAMETERS.
+If PARAMETERS contains a `reverse' parameter, handle that."
+  (let ((frame (make-terminal-frame parameters))
+       success)
+    (unwind-protect
+       (with-selected-frame frame
+         (tty-handle-reverse-video frame (frame-parameters frame))
+
+          (unless (terminal-parameter frame 'terminal-initted)
+            (set-terminal-parameter frame 'terminal-initted t)
+            (set-locale-environment nil frame)
+            (tty-run-terminal-initialization frame nil t))
+         (frame-set-background-mode frame t)
+         (face-set-after-frame-default frame parameters)
+         (setq success t))
+      (unless success
+       (delete-frame frame)))
+    frame))
+
+(defun tty-find-type (pred type)
+  "Return the longest prefix of TYPE to which PRED returns non-nil.
+TYPE should be a tty type name such as \"xterm-16color\".
+
+The function tries only those prefixes that are followed by a
+dash or underscore in the original type name, like \"xterm\" in
+the above example."
+  (let (hyphend)
+    (while (and type
+               (not (funcall pred type)))
+      ;; Strip off last hyphen and what follows, then try again
+      (setq type
+           (if (setq hyphend (string-match-p "[-_][^-_]+$" type))
+               (substring type 0 hyphend)
+             nil))))
+  type)
+
+(defvar tty-setup-hook nil
+  "Hook run after running the initialization function of a new text terminal.
+Specifically, `tty-run-terminal-initialization' runs this.
+This can be used to fine tune the `input-decode-map', for example.")
+
+(defun tty-run-terminal-initialization (frame &optional type run-hook)
+  "Run the special initialization code for the terminal type of FRAME.
+The optional TYPE parameter may be used to override the autodetected
+terminal type to a different value.
+
+If optional argument RUN-HOOK is non-nil, then as a final step,
+this runs the hook `tty-setup-hook'.
+
+If you set `term-file-prefix' to nil, this function does nothing."
+  (setq type (or type (tty-type frame)))
+  ;; Load library for our terminal type.
+  ;; User init file can set term-file-prefix to nil to prevent this.
+  (with-selected-frame frame
+    (unless (null term-file-prefix)
+      (let* (term-init-func)
+       ;; First, load the terminal initialization file, if it is
+       ;; available and it hasn't been loaded already.
+       (tty-find-type #'(lambda (type)
+                          (let ((file (locate-library (concat term-file-prefix 
type))))
+                            (and file
+                                 (or (assoc file load-history)
+                                     (load file t t)))))
+                      type)
+       ;; Next, try to find a matching initialization function, and call it.
+       (tty-find-type #'(lambda (type)
+                          (fboundp (setq term-init-func
+                                         (intern (concat "terminal-init-" 
type)))))
+                      type)
+       (when (fboundp term-init-func)
+         (funcall term-init-func))
+       (set-terminal-parameter frame 'terminal-initted term-init-func)
+       (if run-hook (run-hooks 'tty-setup-hook))))))
+
+;; Called from C function init_display to initialize faces of the
+;; dumped terminal frame on startup.
+
+(defun tty-set-up-initial-frame-faces ()
+  (let ((frame (selected-frame)))
+    (frame-set-background-mode frame t)
+    (face-set-after-frame-default frame)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Standard faces.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defgroup basic-faces nil
+  "The standard faces of Emacs."
+  :group 'faces)
+
+(defface default
+  '((t nil)) ; If this were nil, face-defface-spec would not be set.
+  "Basic default face."
+  :group 'basic-faces)
+
+(defface bold
+  '((t :weight bold))
+  "Basic bold face."
+  :group 'basic-faces)
+
+(defface italic
+  '((((supports :slant italic))
+     :slant italic)
+    (((supports :underline t))
+     :underline t)
+    (t
+     ;; Default to italic, even if it doesn't appear to be supported,
+     ;; because in some cases the display engine will do its own
+     ;; workaround (to `dim' on ttys).
+     :slant italic))
+  "Basic italic face."
+  :group 'basic-faces)
+
+(defface bold-italic
+  '((t :weight bold :slant italic))
+  "Basic bold-italic face."
+  :group 'basic-faces)
+
+(defface underline
+  '((((supports :underline t))
+     :underline t)
+    (((supports :weight bold))
+     :weight bold)
+    (t :underline t))
+  "Basic underlined face."
+  :group 'basic-faces)
+
+(defface fixed-pitch
+  '((t :family "Monospace"))
+  "The basic fixed-pitch face."
+  :group 'basic-faces)
+
+(defface variable-pitch
+  '((t :family "Sans Serif"))
+  "The basic variable-pitch face."
+  :group 'basic-faces)
+
+(defface shadow
+  '((((class color grayscale) (min-colors 88) (background light))
+     :foreground "grey50")
+    (((class color grayscale) (min-colors 88) (background dark))
+     :foreground "grey70")
+    (((class color) (min-colors 8) (background light))
+     :foreground "green")
+    (((class color) (min-colors 8) (background dark))
+     :foreground "yellow"))
+  "Basic face for shadowed text."
+  :group 'basic-faces
+  :version "22.1")
+
+(defface link
+  '((((class color) (min-colors 88) (background light))
+     :foreground "RoyalBlue3" :underline t)
+    (((class color) (background light))
+     :foreground "blue" :underline t)
+    (((class color) (min-colors 88) (background dark))
+     :foreground "cyan1" :underline t)
+    (((class color) (background dark))
+     :foreground "cyan" :underline t)
+    (t :inherit underline))
+  "Basic face for unvisited links."
+  :group 'basic-faces
+  :version "22.1")
+
+(defface link-visited
+  '((default :inherit link)
+    (((class color) (background light)) :foreground "magenta4")
+    (((class color) (background dark)) :foreground "violet"))
+  "Basic face for visited links."
+  :group 'basic-faces
+  :version "22.1")
+
+(defface highlight
+  '((((class color) (min-colors 88) (background light))
+     :background "darkseagreen2")
+    (((class color) (min-colors 88) (background dark))
+     :background "darkolivegreen")
+    (((class color) (min-colors 16) (background light))
+     :background "darkseagreen2")
+    (((class color) (min-colors 16) (background dark))
+     :background "darkolivegreen")
+    (((class color) (min-colors 8))
+     :background "green" :foreground "black")
+    (t :inverse-video t))
+  "Basic face for highlighting."
+  :group 'basic-faces)
+
+;; Region face: under NS, default to the system-defined selection
+;; color (optimized for the fixed white background of other apps),
+;; if background is light.
+(defface region
+  '((((class color) (min-colors 88) (background dark))
+     :background "blue3")
+    (((class color) (min-colors 88) (background light) (type gtk))
+     :distant-foreground "gtk_selection_fg_color"
+     :background "gtk_selection_bg_color")
+    (((class color) (min-colors 88) (background light) (type ns))
+     :distant-foreground "ns_selection_fg_color"
+     :background "ns_selection_bg_color")
+    (((class color) (min-colors 88) (background light))
+     :background "lightgoldenrod2")
+    (((class color) (min-colors 16) (background dark))
+     :background "blue3")
+    (((class color) (min-colors 16) (background light))
+     :background "lightgoldenrod2")
+    (((class color) (min-colors 8))
+     :background "blue" :foreground "white")
+    (((type tty) (class mono))
+     :inverse-video t)
+    (t :background "gray"))
+  "Basic face for highlighting the region."
+  :version "21.1"
+  :group 'basic-faces)
+
+(defface secondary-selection
+  '((((class color) (min-colors 88) (background light))
+     :background "yellow1")
+    (((class color) (min-colors 88) (background dark))
+     :background "SkyBlue4")
+    (((class color) (min-colors 16) (background light))
+     :background "yellow")
+    (((class color) (min-colors 16) (background dark))
+     :background "SkyBlue4")
+    (((class color) (min-colors 8))
+     :background "cyan" :foreground "black")
+    (t :inverse-video t))
+  "Basic face for displaying the secondary selection."
+  :group 'basic-faces)
+
+(defface trailing-whitespace
+  '((((class color) (background light))
+     :background "red1")
+    (((class color) (background dark))
+     :background "red1")
+    (t :inverse-video t))
+  "Basic face for highlighting trailing whitespace."
+  :version "21.1"
+  :group 'basic-faces)
+
+(defface escape-glyph
+  '((((background dark)) :foreground "cyan")
+    ;; See the comment in minibuffer-prompt for
+    ;; the reason not to use blue on MS-DOS.
+    (((type pc)) :foreground "magenta")
+    ;; red4 is too dark, but some say blue is too loud.
+    ;; brown seems to work ok. -- rms.
+    (t :foreground "brown"))
+  "Face for characters displayed as sequences using `^' or `\\'."
+  :group 'basic-faces
+  :version "22.1")
+
+(defface nobreak-space
+  '((((class color) (min-colors 88)) :inherit escape-glyph :underline t)
+    (((class color) (min-colors 8)) :background "magenta")
+    (t :inverse-video t))
+  "Face for displaying nobreak space."
+  :group 'basic-faces
+  :version "22.1")
+
+(defgroup mode-line-faces nil
+  "Faces used in the mode line."
+  :group 'mode-line
+  :group 'faces
+  :version "22.1")
+
+(defface mode-line
+  '((((class color) (min-colors 88))
+     :box (:line-width -1 :style released-button)
+     :background "grey75" :foreground "black")
+    (t
+     :inverse-video t))
+  "Basic mode line face for selected window."
+  :version "21.1"
+  :group 'mode-line-faces
+  :group 'basic-faces)
+
+(defface mode-line-inactive
+  '((default
+     :inherit mode-line)
+    (((class color) (min-colors 88) (background light))
+     :weight light
+     :box (:line-width -1 :color "grey75" :style nil)
+     :foreground "grey20" :background "grey90")
+    (((class color) (min-colors 88) (background dark) )
+     :weight light
+     :box (:line-width -1 :color "grey40" :style nil)
+     :foreground "grey80" :background "grey30"))
+  "Basic mode line face for non-selected windows."
+  :version "22.1"
+  :group 'mode-line-faces
+  :group 'basic-faces)
+(define-obsolete-face-alias 'modeline-inactive 'mode-line-inactive "22.1")
+
+(defface mode-line-highlight
+  '((((class color) (min-colors 88))
+     :box (:line-width 2 :color "grey40" :style released-button))
+    (t
+     :inherit highlight))
+  "Basic mode line face for highlighting."
+  :version "22.1"
+  :group 'mode-line-faces
+  :group 'basic-faces)
+(define-obsolete-face-alias 'modeline-highlight 'mode-line-highlight "22.1")
+
+(defface mode-line-emphasis
+  '((t (:weight bold)))
+  "Face used to emphasize certain mode line features.
+Use the face `mode-line-highlight' for features that can be selected."
+  :version "23.1"
+  :group 'mode-line-faces
+  :group 'basic-faces)
+
+(defface mode-line-buffer-id
+  '((t (:weight bold)))
+  "Face used for buffer identification parts of the mode line."
+  :version "22.1"
+  :group 'mode-line-faces
+  :group 'basic-faces)
+(define-obsolete-face-alias 'modeline-buffer-id 'mode-line-buffer-id "22.1")
+
+(defface header-line
+  '((default
+     :inherit mode-line)
+    (((type tty))
+     ;; This used to be `:inverse-video t', but that doesn't look very
+     ;; good when combined with inverse-video mode-lines and multiple
+     ;; windows.  Underlining looks better, and is more consistent with
+     ;; the window-system face variants, which deemphasize the
+     ;; header-line in relation to the mode-line face.  If a terminal
+     ;; can't underline, then the header-line will end up without any
+     ;; highlighting; this may be too confusing in general, although it
+     ;; happens to look good with the only current use of header-lines,
+     ;; the info browser. XXX
+     :inverse-video nil               ;Override the value inherited from 
mode-line.
+     :underline t)
+    (((class color grayscale) (background light))
+     :background "grey90" :foreground "grey20"
+     :box nil)
+    (((class color grayscale) (background dark))
+     :background "grey20" :foreground "grey90"
+     :box nil)
+    (((class mono) (background light))
+     :background "white" :foreground "black"
+     :inverse-video nil
+     :box nil
+     :underline t)
+    (((class mono) (background dark))
+     :background "black" :foreground "white"
+     :inverse-video nil
+     :box nil
+     :underline t))
+  "Basic header-line face."
+  :version "21.1"
+  :group 'basic-faces)
+
+(defface vertical-border
+  '((((type tty)) :inherit mode-line-inactive))
+  "Face used for vertical window dividers on ttys."
+  :version "22.1"
+  :group 'basic-faces)
+
+(defface window-divider '((t :foreground "gray60"))
+  "Basic face for window dividers.
+When a divider is less than 3 pixels wide, it is drawn solidly
+with the foreground of this face.  For larger dividers this face
+is used for the inner part while the first pixel line/column is
+drawn with the `window-divider-first-pixel' face and the last
+pixel line/column with the `window-divider-last-pixel' face."
+  :version "24.4"
+  :group 'frames
+  :group 'basic-faces)
+
+(defface window-divider-first-pixel
+  '((t :foreground "gray80"))
+  "Basic face for first pixel line/column of window dividers.
+When a divider is at least 3 pixels wide, its first pixel
+line/column is drawn with the foreground of this face.  If you do
+not want to accentuate the first pixel line/column, set this to
+the same as `window-divider' face."
+  :version "24.4"
+  :group 'frames
+  :group 'basic-faces)
+
+(defface window-divider-last-pixel
+  '((t :foreground "gray40"))
+  "Basic face for last pixel line/column of window dividers.
+When a divider is at least 3 pixels wide, its last pixel
+line/column is drawn with the foreground of this face.  If you do
+not want to accentuate the last pixel line/column, set this to
+the same as `window-divider' face."
+  :version "24.4"
+  :group 'frames
+  :group 'basic-faces)
+
+(defface minibuffer-prompt
+  '((((background dark)) :foreground "cyan")
+    ;; Don't use blue because many users of the MS-DOS port customize
+    ;; their foreground color to be blue.
+    (((type pc)) :foreground "magenta")
+    (t :foreground "medium blue"))
+  "Face for minibuffer prompts.
+By default, Emacs automatically adds this face to the value of
+`minibuffer-prompt-properties', which is a list of text properties
+used to display the prompt text."
+  :version "22.1"
+  :group 'basic-faces)
+
+(setq minibuffer-prompt-properties
+      (append minibuffer-prompt-properties (list 'face 'minibuffer-prompt)))
+
+(defface fringe
+  '((((class color) (background light))
+     :background "grey95")
+    (((class color) (background dark))
+     :background "grey10")
+    (t
+     :background "gray"))
+  "Basic face for the fringes to the left and right of windows under X."
+  :version "21.1"
+  :group 'frames
+  :group 'basic-faces)
+
+(defface scroll-bar '((t nil))
+  "Basic face for the scroll bar colors under X."
+  :version "21.1"
+  :group 'frames
+  :group 'basic-faces)
+
+(defface border '((t nil))
+  "Basic face for the frame border under X."
+  :version "21.1"
+  :group 'frames
+  :group 'basic-faces)
+
+(defface cursor
+  '((((background light)) :background "black")
+    (((background dark))  :background "white"))
+  "Basic face for the cursor color under X.
+Currently, only the `:background' attribute is meaningful; all
+other attributes are ignored.  The cursor foreground color is
+taken from the background color of the underlying text.
+
+Note: Other faces cannot inherit from the cursor face."
+  :version "21.1"
+  :group 'cursor
+  :group 'basic-faces)
+
+(put 'cursor 'face-no-inherit t)
+
+(defface mouse '((t nil))
+  "Basic face for the mouse color under X."
+  :version "21.1"
+  :group 'mouse
+  :group 'basic-faces)
+
+(defface tool-bar
+  '((default
+     :box (:line-width 1 :style released-button)
+     :foreground "black")
+    (((type x w32 ns) (class color))
+     :background "grey75")
+    (((type x) (class mono))
+     :background "grey"))
+  "Basic tool-bar face."
+  :version "21.1"
+  :group 'basic-faces)
+
+(defface menu
+  '((((type tty))
+     :inverse-video t)
+    (((type x-toolkit))
+     )
+    (t
+     :inverse-video t))
+  "Basic face for the font and colors of the menu bar and popup menus."
+  :version "21.1"
+  :group 'menu
+  :group 'basic-faces)
+
+(defface help-argument-name '((t :inherit italic))
+  "Face to highlight argument names in *Help* buffers."
+  :group 'help)
+
+(defface glyphless-char
+  '((((type tty)) :inherit underline)
+    (((type pc)) :inherit escape-glyph)
+    (t :height 0.6))
+  "Face for displaying non-graphic characters (e.g. U+202A (LRE)).
+It is used for characters of no fonts too."
+  :version "24.1"
+  :group 'basic-faces)
+
+(defface error
+  '((default :weight bold)
+    (((class color) (min-colors 88) (background light)) :foreground "Red1")
+    (((class color) (min-colors 88) (background dark))  :foreground "Pink")
+    (((class color) (min-colors 16) (background light)) :foreground "Red1")
+    (((class color) (min-colors 16) (background dark))  :foreground "Pink")
+    (((class color) (min-colors 8)) :foreground "red")
+    (t :inverse-video t))
+  "Basic face used to highlight errors and to denote failure."
+  :version "24.1"
+  :group 'basic-faces)
+
+(defface warning
+  '((default :weight bold)
+    (((class color) (min-colors 16)) :foreground "DarkOrange")
+    (((class color)) :foreground "yellow"))
+  "Basic face used to highlight warnings."
+  :version "24.1"
+  :group 'basic-faces)
+
+(defface success
+  '((default :weight bold)
+    (((class color) (min-colors 16) (background light)) :foreground 
"ForestGreen")
+    (((class color) (min-colors 88) (background dark))  :foreground "Green1")
+    (((class color) (min-colors 16) (background dark))  :foreground "Green")
+    (((class color)) :foreground "green"))
+  "Basic face used to indicate successful operation."
+  :version "24.1"
+  :group 'basic-faces)
+
+;; Faces for TTY menus.
+(defface tty-menu-enabled-face
+  '((t
+     :foreground "yellow" :background "blue" :weight bold))
+  "Face for displaying enabled items in TTY menus."
+  :group 'basic-faces)
+
+(defface tty-menu-disabled-face
+  '((((class color) (min-colors 16))
+     :foreground "lightgray" :background "blue")
+    (t
+     :foreground "white" :background "blue"))
+  "Face for displaying disabled items in TTY menus."
+  :group 'basic-faces)
+
+(defface tty-menu-selected-face
+  '((t :background "red"))
+  "Face for displaying the currently selected item in TTY menus."
+  :group 'basic-faces)
+
+(defgroup paren-showing-faces nil
+  "Faces used to highlight paren matches."
+  :group 'paren-showing
+  :group 'faces
+  :version "22.1")
+
+(defface show-paren-match
+  '((((class color) (background light))
+     :background "turquoise")          ; looks OK on tty (becomes cyan)
+    (((class color) (background dark))
+     :background "steelblue3")         ; looks OK on tty (becomes blue)
+    (((background dark))
+     :background "grey50")
+    (t
+     :background "gray"))
+  "Face used for a matching paren."
+  :group 'paren-showing-faces)
+
+(defface show-paren-mismatch
+  '((((class color)) (:foreground "white" :background "purple"))
+    (t (:inverse-video t)))
+  "Face used for a mismatching paren."
+  :group 'paren-showing-faces)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Manipulating font names.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; This is here for compatibility with Emacs 20.2.  For example,
+;; international/fontset.el uses x-resolve-font-name.  The following
+;; functions are not used in the face implementation itself.
+
+(defvar x-font-regexp nil)
+(defvar x-font-regexp-head nil)
+(defvar x-font-regexp-weight nil)
+(defvar x-font-regexp-slant nil)
+
+(defconst x-font-regexp-weight-subnum 1)
+(defconst x-font-regexp-slant-subnum 2)
+(defconst x-font-regexp-swidth-subnum 3)
+(defconst x-font-regexp-adstyle-subnum 4)
+
+;;; Regexps matching font names in "Host Portable Character Representation."
+;;;
+(let ((-               "[-?]")
+      (foundry         "[^-]+")
+      (family          "[^-]+")
+      (weight          "\\(bold\\|demibold\\|medium\\)")               ; 1
+;     (weight\?                "\\(\\*\\|bold\\|demibold\\|medium\\|\\)")      
; 1
+      (weight\?                "\\([^-]*\\)")                                  
; 1
+      (slant           "\\([ior]\\)")                                  ; 2
+;     (slant\?         "\\([ior?*]?\\)")                               ; 2
+      (slant\?         "\\([^-]?\\)")                                  ; 2
+;     (swidth          "\\(\\*\\|normal\\|semicondensed\\|\\)")        ; 3
+      (swidth          "\\([^-]*\\)")                                  ; 3
+;     (adstyle         "\\(\\*\\|sans\\|\\)")                          ; 4
+      (adstyle         "\\([^-]*\\)")                                  ; 4
+      (pixelsize       "[0-9]+")
+      (pointsize       "[0-9][0-9]+")
+      (resx            "[0-9][0-9]+")
+      (resy            "[0-9][0-9]+")
+      (spacing         "[cmp?*]")
+      (avgwidth                "[0-9]+")
+      (registry                "[^-]+")
+      (encoding                "[^-]+")
+      )
+  (setq x-font-regexp
+       (purecopy (concat "\\`\\*?[-?*]"
+               foundry - family - weight\? - slant\? - swidth - adstyle -
+               pixelsize - pointsize - resx - resy - spacing - avgwidth -
+               registry - encoding "\\*?\\'"
+               )))
+  (setq x-font-regexp-head
+       (purecopy (concat "\\`[-?*]" foundry - family - weight\? - slant\?
+               "\\([-*?]\\|\\'\\)")))
+  (setq x-font-regexp-slant (purecopy (concat - slant -)))
+  (setq x-font-regexp-weight (purecopy (concat - weight -)))
+  nil)
+
+
+(defun x-resolve-font-name (pattern &optional face frame)
+  "Return a font name matching PATTERN.
+All wildcards in PATTERN are instantiated.
+If PATTERN is nil, return the name of the frame's base font, which never
+contains wildcards.
+Given optional arguments FACE and FRAME, return a font which is
+also the same size as FACE on FRAME, or fail."
+  (and (eq frame t)
+       (setq frame nil))
+  (if pattern
+      ;; Note that x-list-fonts has code to handle a face with nil as its font.
+      (let ((fonts (x-list-fonts pattern face frame 1)))
+       (or fonts
+           (if face
+               (if (string-match-p "\\*" pattern)
+                   (if (null (face-font face))
+                       (error "No matching fonts are the same height as the 
frame default font")
+                     (error "No matching fonts are the same height as face 
`%s'" face))
+                 (if (null (face-font face))
+                     (error "Height of font `%s' doesn't match the frame 
default font"
+                            pattern)
+                   (error "Height of font `%s' doesn't match face `%s'"
+                          pattern face)))
+             (error "No fonts match `%s'" pattern)))
+       (car fonts))
+    (cdr (assq 'font (frame-parameters (selected-frame))))))
+
+(defcustom font-list-limit 100
+  "This variable is obsolete and has no effect."
+  :type 'integer
+  :group 'display)
+(make-obsolete-variable 'font-list-limit nil "24.3")
+
+(provide 'faces)
+
+;;; faces.el ends here
diff --git a/packages/context-coloring/benchmark/fixtures/lisp.el 
b/packages/context-coloring/benchmark/fixtures/lisp.el
new file mode 100644
index 0000000..f8ca6f6
--- /dev/null
+++ b/packages/context-coloring/benchmark/fixtures/lisp.el
@@ -0,0 +1,931 @@
+;;; lisp.el --- Lisp editing commands for Emacs  -*- lexical-binding:t -*-
+
+;; Copyright (C) 1985-1986, 1994, 2000-2015 Free Software Foundation,
+;; Inc.
+
+;; Maintainer: address@hidden
+;; Keywords: lisp, languages
+;; Package: emacs
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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.
+
+;; GNU Emacs 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 GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Lisp editing commands to go with Lisp major mode.  More-or-less
+;; applicable in other modes too.
+
+;;; Code:
+
+;; Note that this variable is used by non-lisp modes too.
+(defcustom defun-prompt-regexp nil
+  "If non-nil, a regexp to ignore before a defun.
+This is only necessary if the opening paren or brace is not in column 0.
+See function `beginning-of-defun'."
+  :type '(choice (const nil)
+                regexp)
+  :group 'lisp)
+(make-variable-buffer-local 'defun-prompt-regexp)
+
+(defcustom parens-require-spaces t
+  "If non-nil, add whitespace as needed when inserting parentheses.
+This affects `insert-parentheses' and `insert-pair'."
+  :type 'boolean
+  :group 'lisp)
+
+(defvar forward-sexp-function nil
+  ;; FIXME:
+  ;; - for some uses, we may want a "sexp-only" version, which only
+  ;;   jumps over a well-formed sexp, rather than some dwimish thing
+  ;;   like jumping from an "else" back up to its "if".
+  ;; - for up-list, we could use the "sexp-only" behavior as well
+  ;;   to treat the dwimish halfsexp as a form of "up-list" step.
+  "If non-nil, `forward-sexp' delegates to this function.
+Should take the same arguments and behave similarly to `forward-sexp'.")
+
+(defun forward-sexp (&optional arg)
+  "Move forward across one balanced expression (sexp).
+With ARG, do it that many times.  Negative arg -N means
+move backward across N balanced expressions.
+This command assumes point is not in a string or comment.
+Calls `forward-sexp-function' to do the work, if that is non-nil."
+  (interactive "^p")
+  (or arg (setq arg 1))
+  (if forward-sexp-function
+      (funcall forward-sexp-function arg)
+    (goto-char (or (scan-sexps (point) arg) (buffer-end arg)))
+    (if (< arg 0) (backward-prefix-chars))))
+
+(defun backward-sexp (&optional arg)
+  "Move backward across one balanced expression (sexp).
+With ARG, do it that many times.  Negative arg -N means
+move forward across N balanced expressions.
+This command assumes point is not in a string or comment.
+Uses `forward-sexp' to do the work."
+  (interactive "^p")
+  (or arg (setq arg 1))
+  (forward-sexp (- arg)))
+
+(defun mark-sexp (&optional arg allow-extend)
+  "Set mark ARG sexps from point.
+The place mark goes is the same place \\[forward-sexp] would
+move to with the same argument.
+Interactively, if this command is repeated
+or (in Transient Mark mode) if the mark is active,
+it marks the next ARG sexps after the ones already marked.
+This command assumes point is not in a string or comment."
+  (interactive "P\np")
+  (cond ((and allow-extend
+             (or (and (eq last-command this-command) (mark t))
+                 (and transient-mark-mode mark-active)))
+        (setq arg (if arg (prefix-numeric-value arg)
+                    (if (< (mark) (point)) -1 1)))
+        (set-mark
+         (save-excursion
+           (goto-char (mark))
+           (forward-sexp arg)
+           (point))))
+       (t
+        (push-mark
+         (save-excursion
+           (forward-sexp (prefix-numeric-value arg))
+           (point))
+         nil t))))
+
+(defun forward-list (&optional arg)
+  "Move forward across one balanced group of parentheses.
+This command will also work on other parentheses-like expressions
+defined by the current language mode.
+With ARG, do it that many times.
+Negative arg -N means move backward across N groups of parentheses.
+This command assumes point is not in a string or comment."
+  (interactive "^p")
+  (or arg (setq arg 1))
+  (goto-char (or (scan-lists (point) arg 0) (buffer-end arg))))
+
+(defun backward-list (&optional arg)
+  "Move backward across one balanced group of parentheses.
+This command will also work on other parentheses-like expressions
+defined by the current language mode.
+With ARG, do it that many times.
+Negative arg -N means move forward across N groups of parentheses.
+This command assumes point is not in a string or comment."
+  (interactive "^p")
+  (or arg (setq arg 1))
+  (forward-list (- arg)))
+
+(defun down-list (&optional arg)
+  "Move forward down one level of parentheses.
+This command will also work on other parentheses-like expressions
+defined by the current language mode.
+With ARG, do this that many times.
+A negative argument means move backward but still go down a level.
+This command assumes point is not in a string or comment."
+  (interactive "^p")
+  (or arg (setq arg 1))
+  (let ((inc (if (> arg 0) 1 -1)))
+    (while (/= arg 0)
+      (goto-char (or (scan-lists (point) inc -1) (buffer-end arg)))
+      (setq arg (- arg inc)))))
+
+(defun backward-up-list (&optional arg)
+  "Move backward out of one level of parentheses.
+This command will also work on other parentheses-like expressions
+defined by the current language mode.
+With ARG, do this that many times.
+A negative argument means move forward but still to a less deep spot.
+This command assumes point is not in a string or comment."
+  (interactive "^p")
+  (up-list (- (or arg 1))))
+
+(defun up-list (&optional arg)
+  "Move forward out of one level of parentheses.
+This command will also work on other parentheses-like expressions
+defined by the current language mode.
+With ARG, do this that many times.
+A negative argument means move backward but still to a less deep spot.
+This command assumes point is not in a string or comment."
+  (interactive "^p")
+  (or arg (setq arg 1))
+  (let ((inc (if (> arg 0) 1 -1))
+        pos)
+    (while (/= arg 0)
+      (if (null forward-sexp-function)
+          (goto-char (or (scan-lists (point) inc 1) (buffer-end arg)))
+       (condition-case err
+           (while (progn (setq pos (point))
+                         (forward-sexp inc)
+                         (/= (point) pos)))
+         (scan-error (goto-char (nth (if (> arg 0) 3 2) err))))
+       (if (= (point) pos)
+            (signal 'scan-error
+                    (list "Unbalanced parentheses" (point) (point)))))
+      (setq arg (- arg inc)))))
+
+(defun kill-sexp (&optional arg)
+  "Kill the sexp (balanced expression) following point.
+With ARG, kill that many sexps after point.
+Negative arg -N means kill N sexps before point.
+This command assumes point is not in a string or comment."
+  (interactive "p")
+  (let ((opoint (point)))
+    (forward-sexp (or arg 1))
+    (kill-region opoint (point))))
+
+(defun backward-kill-sexp (&optional arg)
+  "Kill the sexp (balanced expression) preceding point.
+With ARG, kill that many sexps before point.
+Negative arg -N means kill N sexps after point.
+This command assumes point is not in a string or comment."
+  (interactive "p")
+  (kill-sexp (- (or arg 1))))
+
+;; After Zmacs:
+(defun kill-backward-up-list (&optional arg)
+  "Kill the form containing the current sexp, leaving the sexp itself.
+A prefix argument ARG causes the relevant number of surrounding
+forms to be removed.
+This command assumes point is not in a string or comment."
+  (interactive "*p")
+  (let ((current-sexp (thing-at-point 'sexp)))
+    (if current-sexp
+        (save-excursion
+          (backward-up-list arg)
+          (kill-sexp)
+          (insert current-sexp))
+      (error "Not at a sexp"))))
+
+(defvar beginning-of-defun-function nil
+  "If non-nil, function for `beginning-of-defun-raw' to call.
+This is used to find the beginning of the defun instead of using the
+normal recipe (see `beginning-of-defun').  Major modes can define this
+if defining `defun-prompt-regexp' is not sufficient to handle the mode's
+needs.
+
+The function takes the same argument as `beginning-of-defun' and should
+behave similarly, returning non-nil if it found the beginning of a defun.
+Ideally it should move to a point right before an open-paren which encloses
+the body of the defun.")
+
+(defun beginning-of-defun (&optional arg)
+  "Move backward to the beginning of a defun.
+With ARG, do it that many times.  Negative ARG means move forward
+to the ARGth following beginning of defun.
+
+If search is successful, return t; point ends up at the beginning
+of the line where the search succeeded.  Otherwise, return nil.
+
+When `open-paren-in-column-0-is-defun-start' is non-nil, a defun
+is assumed to start where there is a char with open-parenthesis
+syntax at the beginning of a line.  If `defun-prompt-regexp' is
+non-nil, then a string which matches that regexp may also precede
+the open-parenthesis.  If `defun-prompt-regexp' and
+`open-paren-in-column-0-is-defun-start' are both nil, this
+function instead finds an open-paren at the outermost level.
+
+If the variable `beginning-of-defun-function' is non-nil, its
+value is called as a function, with argument ARG, to find the
+defun's beginning.
+
+Regardless of the values of `defun-prompt-regexp' and
+`beginning-of-defun-function', point always moves to the
+beginning of the line whenever the search is successful."
+  (interactive "^p")
+  (or (not (eq this-command 'beginning-of-defun))
+      (eq last-command 'beginning-of-defun)
+      (and transient-mark-mode mark-active)
+      (push-mark))
+  (and (beginning-of-defun-raw arg)
+       (progn (beginning-of-line) t)))
+
+(defun beginning-of-defun-raw (&optional arg)
+  "Move point to the character that starts a defun.
+This is identical to function `beginning-of-defun', except that point
+does not move to the beginning of the line when `defun-prompt-regexp'
+is non-nil.
+
+If variable `beginning-of-defun-function' is non-nil, its value
+is called as a function to find the defun's beginning."
+  (interactive "^p")   ; change this to "P", maybe, if we ever come to pass ARG
+                      ; to beginning-of-defun-function.
+  (unless arg (setq arg 1))
+  (cond
+   (beginning-of-defun-function
+    (condition-case nil
+        (funcall beginning-of-defun-function arg)
+      ;; We used to define beginning-of-defun-function as taking no argument
+      ;; but that makes it impossible to implement correct forward motion:
+      ;; we used to use end-of-defun for that, but it's not supposed to do
+      ;; the same thing (it moves to the end of a defun not to the beginning
+      ;; of the next).
+      ;; In case the beginning-of-defun-function uses the old calling
+      ;; convention, fallback on the old implementation.
+      (wrong-number-of-arguments
+       (if (> arg 0)
+           (dotimes (_ arg)
+             (funcall beginning-of-defun-function))
+        (dotimes (_ (- arg))
+          (funcall end-of-defun-function))))))
+
+   ((or defun-prompt-regexp open-paren-in-column-0-is-defun-start)
+    (and (< arg 0) (not (eobp)) (forward-char 1))
+    (and (re-search-backward (if defun-prompt-regexp
+                                (concat (if 
open-paren-in-column-0-is-defun-start
+                                            "^\\s(\\|" "")
+                                        "\\(?:" defun-prompt-regexp "\\)\\s(")
+                              "^\\s(")
+                            nil 'move arg)
+        (progn (goto-char (1- (match-end 0)))
+                t)))
+
+   ;; If open-paren-in-column-0-is-defun-start and defun-prompt-regexp
+   ;; are both nil, column 0 has no significance - so scan forward
+   ;; from BOB to see how nested point is, then carry on from there.
+   ;;
+   ;; It is generally not a good idea to land up here, because the
+   ;; call to scan-lists below can be extremely slow.  This is because
+   ;; back_comment in syntax.c may have to scan from bob to find the
+   ;; beginning of each comment.  Fixing this is not trivial -- cyd.
+
+   ((eq arg 0))
+   (t
+    (let ((floor (point-min))
+         (ceiling (point-max))
+         (arg-+ve (> arg 0)))
+      (save-restriction
+       (widen)
+       (let ((ppss (let (syntax-begin-function
+                         font-lock-beginning-of-syntax-function)
+                     (syntax-ppss)))
+             ;; position of least enclosing paren, or nil.
+             encl-pos)
+         ;; Back out of any comment/string, so that encl-pos will always
+         ;; become nil if we're at top-level.
+         (when (nth 8 ppss)
+           (goto-char (nth 8 ppss))
+           (setq ppss (syntax-ppss)))  ; should be fast, due to cache.
+         (setq encl-pos (syntax-ppss-toplevel-pos ppss))
+         (if encl-pos (goto-char encl-pos))
+
+         (and encl-pos arg-+ve (setq arg (1- arg)))
+         (and (not encl-pos) (not arg-+ve) (not (looking-at "\\s("))
+              (setq arg (1+ arg)))
+
+         (condition-case nil   ; to catch crazy parens.
+             (progn
+               (goto-char (scan-lists (point) (- arg) 0))
+               (if arg-+ve
+                   (if (>= (point) floor)
+                       t
+                     (goto-char floor)
+                     nil)
+                 ;; forward to next (, or trigger the c-c
+                 (goto-char (1- (scan-lists (point) 1 -1)))
+                 (if (<= (point) ceiling)
+                     t
+                   (goto-char ceiling)
+                   nil)))
+           (error
+            (goto-char (if arg-+ve floor ceiling))
+            nil))))))))
+
+(defvar end-of-defun-function
+  (lambda () (forward-sexp 1))
+  "Function for `end-of-defun' to call.
+This is used to find the end of the defun at point.
+It is called with no argument, right after calling `beginning-of-defun-raw'.
+So the function can assume that point is at the beginning of the defun body.
+It should move point to the first position after the defun.")
+
+(defun buffer-end (arg)
+  "Return the \"far end\" position of the buffer, in direction ARG.
+If ARG is positive, that's the end of the buffer.
+Otherwise, that's the beginning of the buffer."
+  (if (> arg 0) (point-max) (point-min)))
+
+(defun end-of-defun (&optional arg)
+  "Move forward to next end of defun.
+With argument, do it that many times.
+Negative argument -N means move back to Nth preceding end of defun.
+
+An end of a defun occurs right after the close-parenthesis that
+matches the open-parenthesis that starts a defun; see function
+`beginning-of-defun'.
+
+If variable `end-of-defun-function' is non-nil, its value
+is called as a function to find the defun's end."
+  (interactive "^p")
+  (or (not (eq this-command 'end-of-defun))
+      (eq last-command 'end-of-defun)
+      (and transient-mark-mode mark-active)
+      (push-mark))
+  (if (or (null arg) (= arg 0)) (setq arg 1))
+  (let ((pos (point))
+        (beg (progn (end-of-line 1) (beginning-of-defun-raw 1) (point)))
+       (skip (lambda ()
+               ;; When comparing point against pos, we want to consider that if
+               ;; point was right after the end of the function, it's still
+               ;; considered as "in that function".
+               ;; E.g. `eval-defun' from right after the last close-paren.
+               (unless (bolp)
+                 (skip-chars-forward " \t")
+                 (if (looking-at "\\s<\\|\n")
+                     (forward-line 1))))))
+    (funcall end-of-defun-function)
+    (funcall skip)
+    (cond
+     ((> arg 0)
+      ;; Moving forward.
+      (if (> (point) pos)
+          ;; We already moved forward by one because we started from
+          ;; within a function.
+          (setq arg (1- arg))
+        ;; We started from after the end of the previous function.
+        (goto-char pos))
+      (unless (zerop arg)
+        (beginning-of-defun-raw (- arg))
+        (funcall end-of-defun-function)))
+     ((< arg 0)
+      ;; Moving backward.
+      (if (< (point) pos)
+          ;; We already moved backward because we started from between
+          ;; two functions.
+          (setq arg (1+ arg))
+        ;; We started from inside a function.
+        (goto-char beg))
+      (unless (zerop arg)
+        (beginning-of-defun-raw (- arg))
+       (setq beg (point))
+        (funcall end-of-defun-function))))
+    (funcall skip)
+    (while (and (< arg 0) (>= (point) pos))
+      ;; We intended to move backward, but this ended up not doing so:
+      ;; Try harder!
+      (goto-char beg)
+      (beginning-of-defun-raw (- arg))
+      (if (>= (point) beg)
+         (setq arg 0)
+       (setq beg (point))
+        (funcall end-of-defun-function)
+       (funcall skip)))))
+
+(defun mark-defun (&optional allow-extend)
+  "Put mark at end of this defun, point at beginning.
+The defun marked is the one that contains point or follows point.
+
+Interactively, if this command is repeated
+or (in Transient Mark mode) if the mark is active,
+it marks the next defun after the ones already marked."
+  (interactive "p")
+  (cond ((and allow-extend
+             (or (and (eq last-command this-command) (mark t))
+                 (and transient-mark-mode mark-active)))
+        (set-mark
+         (save-excursion
+           (goto-char (mark))
+           (end-of-defun)
+           (point))))
+       (t
+        (let ((opoint (point))
+              beg end)
+          (push-mark opoint)
+          ;; Try first in this order for the sake of languages with nested
+          ;; functions where several can end at the same place as with
+          ;; the offside rule, e.g. Python.
+          (beginning-of-defun)
+          (setq beg (point))
+          (end-of-defun)
+          (setq end (point))
+          (while (looking-at "^\n")
+            (forward-line 1))
+          (if (> (point) opoint)
+              (progn
+                ;; We got the right defun.
+                (push-mark beg nil t)
+                (goto-char end)
+                (exchange-point-and-mark))
+            ;; beginning-of-defun moved back one defun
+            ;; so we got the wrong one.
+            (goto-char opoint)
+            (end-of-defun)
+            (push-mark (point) nil t)
+            (beginning-of-defun))
+          (re-search-backward "^\n" (- (point) 1) t)))))
+
+(defun narrow-to-defun (&optional _arg)
+  "Make text outside current defun invisible.
+The defun visible is the one that contains point or follows point.
+Optional ARG is ignored."
+  (interactive)
+  (save-excursion
+    (widen)
+    (let ((opoint (point))
+         beg end)
+      ;; Try first in this order for the sake of languages with nested
+      ;; functions where several can end at the same place as with
+      ;; the offside rule, e.g. Python.
+
+      ;; Finding the start of the function is a bit problematic since
+      ;; `beginning-of-defun' when we are on the first character of
+      ;; the function might go to the previous function.
+      ;;
+      ;; Therefore we first move one character forward and then call
+      ;; `beginning-of-defun'.  However now we must check that we did
+      ;; not move into the next function.
+      (let ((here (point)))
+        (unless (eolp)
+         (forward-char))
+        (beginning-of-defun)
+        (when (< (point) here)
+          (goto-char here)
+          (beginning-of-defun)))
+      (setq beg (point))
+      (end-of-defun)
+      (setq end (point))
+      (while (looking-at "^\n")
+       (forward-line 1))
+      (unless (> (point) opoint)
+       ;; beginning-of-defun moved back one defun
+       ;; so we got the wrong one.
+       (goto-char opoint)
+       (end-of-defun)
+       (setq end (point))
+       (beginning-of-defun)
+       (setq beg (point)))
+      (goto-char end)
+      (re-search-backward "^\n" (- (point) 1) t)
+      (narrow-to-region beg end))))
+
+(defvar insert-pair-alist
+  '((?\( ?\)) (?\[ ?\]) (?\{ ?\}) (?\< ?\>) (?\" ?\") (?\' ?\') (?\` ?\'))
+  "Alist of paired characters inserted by `insert-pair'.
+Each element looks like (OPEN-CHAR CLOSE-CHAR) or (COMMAND-CHAR
+OPEN-CHAR CLOSE-CHAR).  The characters OPEN-CHAR and CLOSE-CHAR
+of the pair whose key is equal to the last input character with
+or without modifiers, are inserted by `insert-pair'.")
+
+(defun insert-pair (&optional arg open close)
+  "Enclose following ARG sexps in a pair of OPEN and CLOSE characters.
+Leave point after the first character.
+A negative ARG encloses the preceding ARG sexps instead.
+No argument is equivalent to zero: just insert characters
+and leave point between.
+If `parens-require-spaces' is non-nil, this command also inserts a space
+before and after, depending on the surrounding characters.
+If region is active, insert enclosing characters at region boundaries.
+
+If arguments OPEN and CLOSE are nil, the character pair is found
+from the variable `insert-pair-alist' according to the last input
+character with or without modifiers.  If no character pair is
+found in the variable `insert-pair-alist', then the last input
+character is inserted ARG times.
+
+This command assumes point is not in a string or comment."
+  (interactive "P")
+  (if (not (and open close))
+      (let ((pair (or (assq last-command-event insert-pair-alist)
+                      (assq (event-basic-type last-command-event)
+                            insert-pair-alist))))
+        (if pair
+            (if (nth 2 pair)
+                (setq open (nth 1 pair) close (nth 2 pair))
+              (setq open (nth 0 pair) close (nth 1 pair))))))
+  (if (and open close)
+      (if (and transient-mark-mode mark-active)
+          (progn
+            (save-excursion (goto-char (region-end))       (insert close))
+            (save-excursion (goto-char (region-beginning)) (insert open)))
+        (if arg (setq arg (prefix-numeric-value arg))
+          (setq arg 0))
+        (cond ((> arg 0) (skip-chars-forward " \t"))
+              ((< arg 0) (forward-sexp arg) (setq arg (- arg))))
+        (and parens-require-spaces
+             (not (bobp))
+             (memq (char-syntax (preceding-char)) (list ?w ?_ (char-syntax 
close)))
+             (insert " "))
+        (insert open)
+        (save-excursion
+          (or (eq arg 0) (forward-sexp arg))
+          (insert close)
+          (and parens-require-spaces
+               (not (eobp))
+               (memq (char-syntax (following-char)) (list ?w ?_ (char-syntax 
open)))
+               (insert " "))))
+    (insert-char (event-basic-type last-command-event)
+                 (prefix-numeric-value arg))))
+
+(defun insert-parentheses (&optional arg)
+  "Enclose following ARG sexps in parentheses.
+Leave point after open-paren.
+A negative ARG encloses the preceding ARG sexps instead.
+No argument is equivalent to zero: just insert `()' and leave point between.
+If `parens-require-spaces' is non-nil, this command also inserts a space
+before and after, depending on the surrounding characters.
+If region is active, insert enclosing characters at region boundaries.
+
+This command assumes point is not in a string or comment."
+  (interactive "P")
+  (insert-pair arg ?\( ?\)))
+
+(defun delete-pair ()
+  "Delete a pair of characters enclosing the sexp that follows point."
+  (interactive)
+  (save-excursion (forward-sexp 1) (delete-char -1))
+  (delete-char 1))
+
+(defun raise-sexp (&optional arg)
+  "Raise ARG sexps higher up the tree."
+  (interactive "p")
+  (let ((s (if (and transient-mark-mode mark-active)
+               (buffer-substring (region-beginning) (region-end))
+             (buffer-substring
+              (point)
+              (save-excursion (forward-sexp arg) (point))))))
+    (backward-up-list 1)
+    (delete-region (point) (save-excursion (forward-sexp 1) (point)))
+    (save-excursion (insert s))))
+
+(defun move-past-close-and-reindent ()
+  "Move past next `)', delete indentation before it, then indent after it."
+  (interactive)
+  (up-list 1)
+  (forward-char -1)
+  (while (save-excursion               ; this is my contribution
+          (let ((before-paren (point)))
+            (back-to-indentation)
+            (and (= (point) before-paren)
+                 (progn
+                   ;; Move to end of previous line.
+                   (beginning-of-line)
+                   (forward-char -1)
+                   ;; Verify it doesn't end within a string or comment.
+                   (let ((end (point))
+                         state)
+                     (beginning-of-line)
+                     ;; Get state at start of line.
+                     (setq state  (list 0 nil nil
+                                        (null (calculate-lisp-indent))
+                                        nil nil nil nil
+                                        nil))
+                     ;; Parse state across the line to get state at end.
+                     (setq state (parse-partial-sexp (point) end nil nil
+                                                     state))
+                     ;; Check not in string or comment.
+                     (and (not (elt state 3)) (not (elt state 4))))))))
+    (delete-indentation))
+  (forward-char 1)
+  (newline-and-indent))
+
+(defun check-parens ()                 ; lame name?
+  "Check for unbalanced parentheses in the current buffer.
+More accurately, check the narrowed part of the buffer for unbalanced
+expressions (\"sexps\") in general.  This is done according to the
+current syntax table and will find unbalanced brackets or quotes as
+appropriate.  (See Info node `(emacs)Parentheses'.)  If imbalance is
+found, an error is signaled and point is left at the first unbalanced
+character."
+  (interactive)
+  (condition-case data
+      ;; Buffer can't have more than (point-max) sexps.
+      (scan-sexps (point-min) (point-max))
+    (scan-error (goto-char (nth 2 data))
+               ;; Could print (nth 1 data), which is either
+               ;; "Containing expression ends prematurely" or
+               ;; "Unbalanced parentheses", but those may not be so
+               ;; accurate/helpful, e.g. quotes may actually be
+               ;; mismatched.
+               (user-error "Unmatched bracket or quote"))))
+
+(defun field-complete (table &optional predicate)
+  (declare (obsolete completion-in-region "24.4"))
+  (let ((minibuffer-completion-table table)
+        (minibuffer-completion-predicate predicate)
+        ;; This made sense for lisp-complete-symbol, but for
+        ;; field-complete, this is out of place.  --Stef
+        ;; (completion-annotate-function
+        ;;  (unless (eq predicate 'fboundp)
+        ;;    (lambda (str)
+        ;;      (if (fboundp (intern-soft str)) " <f>"))))
+        )
+    (call-interactively 'minibuffer-complete)))
+
+(defun lisp-complete-symbol (&optional predicate)
+  "Perform completion on Lisp symbol preceding point.
+Compare that symbol against the known Lisp symbols.
+If no characters can be completed, display a list of possible completions.
+Repeating the command at that point scrolls the list.
+
+When called from a program, optional arg PREDICATE is a predicate
+determining which symbols are considered, e.g. `commandp'.
+If PREDICATE is nil, the context determines which symbols are
+considered.  If the symbol starts just after an open-parenthesis, only
+symbols with function definitions are considered.  Otherwise, all
+symbols with function definitions, values or properties are
+considered."
+  (declare (obsolete completion-at-point "24.4"))
+  (interactive)
+  (let* ((data (lisp-completion-at-point predicate))
+         (plist (nthcdr 3 data)))
+    (if (null data)
+        (minibuffer-message "Nothing to complete")
+      (let ((completion-extra-properties plist))
+        (completion-in-region (nth 0 data) (nth 1 data) (nth 2 data)
+                              (plist-get plist :predicate))))))
+
+(defun lisp--local-variables-1 (vars sexp)
+  "Return the vars locally bound around the witness, or nil if not found."
+  (let (res)
+    (while
+        (unless
+            (setq res
+                  (pcase sexp
+                    (`(,(or `let `let*) ,bindings)
+                     (let ((vars vars))
+                       (when (eq 'let* (car sexp))
+                         (dolist (binding (cdr (reverse bindings)))
+                           (push (or (car-safe binding) binding) vars)))
+                       (lisp--local-variables-1
+                        vars (car (cdr-safe (car (last bindings)))))))
+                    (`(,(or `let `let*) ,bindings . ,body)
+                     (let ((vars vars))
+                       (dolist (binding bindings)
+                         (push (or (car-safe binding) binding) vars))
+                       (lisp--local-variables-1 vars (car (last body)))))
+                    (`(lambda ,_) (setq sexp nil))
+                    (`(lambda ,args . ,body)
+                     (lisp--local-variables-1
+                      (append args vars) (car (last body))))
+                    (`(condition-case ,_ ,e) (lisp--local-variables-1 vars e))
+                    (`(condition-case ,v ,_ . ,catches)
+                     (lisp--local-variables-1
+                      (cons v vars) (cdr (car (last catches)))))
+                    (`(quote . ,_) (setq sexp nil))
+                    (`(,_ . ,_)
+                     (lisp--local-variables-1 vars (car (last sexp))))
+                    (`lisp--witness--lisp (or vars '(nil)))
+                    (_ nil)))
+          (setq sexp (ignore-errors (butlast sexp)))))
+    res))
+
+(defun lisp--local-variables ()
+  "Return a list of locally let-bound variables at point."
+  (save-excursion
+    (skip-syntax-backward "w_")
+    (let* ((ppss (syntax-ppss))
+           (txt (buffer-substring-no-properties (or (car (nth 9 ppss)) (point))
+                                                (or (nth 8 ppss) (point))))
+           (closer ()))
+      (dolist (p (nth 9 ppss))
+        (push (cdr (syntax-after p)) closer))
+      (setq closer (apply #'string closer))
+      (let* ((sexp (condition-case nil
+                       (car (read-from-string
+                             (concat txt "lisp--witness--lisp" closer)))
+                     (end-of-file nil)))
+             (macroexpand-advice (lambda (expander form &rest args)
+                                   (condition-case nil
+                                       (apply expander form args)
+                                     (error form))))
+             (sexp
+              (unwind-protect
+                  (progn
+                    (advice-add 'macroexpand :around macroexpand-advice)
+                    (macroexpand-all sexp))
+                (advice-remove 'macroexpand macroexpand-advice)))
+             (vars (lisp--local-variables-1 nil sexp)))
+        (delq nil
+              (mapcar (lambda (var)
+                        (and (symbolp var)
+                             (not (string-match (symbol-name var) "\\`[&_]"))
+                             ;; Eliminate uninterned vars.
+                             (intern-soft var)
+                             var))
+                      vars))))))
+
+(defvar lisp--local-variables-completion-table
+  ;; Use `defvar' rather than `defconst' since defconst would purecopy this
+  ;; value, which would doubly fail: it would fail because purecopy can't
+  ;; handle the recursive bytecode object, and it would fail because it would
+  ;; move `lastpos' and `lastvars' to pure space where they'd be immutable!
+  (let ((lastpos nil) (lastvars nil))
+    (letrec ((hookfun (lambda ()
+                        (setq lastpos nil)
+                        (remove-hook 'post-command-hook hookfun))))
+      (completion-table-dynamic
+       (lambda (_string)
+         (save-excursion
+           (skip-syntax-backward "_w")
+           (let ((newpos (cons (point) (current-buffer))))
+             (unless (equal lastpos newpos)
+               (add-hook 'post-command-hook hookfun)
+               (setq lastpos newpos)
+               (setq lastvars
+                     (mapcar #'symbol-name (lisp--local-variables))))))
+         lastvars)))))
+
+;; FIXME: Support for Company brings in features which straddle eldoc.
+;; We should consolidate this, so that major modes can provide all that
+;; data all at once:
+;; - a function to extract "the reference at point" (may be more complex
+;;     than a mere string, to distinguish various namespaces).
+;; - a function to jump to such a reference.
+;; - a function to show the signature/interface of such a reference.
+;; - a function to build a help-buffer about that reference.
+;; FIXME: Those functions should also be used by the normal completion code in
+;; the *Completions* buffer.
+
+(defun lisp--company-doc-buffer (str)
+  (let ((symbol (intern-soft str)))
+    ;; FIXME: we really don't want to "display-buffer and then undo it".
+    (save-window-excursion
+      ;; Make sure we don't display it in another frame, otherwise
+      ;; save-window-excursion won't be able to undo it.
+      (let ((display-buffer-overriding-action
+             '(nil . ((inhibit-switch-frame . t)))))
+        (ignore-errors
+          (cond
+           ((fboundp symbol) (describe-function symbol))
+           ((boundp symbol) (describe-variable symbol))
+           ((featurep symbol) (describe-package symbol))
+           ((facep symbol) (describe-face symbol))
+           (t (signal 'user-error nil)))
+          (help-buffer))))))
+
+(defun lisp--company-doc-string (str)
+  (let* ((symbol (intern-soft str))
+         (doc (if (fboundp symbol)
+                  (documentation symbol t)
+                (documentation-property symbol 'variable-documentation t))))
+    (and (stringp doc)
+         (string-match ".*$" doc)
+         (match-string 0 doc))))
+
+(declare-function find-library-name "find-func" (library))
+
+(defun lisp--company-location (str)
+  (let ((sym (intern-soft str)))
+    (cond
+     ((fboundp sym) (find-definition-noselect sym nil))
+     ((boundp sym) (find-definition-noselect sym 'defvar))
+     ((featurep sym)
+      (require 'find-func)
+      (cons (find-file-noselect (find-library-name
+                                 (symbol-name sym)))
+            0))
+     ((facep sym) (find-definition-noselect sym 'defface)))))
+
+(defun lisp-completion-at-point (&optional _predicate)
+  "Function used for `completion-at-point-functions' in `emacs-lisp-mode'."
+  (with-syntax-table emacs-lisp-mode-syntax-table
+    (let* ((pos (point))
+          (beg (condition-case nil
+                   (save-excursion
+                     (backward-sexp 1)
+                     (skip-syntax-forward "'")
+                     (point))
+                 (scan-error pos)))
+          (end
+           (unless (or (eq beg (point-max))
+                       (member (char-syntax (char-after beg))
+                                '(?\s ?\" ?\( ?\))))
+             (condition-case nil
+                 (save-excursion
+                   (goto-char beg)
+                   (forward-sexp 1)
+                   (when (>= (point) pos)
+                     (point)))
+               (scan-error pos))))
+           (funpos (eq (char-before beg) ?\()) ;t if in function position.
+           (table-etc
+            (if (not funpos)
+                ;; FIXME: We could look at the first element of the list and
+                ;; use it to provide a more specific completion table in some
+                ;; cases.  E.g. filter out keywords that are not understood by
+                ;; the macro/function being called.
+                (list nil (completion-table-merge
+                           lisp--local-variables-completion-table
+                           (apply-partially #'completion-table-with-predicate
+                                            obarray
+                                            ;; Don't include all symbols
+                                            ;; (bug#16646).
+                                            (lambda (sym)
+                                              (or (boundp sym)
+                                                  (fboundp sym)
+                                                  (symbol-plist sym)))
+                                            'strict))
+                      :annotation-function
+                      (lambda (str) (if (fboundp (intern-soft str)) " <f>"))
+                      :company-doc-buffer #'lisp--company-doc-buffer
+                      :company-docsig #'lisp--company-doc-string
+                      :company-location #'lisp--company-location)
+              ;; Looks like a funcall position.  Let's double check.
+              (save-excursion
+                (goto-char (1- beg))
+                (let ((parent
+                       (condition-case nil
+                           (progn (up-list -1) (forward-char 1)
+                                  (let ((c (char-after)))
+                                    (if (eq c ?\() ?\(
+                                      (if (memq (char-syntax c) '(?w ?_))
+                                          (read (current-buffer))))))
+                         (error nil))))
+                  (pcase parent
+                    ;; FIXME: Rather than hardcode special cases here,
+                    ;; we should use something like a symbol-property.
+                    (`declare
+                     (list t (mapcar (lambda (x) (symbol-name (car x)))
+                                     (delete-dups
+                                      ;; FIXME: We should include some
+                                      ;; docstring with each entry.
+                                      (append
+                                       macro-declarations-alist
+                                       defun-declarations-alist)))))
+                    ((and (or `condition-case `condition-case-unless-debug)
+                          (guard (save-excursion
+                                   (ignore-errors
+                                     (forward-sexp 2)
+                                     (< (point) beg)))))
+                     (list t obarray
+                           :predicate (lambda (sym) (get sym 
'error-conditions))))
+                   ((and ?\(
+                         (guard (save-excursion
+                                  (goto-char (1- beg))
+                                  (up-list -1)
+                                  (forward-symbol -1)
+                                  (looking-at "\\_<let\\*?\\_>"))))
+                    (list t obarray
+                          :predicate #'boundp
+                          :company-doc-buffer #'lisp--company-doc-buffer
+                          :company-docsig #'lisp--company-doc-string
+                          :company-location #'lisp--company-location))
+                    (_ (list nil obarray
+                             :predicate #'fboundp
+                             :company-doc-buffer #'lisp--company-doc-buffer
+                             :company-docsig #'lisp--company-doc-string
+                             :company-location #'lisp--company-location
+                             ))))))))
+      (when end
+        (let ((tail (if (null (car table-etc))
+                        (cdr table-etc)
+                      (cons
+                       (if (memq (char-syntax (or (char-after end) ?\s))
+                                 '(?\s ?>))
+                           (cadr table-etc)
+                         (apply-partially 'completion-table-with-terminator
+                                          " " (cadr table-etc)))
+                       (cddr table-etc)))))
+          `(,beg ,end ,@tail))))))
+
+;;; lisp.el ends here
diff --git a/packages/context-coloring/benchmark/fixtures/simple.el 
b/packages/context-coloring/benchmark/fixtures/simple.el
new file mode 100644
index 0000000..5e5cd87
--- /dev/null
+++ b/packages/context-coloring/benchmark/fixtures/simple.el
@@ -0,0 +1,7901 @@
+;;; simple.el --- basic editing commands for Emacs  -*- lexical-binding: t -*-
+
+;; Copyright (C) 1985-1987, 1993-2015 Free Software Foundation, Inc.
+
+;; Maintainer: address@hidden
+;; Keywords: internal
+;; Package: emacs
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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.
+
+;; GNU Emacs 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 GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; A grab-bag of basic Emacs commands not specifically related to some
+;; major mode or to file-handling.
+
+;;; Code:
+
+(eval-when-compile (require 'cl-lib))
+
+(declare-function widget-convert "wid-edit" (type &rest args))
+(declare-function shell-mode "shell" ())
+
+;;; From compile.el
+(defvar compilation-current-error)
+(defvar compilation-context-lines)
+
+(defcustom idle-update-delay 0.5
+  "Idle time delay before updating various things on the screen.
+Various Emacs features that update auxiliary information when point moves
+wait this many seconds after Emacs becomes idle before doing an update."
+  :type 'number
+  :group 'display
+  :version "22.1")
+
+(defgroup killing nil
+  "Killing and yanking commands."
+  :group 'editing)
+
+(defgroup paren-matching nil
+  "Highlight (un)matching of parens and expressions."
+  :group 'matching)
+
+;;; next-error support framework
+
+(defgroup next-error nil
+  "`next-error' support framework."
+  :group 'compilation
+  :version "22.1")
+
+(defface next-error
+  '((t (:inherit region)))
+  "Face used to highlight next error locus."
+  :group 'next-error
+  :version "22.1")
+
+(defcustom next-error-highlight 0.5
+  "Highlighting of locations in selected source buffers.
+If a number, highlight the locus in `next-error' face for the given time
+in seconds, or until the next command is executed.
+If t, highlight the locus until the next command is executed, or until
+some other locus replaces it.
+If nil, don't highlight the locus in the source buffer.
+If `fringe-arrow', indicate the locus by the fringe arrow
+indefinitely until some other locus replaces it."
+  :type '(choice (number :tag "Highlight for specified time")
+                 (const :tag "Semipermanent highlighting" t)
+                 (const :tag "No highlighting" nil)
+                 (const :tag "Fringe arrow" fringe-arrow))
+  :group 'next-error
+  :version "22.1")
+
+(defcustom next-error-highlight-no-select 0.5
+  "Highlighting of locations in `next-error-no-select'.
+If number, highlight the locus in `next-error' face for given time in seconds.
+If t, highlight the locus indefinitely until some other locus replaces it.
+If nil, don't highlight the locus in the source buffer.
+If `fringe-arrow', indicate the locus by the fringe arrow
+indefinitely until some other locus replaces it."
+  :type '(choice (number :tag "Highlight for specified time")
+                 (const :tag "Semipermanent highlighting" t)
+                 (const :tag "No highlighting" nil)
+                 (const :tag "Fringe arrow" fringe-arrow))
+  :group 'next-error
+  :version "22.1")
+
+(defcustom next-error-recenter nil
+  "Display the line in the visited source file recentered as specified.
+If non-nil, the value is passed directly to `recenter'."
+  :type '(choice (integer :tag "Line to recenter to")
+                 (const :tag "Center of window" (4))
+                 (const :tag "No recentering" nil))
+  :group 'next-error
+  :version "23.1")
+
+(defcustom next-error-hook nil
+  "List of hook functions run by `next-error' after visiting source file."
+  :type 'hook
+  :group 'next-error)
+
+(defvar next-error-highlight-timer nil)
+
+(defvar next-error-overlay-arrow-position nil)
+(put 'next-error-overlay-arrow-position 'overlay-arrow-string (purecopy "=>"))
+(add-to-list 'overlay-arrow-variable-list 'next-error-overlay-arrow-position)
+
+(defvar next-error-last-buffer nil
+  "The most recent `next-error' buffer.
+A buffer becomes most recent when its compilation, grep, or
+similar mode is started, or when it is used with \\[next-error]
+or \\[compile-goto-error].")
+
+(defvar next-error-function nil
+  "Function to use to find the next error in the current buffer.
+The function is called with 2 parameters:
+ARG is an integer specifying by how many errors to move.
+RESET is a boolean which, if non-nil, says to go back to the beginning
+of the errors before moving.
+Major modes providing compile-like functionality should set this variable
+to indicate to `next-error' that this is a candidate buffer and how
+to navigate in it.")
+(make-variable-buffer-local 'next-error-function)
+
+(defvar next-error-move-function nil
+  "Function to use to move to an error locus.
+It takes two arguments, a buffer position in the error buffer
+and a buffer position in the error locus buffer.
+The buffer for the error locus should already be current.
+nil means use goto-char using the second argument position.")
+(make-variable-buffer-local 'next-error-move-function)
+
+(defsubst next-error-buffer-p (buffer
+                              &optional avoid-current
+                              extra-test-inclusive
+                              extra-test-exclusive)
+  "Test if BUFFER is a `next-error' capable buffer.
+
+If AVOID-CURRENT is non-nil, treat the current buffer
+as an absolute last resort only.
+
+The function EXTRA-TEST-INCLUSIVE, if non-nil, is called in each buffer
+that normally would not qualify.  If it returns t, the buffer
+in question is treated as usable.
+
+The function EXTRA-TEST-EXCLUSIVE, if non-nil, is called in each buffer
+that would normally be considered usable.  If it returns nil,
+that buffer is rejected."
+  (and (buffer-name buffer)            ;First make sure it's live.
+       (not (and avoid-current (eq buffer (current-buffer))))
+       (with-current-buffer buffer
+        (if next-error-function   ; This is the normal test.
+            ;; Optionally reject some buffers.
+            (if extra-test-exclusive
+                (funcall extra-test-exclusive)
+              t)
+          ;; Optionally accept some other buffers.
+          (and extra-test-inclusive
+               (funcall extra-test-inclusive))))))
+
+(defun next-error-find-buffer (&optional avoid-current
+                                        extra-test-inclusive
+                                        extra-test-exclusive)
+  "Return a `next-error' capable buffer.
+
+If AVOID-CURRENT is non-nil, treat the current buffer
+as an absolute last resort only.
+
+The function EXTRA-TEST-INCLUSIVE, if non-nil, is called in each buffer
+that normally would not qualify.  If it returns t, the buffer
+in question is treated as usable.
+
+The function EXTRA-TEST-EXCLUSIVE, if non-nil, is called in each buffer
+that would normally be considered usable.  If it returns nil,
+that buffer is rejected."
+  (or
+   ;; 1. If one window on the selected frame displays such buffer, return it.
+   (let ((window-buffers
+          (delete-dups
+           (delq nil (mapcar (lambda (w)
+                               (if (next-error-buffer-p
+                                   (window-buffer w)
+                                    avoid-current
+                                    extra-test-inclusive extra-test-exclusive)
+                                   (window-buffer w)))
+                             (window-list))))))
+     (if (eq (length window-buffers) 1)
+         (car window-buffers)))
+   ;; 2. If next-error-last-buffer is an acceptable buffer, use that.
+   (if (and next-error-last-buffer
+            (next-error-buffer-p next-error-last-buffer avoid-current
+                                 extra-test-inclusive extra-test-exclusive))
+       next-error-last-buffer)
+   ;; 3. If the current buffer is acceptable, choose it.
+   (if (next-error-buffer-p (current-buffer) avoid-current
+                           extra-test-inclusive extra-test-exclusive)
+       (current-buffer))
+   ;; 4. Look for any acceptable buffer.
+   (let ((buffers (buffer-list)))
+     (while (and buffers
+                 (not (next-error-buffer-p
+                      (car buffers) avoid-current
+                      extra-test-inclusive extra-test-exclusive)))
+       (setq buffers (cdr buffers)))
+     (car buffers))
+   ;; 5. Use the current buffer as a last resort if it qualifies,
+   ;; even despite AVOID-CURRENT.
+   (and avoid-current
+       (next-error-buffer-p (current-buffer) nil
+                            extra-test-inclusive extra-test-exclusive)
+       (progn
+         (message "This is the only buffer with error message locations")
+         (current-buffer)))
+   ;; 6. Give up.
+   (error "No buffers contain error message locations")))
+
+(defun next-error (&optional arg reset)
+  "Visit next `next-error' message and corresponding source code.
+
+If all the error messages parsed so far have been processed already,
+the message buffer is checked for new ones.
+
+A prefix ARG specifies how many error messages to move;
+negative means move back to previous error messages.
+Just \\[universal-argument] as a prefix means reparse the error message buffer
+and start at the first error.
+
+The RESET argument specifies that we should restart from the beginning.
+
+\\[next-error] normally uses the most recently started
+compilation, grep, or occur buffer.  It can also operate on any
+buffer with output from the \\[compile], \\[grep] commands, or,
+more generally, on any buffer in Compilation mode or with
+Compilation Minor mode enabled, or any buffer in which
+`next-error-function' is bound to an appropriate function.
+To specify use of a particular buffer for error messages, type
+\\[next-error] in that buffer when it is the only one displayed
+in the current frame.
+
+Once \\[next-error] has chosen the buffer for error messages, it
+runs `next-error-hook' with `run-hooks', and stays with that buffer
+until you use it in some other buffer which uses Compilation mode
+or Compilation Minor mode.
+
+To control which errors are matched, customize the variable
+`compilation-error-regexp-alist'."
+  (interactive "P")
+  (if (consp arg) (setq reset t arg nil))
+  (when (setq next-error-last-buffer (next-error-find-buffer))
+    ;; we know here that next-error-function is a valid symbol we can funcall
+    (with-current-buffer next-error-last-buffer
+      (funcall next-error-function (prefix-numeric-value arg) reset)
+      (when next-error-recenter
+        (recenter next-error-recenter))
+      (run-hooks 'next-error-hook))))
+
+(defun next-error-internal ()
+  "Visit the source code corresponding to the `next-error' message at point."
+  (setq next-error-last-buffer (current-buffer))
+  ;; we know here that next-error-function is a valid symbol we can funcall
+  (with-current-buffer next-error-last-buffer
+    (funcall next-error-function 0 nil)
+    (when next-error-recenter
+      (recenter next-error-recenter))
+    (run-hooks 'next-error-hook)))
+
+(defalias 'goto-next-locus 'next-error)
+(defalias 'next-match 'next-error)
+
+(defun previous-error (&optional n)
+  "Visit previous `next-error' message and corresponding source code.
+
+Prefix arg N says how many error messages to move backwards (or
+forwards, if negative).
+
+This operates on the output from the \\[compile] and \\[grep] commands."
+  (interactive "p")
+  (next-error (- (or n 1))))
+
+(defun first-error (&optional n)
+  "Restart at the first error.
+Visit corresponding source code.
+With prefix arg N, visit the source code of the Nth error.
+This operates on the output from the \\[compile] command, for instance."
+  (interactive "p")
+  (next-error n t))
+
+(defun next-error-no-select (&optional n)
+  "Move point to the next error in the `next-error' buffer and highlight match.
+Prefix arg N says how many error messages to move forwards (or
+backwards, if negative).
+Finds and highlights the source line like \\[next-error], but does not
+select the source buffer."
+  (interactive "p")
+  (let ((next-error-highlight next-error-highlight-no-select))
+    (next-error n))
+  (pop-to-buffer next-error-last-buffer))
+
+(defun previous-error-no-select (&optional n)
+  "Move point to the previous error in the `next-error' buffer and highlight 
match.
+Prefix arg N says how many error messages to move backwards (or
+forwards, if negative).
+Finds and highlights the source line like \\[previous-error], but does not
+select the source buffer."
+  (interactive "p")
+  (next-error-no-select (- (or n 1))))
+
+;; Internal variable for `next-error-follow-mode-post-command-hook'.
+(defvar next-error-follow-last-line nil)
+
+(define-minor-mode next-error-follow-minor-mode
+  "Minor mode for compilation, occur and diff modes.
+With a prefix argument ARG, enable mode if ARG is positive, and
+disable it otherwise.  If called from Lisp, enable mode if ARG is
+omitted or nil.
+When turned on, cursor motion in the compilation, grep, occur or diff
+buffer causes automatic display of the corresponding source code location."
+  :group 'next-error :init-value nil :lighter " Fol"
+  (if (not next-error-follow-minor-mode)
+      (remove-hook 'post-command-hook 
'next-error-follow-mode-post-command-hook t)
+    (add-hook 'post-command-hook 'next-error-follow-mode-post-command-hook nil 
t)
+    (make-local-variable 'next-error-follow-last-line)))
+
+;; Used as a `post-command-hook' by `next-error-follow-mode'
+;; for the *Compilation* *grep* and *Occur* buffers.
+(defun next-error-follow-mode-post-command-hook ()
+  (unless (equal next-error-follow-last-line (line-number-at-pos))
+    (setq next-error-follow-last-line (line-number-at-pos))
+    (condition-case nil
+       (let ((compilation-context-lines nil))
+         (setq compilation-current-error (point))
+         (next-error-no-select 0))
+      (error t))))
+
+
+;;;
+
+(defun fundamental-mode ()
+  "Major mode not specialized for anything in particular.
+Other major modes are defined by comparison with this one."
+  (interactive)
+  (kill-all-local-variables)
+  (run-mode-hooks))
+
+;; Special major modes to view specially formatted data rather than files.
+
+(defvar special-mode-map
+  (let ((map (make-sparse-keymap)))
+    (suppress-keymap map)
+    (define-key map "q" 'quit-window)
+    (define-key map " " 'scroll-up-command)
+    (define-key map [?\S-\ ] 'scroll-down-command)
+    (define-key map "\C-?" 'scroll-down-command)
+    (define-key map "?" 'describe-mode)
+    (define-key map "h" 'describe-mode)
+    (define-key map ">" 'end-of-buffer)
+    (define-key map "<" 'beginning-of-buffer)
+    (define-key map "g" 'revert-buffer)
+    map))
+
+(put 'special-mode 'mode-class 'special)
+(define-derived-mode special-mode nil "Special"
+  "Parent major mode from which special major modes should inherit."
+  (setq buffer-read-only t))
+
+;; Making and deleting lines.
+
+(defvar self-insert-uses-region-functions nil
+  "Special hook to tell if `self-insert-command' will use the region.
+It must be called via `run-hook-with-args-until-success' with no arguments.
+Any `post-self-insert-command' which consumes the region should
+register a function on this hook so that things like `delete-selection-mode'
+can refrain from consuming the region.")
+
+(defvar hard-newline (propertize "\n" 'hard t 'rear-nonsticky '(hard))
+  "Propertized string representing a hard newline character.")
+
+(defun newline (&optional arg interactive)
+  "Insert a newline, and move to left margin of the new line if it's blank.
+If option `use-hard-newlines' is non-nil, the newline is marked with the
+text-property `hard'.
+With ARG, insert that many newlines.
+
+If `electric-indent-mode' is enabled, this indents the final new line
+that it adds, and reindents the preceding line.  To just insert
+a newline, use \\[electric-indent-just-newline].
+
+Calls `auto-fill-function' if the current column number is greater
+than the value of `fill-column' and ARG is nil.
+A non-nil INTERACTIVE argument means to run the `post-self-insert-hook'."
+  (interactive "*P\np")
+  (barf-if-buffer-read-only)
+  ;; Call self-insert so that auto-fill, abbrev expansion etc. happens.
+  ;; Set last-command-event to tell self-insert what to insert.
+  (let* ((was-page-start (and (bolp) (looking-at page-delimiter)))
+         (beforepos (point))
+         (last-command-event ?\n)
+         ;; Don't auto-fill if we have a numeric argument.
+         (auto-fill-function (if arg nil auto-fill-function))
+         (postproc
+          ;; Do the rest in post-self-insert-hook, because we want to do it
+          ;; *before* other functions on that hook.
+          (lambda ()
+            (cl-assert (eq ?\n (char-before)))
+            ;; Mark the newline(s) `hard'.
+            (if use-hard-newlines
+                (set-hard-newline-properties
+                 (- (point) (prefix-numeric-value arg)) (point)))
+            ;; If the newline leaves the previous line blank, and we
+            ;; have a left margin, delete that from the blank line.
+            (save-excursion
+              (goto-char beforepos)
+              (beginning-of-line)
+              (and (looking-at "[ \t]$")
+                   (> (current-left-margin) 0)
+                   (delete-region (point)
+                                  (line-end-position))))
+            ;; Indent the line after the newline, except in one case:
+            ;; when we added the newline at the beginning of a line which
+            ;; starts a page.
+            (or was-page-start
+                (move-to-left-margin nil t)))))
+    (unwind-protect
+        (if (not interactive)
+        ;; FIXME: For non-interactive uses, many calls actually just want
+        ;; (insert "\n"), so maybe we should do just that, so as to avoid
+        ;; the risk of filling or running abbrevs unexpectedly.
+        (let ((post-self-insert-hook (list postproc)))
+          (self-insert-command (prefix-numeric-value arg)))
+      (unwind-protect
+          (progn
+            (add-hook 'post-self-insert-hook postproc nil t)
+            (self-insert-command (prefix-numeric-value arg)))
+        ;; We first used let-binding to protect the hook, but that was naive
+        ;; since add-hook affects the symbol-default value of the variable,
+        ;; whereas the let-binding might only protect the buffer-local value.
+        (remove-hook 'post-self-insert-hook postproc t)))
+      (cl-assert (not (member postproc post-self-insert-hook)))
+      (cl-assert (not (member postproc (default-value 
'post-self-insert-hook))))))
+  nil)
+
+(defun set-hard-newline-properties (from to)
+  (let ((sticky (get-text-property from 'rear-nonsticky)))
+    (put-text-property from to 'hard 't)
+    ;; If rear-nonsticky is not "t", add 'hard to rear-nonsticky list
+    (if (and (listp sticky) (not (memq 'hard sticky)))
+       (put-text-property from (point) 'rear-nonsticky
+                          (cons 'hard sticky)))))
+
+(defun open-line (n)
+  "Insert a newline and leave point before it.
+If there is a fill prefix and/or a `left-margin', insert them
+on the new line if the line would have been blank.
+With arg N, insert N newlines."
+  (interactive "*p")
+  (let* ((do-fill-prefix (and fill-prefix (bolp)))
+        (do-left-margin (and (bolp) (> (current-left-margin) 0)))
+        (loc (point-marker))
+        ;; Don't expand an abbrev before point.
+        (abbrev-mode nil))
+    (newline n)
+    (goto-char loc)
+    (while (> n 0)
+      (cond ((bolp)
+            (if do-left-margin (indent-to (current-left-margin)))
+            (if do-fill-prefix (insert-and-inherit fill-prefix))))
+      (forward-line 1)
+      (setq n (1- n)))
+    (goto-char loc)
+    (end-of-line)))
+
+(defun split-line (&optional arg)
+  "Split current line, moving portion beyond point vertically down.
+If the current line starts with `fill-prefix', insert it on the new
+line as well.  With prefix ARG, don't insert `fill-prefix' on new line.
+
+When called from Lisp code, ARG may be a prefix string to copy."
+  (interactive "*P")
+  (skip-chars-forward " \t")
+  (let* ((col (current-column))
+        (pos (point))
+        ;; What prefix should we check for (nil means don't).
+        (prefix (cond ((stringp arg) arg)
+                      (arg nil)
+                      (t fill-prefix)))
+        ;; Does this line start with it?
+        (have-prfx (and prefix
+                        (save-excursion
+                          (beginning-of-line)
+                          (looking-at (regexp-quote prefix))))))
+    (newline 1)
+    (if have-prfx (insert-and-inherit prefix))
+    (indent-to col 0)
+    (goto-char pos)))
+
+(defun delete-indentation (&optional arg)
+  "Join this line to previous and fix up whitespace at join.
+If there is a fill prefix, delete it from the beginning of this line.
+With argument, join this line to following line."
+  (interactive "*P")
+  (beginning-of-line)
+  (if arg (forward-line 1))
+  (if (eq (preceding-char) ?\n)
+      (progn
+       (delete-region (point) (1- (point)))
+       ;; If the second line started with the fill prefix,
+       ;; delete the prefix.
+       (if (and fill-prefix
+                (<= (+ (point) (length fill-prefix)) (point-max))
+                (string= fill-prefix
+                         (buffer-substring (point)
+                                           (+ (point) (length fill-prefix)))))
+           (delete-region (point) (+ (point) (length fill-prefix))))
+       (fixup-whitespace))))
+
+(defalias 'join-line #'delete-indentation) ; easier to find
+
+(defun delete-blank-lines ()
+  "On blank line, delete all surrounding blank lines, leaving just one.
+On isolated blank line, delete that one.
+On nonblank line, delete any immediately following blank lines."
+  (interactive "*")
+  (let (thisblank singleblank)
+    (save-excursion
+      (beginning-of-line)
+      (setq thisblank (looking-at "[ \t]*$"))
+      ;; Set singleblank if there is just one blank line here.
+      (setq singleblank
+           (and thisblank
+                (not (looking-at "[ \t]*\n[ \t]*$"))
+                (or (bobp)
+                    (progn (forward-line -1)
+                           (not (looking-at "[ \t]*$")))))))
+    ;; Delete preceding blank lines, and this one too if it's the only one.
+    (if thisblank
+       (progn
+         (beginning-of-line)
+         (if singleblank (forward-line 1))
+         (delete-region (point)
+                        (if (re-search-backward "[^ \t\n]" nil t)
+                            (progn (forward-line 1) (point))
+                          (point-min)))))
+    ;; Delete following blank lines, unless the current line is blank
+    ;; and there are no following blank lines.
+    (if (not (and thisblank singleblank))
+       (save-excursion
+         (end-of-line)
+         (forward-line 1)
+         (delete-region (point)
+                        (if (re-search-forward "[^ \t\n]" nil t)
+                            (progn (beginning-of-line) (point))
+                          (point-max)))))
+    ;; Handle the special case where point is followed by newline and eob.
+    ;; Delete the line, leaving point at eob.
+    (if (looking-at "^[ \t]*\n\\'")
+       (delete-region (point) (point-max)))))
+
+(defcustom delete-trailing-lines t
+  "If non-nil, \\[delete-trailing-whitespace] deletes trailing lines.
+Trailing lines are deleted only if `delete-trailing-whitespace'
+is called on the entire buffer (rather than an active region)."
+  :type 'boolean
+  :group 'editing
+  :version "24.3")
+
+(defun delete-trailing-whitespace (&optional start end)
+  "Delete trailing whitespace between START and END.
+If called interactively, START and END are the start/end of the
+region if the mark is active, or of the buffer's accessible
+portion if the mark is inactive.
+
+This command deletes whitespace characters after the last
+non-whitespace character in each line between START and END.  It
+does not consider formfeed characters to be whitespace.
+
+If this command acts on the entire buffer (i.e. if called
+interactively with the mark inactive, or called from Lisp with
+END nil), it also deletes all trailing lines at the end of the
+buffer if the variable `delete-trailing-lines' is non-nil."
+  (interactive (progn
+                 (barf-if-buffer-read-only)
+                 (if (use-region-p)
+                     (list (region-beginning) (region-end))
+                   (list nil nil))))
+  (save-match-data
+    (save-excursion
+      (let ((end-marker (copy-marker (or end (point-max))))
+            (start (or start (point-min))))
+        (goto-char start)
+        (while (re-search-forward "\\s-$" end-marker t)
+          (skip-syntax-backward "-" (line-beginning-position))
+          ;; Don't delete formfeeds, even if they are considered whitespace.
+          (if (looking-at-p ".*\f")
+              (goto-char (match-end 0)))
+          (delete-region (point) (match-end 0)))
+        ;; Delete trailing empty lines.
+        (goto-char end-marker)
+        (when (and (not end)
+                  delete-trailing-lines
+                   ;; Really the end of buffer.
+                  (= (point-max) (1+ (buffer-size)))
+                   (<= (skip-chars-backward "\n") -2))
+          (delete-region (1+ (point)) end-marker))
+        (set-marker end-marker nil))))
+  ;; Return nil for the benefit of `write-file-functions'.
+  nil)
+
+(defun newline-and-indent ()
+  "Insert a newline, then indent according to major mode.
+Indentation is done using the value of `indent-line-function'.
+In programming language modes, this is the same as TAB.
+In some text modes, where TAB inserts a tab, this command indents to the
+column specified by the function `current-left-margin'."
+  (interactive "*")
+  (delete-horizontal-space t)
+  (newline nil t)
+  (indent-according-to-mode))
+
+(defun reindent-then-newline-and-indent ()
+  "Reindent current line, insert newline, then indent the new line.
+Indentation of both lines is done according to the current major mode,
+which means calling the current value of `indent-line-function'.
+In programming language modes, this is the same as TAB.
+In some text modes, where TAB inserts a tab, this indents to the
+column specified by the function `current-left-margin'."
+  (interactive "*")
+  (let ((pos (point)))
+    ;; Be careful to insert the newline before indenting the line.
+    ;; Otherwise, the indentation might be wrong.
+    (newline)
+    (save-excursion
+      (goto-char pos)
+      ;; We are at EOL before the call to indent-according-to-mode, and
+      ;; after it we usually are as well, but not always.  We tried to
+      ;; address it with `save-excursion' but that uses a normal marker
+      ;; whereas we need `move after insertion', so we do the save/restore
+      ;; by hand.
+      (setq pos (copy-marker pos t))
+      (indent-according-to-mode)
+      (goto-char pos)
+      ;; Remove the trailing white-space after indentation because
+      ;; indentation may introduce the whitespace.
+      (delete-horizontal-space t))
+    (indent-according-to-mode)))
+
+(defcustom read-quoted-char-radix 8
+  "Radix for \\[quoted-insert] and other uses of `read-quoted-char'.
+Legitimate radix values are 8, 10 and 16."
+ :type '(choice (const 8) (const 10) (const 16))
+ :group 'editing-basics)
+
+(defun read-quoted-char (&optional prompt)
+  "Like `read-char', but do not allow quitting.
+Also, if the first character read is an octal digit,
+we read any number of octal digits and return the
+specified character code.  Any nondigit terminates the sequence.
+If the terminator is RET, it is discarded;
+any other terminator is used itself as input.
+
+The optional argument PROMPT specifies a string to use to prompt the user.
+The variable `read-quoted-char-radix' controls which radix to use
+for numeric input."
+  (let ((message-log-max nil)
+       (help-events (delq nil (mapcar (lambda (c) (unless (characterp c) c))
+                                      help-event-list)))
+       done (first t) (code 0) translated)
+    (while (not done)
+      (let ((inhibit-quit first)
+           ;; Don't let C-h or other help chars get the help
+           ;; message--only help function keys.  See bug#16617.
+           (help-char nil)
+           (help-event-list help-events)
+           (help-form
+            "Type the special character you want to use,
+or the octal character code.
+RET terminates the character code and is discarded;
+any other non-digit terminates the character code and is then used as input."))
+       (setq translated (read-key (and prompt (format "%s-" prompt))))
+       (if inhibit-quit (setq quit-flag nil)))
+      (if (integerp translated)
+         (setq translated (char-resolve-modifiers translated)))
+      (cond ((null translated))
+           ((not (integerp translated))
+            (setq unread-command-events
+                   (listify-key-sequence (this-single-command-raw-keys))
+                  done t))
+           ((/= (logand translated ?\M-\^@) 0)
+            ;; Turn a meta-character into a character with the 0200 bit set.
+            (setq code (logior (logand translated (lognot ?\M-\^@)) 128)
+                  done t))
+           ((and (<= ?0 translated)
+                  (< translated (+ ?0 (min 10 read-quoted-char-radix))))
+            (setq code (+ (* code read-quoted-char-radix) (- translated ?0)))
+            (and prompt (setq prompt (message "%s %c" prompt translated))))
+           ((and (<= ?a (downcase translated))
+                 (< (downcase translated)
+                     (+ ?a -10 (min 36 read-quoted-char-radix))))
+            (setq code (+ (* code read-quoted-char-radix)
+                          (+ 10 (- (downcase translated) ?a))))
+            (and prompt (setq prompt (message "%s %c" prompt translated))))
+           ((and (not first) (eq translated ?\C-m))
+            (setq done t))
+           ((not first)
+            (setq unread-command-events
+                   (listify-key-sequence (this-single-command-raw-keys))
+                  done t))
+           (t (setq code translated
+                    done t)))
+      (setq first nil))
+    code))
+
+(defun quoted-insert (arg)
+  "Read next input character and insert it.
+This is useful for inserting control characters.
+With argument, insert ARG copies of the character.
+
+If the first character you type after this command is an octal digit,
+you should type a sequence of octal digits which specify a character code.
+Any nondigit terminates the sequence.  If the terminator is a RET,
+it is discarded; any other terminator is used itself as input.
+The variable `read-quoted-char-radix' specifies the radix for this feature;
+set it to 10 or 16 to use decimal or hex instead of octal.
+
+In overwrite mode, this function inserts the character anyway, and
+does not handle octal digits specially.  This means that if you use
+overwrite as your normal editing mode, you can use this function to
+insert characters when necessary.
+
+In binary overwrite mode, this function does overwrite, and octal
+digits are interpreted as a character code.  This is intended to be
+useful for editing binary files."
+  (interactive "*p")
+  (let* ((char
+         ;; Avoid "obsolete" warnings for translation-table-for-input.
+         (with-no-warnings
+           (let (translation-table-for-input input-method-function)
+             (if (or (not overwrite-mode)
+                     (eq overwrite-mode 'overwrite-mode-binary))
+                 (read-quoted-char)
+               (read-char))))))
+    ;; This used to assume character codes 0240 - 0377 stand for
+    ;; characters in some single-byte character set, and converted them
+    ;; to Emacs characters.  But in 23.1 this feature is deprecated
+    ;; in favor of inserting the corresponding Unicode characters.
+    ;; (if (and enable-multibyte-characters
+    ;;          (>= char ?\240)
+    ;;          (<= char ?\377))
+    ;;     (setq char (unibyte-char-to-multibyte char)))
+    (unless (characterp char)
+      (user-error "%s is not a valid character"
+                 (key-description (vector char))))
+    (if (> arg 0)
+       (if (eq overwrite-mode 'overwrite-mode-binary)
+           (delete-char arg)))
+    (while (> arg 0)
+      (insert-and-inherit char)
+      (setq arg (1- arg)))))
+
+(defun forward-to-indentation (&optional arg)
+  "Move forward ARG lines and position at first nonblank character."
+  (interactive "^p")
+  (forward-line (or arg 1))
+  (skip-chars-forward " \t"))
+
+(defun backward-to-indentation (&optional arg)
+  "Move backward ARG lines and position at first nonblank character."
+  (interactive "^p")
+  (forward-line (- (or arg 1)))
+  (skip-chars-forward " \t"))
+
+(defun back-to-indentation ()
+  "Move point to the first non-whitespace character on this line."
+  (interactive "^")
+  (beginning-of-line 1)
+  (skip-syntax-forward " " (line-end-position))
+  ;; Move back over chars that have whitespace syntax but have the p flag.
+  (backward-prefix-chars))
+
+(defun fixup-whitespace ()
+  "Fixup white space between objects around point.
+Leave one space or none, according to the context."
+  (interactive "*")
+  (save-excursion
+    (delete-horizontal-space)
+    (if (or (looking-at "^\\|\\s)")
+           (save-excursion (forward-char -1)
+                           (looking-at "$\\|\\s(\\|\\s'")))
+       nil
+      (insert ?\s))))
+
+(defun delete-horizontal-space (&optional backward-only)
+  "Delete all spaces and tabs around point.
+If BACKWARD-ONLY is non-nil, only delete them before point."
+  (interactive "*P")
+  (let ((orig-pos (point)))
+    (delete-region
+     (if backward-only
+        orig-pos
+       (progn
+        (skip-chars-forward " \t")
+        (constrain-to-field nil orig-pos t)))
+     (progn
+       (skip-chars-backward " \t")
+       (constrain-to-field nil orig-pos)))))
+
+(defun just-one-space (&optional n)
+  "Delete all spaces and tabs around point, leaving one space (or N spaces).
+If N is negative, delete newlines as well, leaving -N spaces.
+See also `cycle-spacing'."
+  (interactive "*p")
+  (cycle-spacing n nil t))
+
+(defvar cycle-spacing--context nil
+  "Store context used in consecutive calls to `cycle-spacing' command.
+The first time this function is run, it saves the original point
+position and original spacing around the point in this
+variable.")
+
+(defun cycle-spacing (&optional n preserve-nl-back single-shot)
+  "Manipulate whitespace around point in a smart way.
+In interactive use, this function behaves differently in successive
+consecutive calls.
+
+The first call in a sequence acts like `just-one-space'.
+It deletes all spaces and tabs around point, leaving one space
+\(or N spaces).  N is the prefix argument.  If N is negative,
+it deletes newlines as well, leaving -N spaces.
+\(If PRESERVE-NL-BACK is non-nil, it does not delete newlines before point.)
+
+The second call in a sequence (or the first call if the above does
+not result in any changes) deletes all spaces.
+
+The third call in a sequence restores the original whitespace (and point).
+
+If SINGLE-SHOT is non-nil, it only performs the first step in the sequence."
+  (interactive "*p")
+  (let ((orig-pos       (point))
+       (skip-characters (if (and n (< n 0)) " \t\n\r" " \t"))
+       (n               (abs (or n 1))))
+    (skip-chars-backward (if preserve-nl-back " \t" skip-characters))
+    (constrain-to-field nil orig-pos)
+    (cond
+     ;; Command run for the first time or single-shot is non-nil.
+     ((or single-shot
+         (not (equal last-command this-command))
+         (not cycle-spacing--context))
+      (let* ((start (point))
+            (n     (- n (skip-chars-forward " " (+ n (point)))))
+            (mid   (point))
+            (end   (progn
+                     (skip-chars-forward skip-characters)
+                     (constrain-to-field nil orig-pos t))))
+       (setq cycle-spacing--context  ;; Save for later.
+             ;; Special handling for case where there was no space at all.
+             (unless (= start end)
+               (cons orig-pos (buffer-substring start (point)))))
+       ;; If this run causes no change in buffer content, delete all spaces,
+       ;; otherwise delete all excess spaces.
+       (delete-region (if (and (not single-shot) (zerop n) (= mid end))
+                          start mid) end)
+        (insert (make-string n ?\s))))
+
+     ;; Command run for the second time.
+     ((not (equal orig-pos (point)))
+      (delete-region (point) orig-pos))
+
+     ;; Command run for the third time.
+     (t
+      (insert (cdr cycle-spacing--context))
+      (goto-char (car cycle-spacing--context))
+      (setq cycle-spacing--context nil)))))
+
+(defun beginning-of-buffer (&optional arg)
+  "Move point to the beginning of the buffer.
+With numeric arg N, put point N/10 of the way from the beginning.
+If the buffer is narrowed, this command uses the beginning of the
+accessible part of the buffer.
+
+If Transient Mark mode is disabled, leave mark at previous
+position, unless a \\[universal-argument] prefix is supplied.
+
+Don't use this command in Lisp programs!
+\(goto-char (point-min)) is faster."
+  (interactive "^P")
+  (or (consp arg)
+      (region-active-p)
+      (push-mark))
+  (let ((size (- (point-max) (point-min))))
+    (goto-char (if (and arg (not (consp arg)))
+                  (+ (point-min)
+                     (if (> size 10000)
+                         ;; Avoid overflow for large buffer sizes!
+                         (* (prefix-numeric-value arg)
+                            (/ size 10))
+                       (/ (+ 10 (* size (prefix-numeric-value arg))) 10)))
+                (point-min))))
+  (if (and arg (not (consp arg))) (forward-line 1)))
+(put 'beginning-of-buffer 'interactive-only
+     "use `(goto-char (point-min))' instead.")
+
+(defun end-of-buffer (&optional arg)
+  "Move point to the end of the buffer.
+With numeric arg N, put point N/10 of the way from the end.
+If the buffer is narrowed, this command uses the end of the
+accessible part of the buffer.
+
+If Transient Mark mode is disabled, leave mark at previous
+position, unless a \\[universal-argument] prefix is supplied.
+
+Don't use this command in Lisp programs!
+\(goto-char (point-max)) is faster."
+  (interactive "^P")
+  (or (consp arg) (region-active-p) (push-mark))
+  (let ((size (- (point-max) (point-min))))
+    (goto-char (if (and arg (not (consp arg)))
+                  (- (point-max)
+                     (if (> size 10000)
+                         ;; Avoid overflow for large buffer sizes!
+                         (* (prefix-numeric-value arg)
+                            (/ size 10))
+                       (/ (* size (prefix-numeric-value arg)) 10)))
+                (point-max))))
+  ;; If we went to a place in the middle of the buffer,
+  ;; adjust it to the beginning of a line.
+  (cond ((and arg (not (consp arg))) (forward-line 1))
+       ((and (eq (current-buffer) (window-buffer))
+              (> (point) (window-end nil t)))
+        ;; If the end of the buffer is not already on the screen,
+        ;; then scroll specially to put it near, but not at, the bottom.
+        (overlay-recenter (point))
+        (recenter -3))))
+(put 'end-of-buffer 'interactive-only "use `(goto-char (point-max))' instead.")
+
+(defcustom delete-active-region t
+  "Whether single-char deletion commands delete an active region.
+This has an effect only if Transient Mark mode is enabled, and
+affects `delete-forward-char' and `delete-backward-char', though
+not `delete-char'.
+
+If the value is the symbol `kill', the active region is killed
+instead of deleted."
+  :type '(choice (const :tag "Delete active region" t)
+                 (const :tag "Kill active region" kill)
+                 (const :tag "Do ordinary deletion" nil))
+  :group 'killing
+  :version "24.1")
+
+(defvar region-extract-function
+  (lambda (delete)
+    (when (region-beginning)
+      (if (eq delete 'delete-only)
+          (delete-region (region-beginning) (region-end))
+        (filter-buffer-substring (region-beginning) (region-end) delete))))
+  "Function to get the region's content.
+Called with one argument DELETE.
+If DELETE is `delete-only', then only delete the region and the return value
+is undefined.  If DELETE is nil, just return the content as a string.
+If anything else, delete the region and return its content as a string.")
+
+(defun delete-backward-char (n &optional killflag)
+  "Delete the previous N characters (following if N is negative).
+If Transient Mark mode is enabled, the mark is active, and N is 1,
+delete the text in the region and deactivate the mark instead.
+To disable this, set option `delete-active-region' to nil.
+
+Optional second arg KILLFLAG, if non-nil, means to kill (save in
+kill ring) instead of delete.  Interactively, N is the prefix
+arg, and KILLFLAG is set if N is explicitly specified.
+
+In Overwrite mode, single character backward deletion may replace
+tabs with spaces so as to back over columns, unless point is at
+the end of the line."
+  (interactive "p\nP")
+  (unless (integerp n)
+    (signal 'wrong-type-argument (list 'integerp n)))
+  (cond ((and (use-region-p)
+             delete-active-region
+             (= n 1))
+        ;; If a region is active, kill or delete it.
+        (if (eq delete-active-region 'kill)
+            (kill-region (region-beginning) (region-end) 'region)
+           (funcall region-extract-function 'delete-only)))
+       ;; In Overwrite mode, maybe untabify while deleting
+       ((null (or (null overwrite-mode)
+                  (<= n 0)
+                  (memq (char-before) '(?\t ?\n))
+                  (eobp)
+                  (eq (char-after) ?\n)))
+        (let ((ocol (current-column)))
+           (delete-char (- n) killflag)
+          (save-excursion
+            (insert-char ?\s (- ocol (current-column)) nil))))
+       ;; Otherwise, do simple deletion.
+       (t (delete-char (- n) killflag))))
+(put 'delete-backward-char 'interactive-only 'delete-char)
+
+(defun delete-forward-char (n &optional killflag)
+  "Delete the following N characters (previous if N is negative).
+If Transient Mark mode is enabled, the mark is active, and N is 1,
+delete the text in the region and deactivate the mark instead.
+To disable this, set variable `delete-active-region' to nil.
+
+Optional second arg KILLFLAG non-nil means to kill (save in kill
+ring) instead of delete.  Interactively, N is the prefix arg, and
+KILLFLAG is set if N was explicitly specified."
+  (interactive "p\nP")
+  (unless (integerp n)
+    (signal 'wrong-type-argument (list 'integerp n)))
+  (cond ((and (use-region-p)
+             delete-active-region
+             (= n 1))
+        ;; If a region is active, kill or delete it.
+        (if (eq delete-active-region 'kill)
+            (kill-region (region-beginning) (region-end) 'region)
+          (funcall region-extract-function 'delete-only)))
+
+       ;; Otherwise, do simple deletion.
+       (t (delete-char n killflag))))
+(put 'delete-forward-char 'interactive-only 'delete-char)
+
+(defun mark-whole-buffer ()
+  "Put point at beginning and mark at end of buffer.
+If narrowing is in effect, only uses the accessible part of the buffer.
+You probably should not use this function in Lisp programs;
+it is usually a mistake for a Lisp function to use any subroutine
+that uses or sets the mark."
+  (interactive)
+  (push-mark (point))
+  (push-mark (point-max) nil t)
+  (goto-char (point-min)))
+
+
+;; Counting lines, one way or another.
+
+(defun goto-line (line &optional buffer)
+  "Go to LINE, counting from line 1 at beginning of buffer.
+If called interactively, a numeric prefix argument specifies
+LINE; without a numeric prefix argument, read LINE from the
+minibuffer.
+
+If optional argument BUFFER is non-nil, switch to that buffer and
+move to line LINE there.  If called interactively with \\[universal-argument]
+as argument, BUFFER is the most recently selected other buffer.
+
+Prior to moving point, this function sets the mark (without
+activating it), unless Transient Mark mode is enabled and the
+mark is already active.
+
+This function is usually the wrong thing to use in a Lisp program.
+What you probably want instead is something like:
+  (goto-char (point-min))
+  (forward-line (1- N))
+If at all possible, an even better solution is to use char counts
+rather than line counts."
+  (interactive
+   (if (and current-prefix-arg (not (consp current-prefix-arg)))
+       (list (prefix-numeric-value current-prefix-arg))
+     ;; Look for a default, a number in the buffer at point.
+     (let* ((default
+             (save-excursion
+               (skip-chars-backward "0-9")
+               (if (looking-at "[0-9]")
+                   (string-to-number
+                    (buffer-substring-no-properties
+                     (point)
+                     (progn (skip-chars-forward "0-9")
+                            (point)))))))
+           ;; Decide if we're switching buffers.
+           (buffer
+            (if (consp current-prefix-arg)
+                (other-buffer (current-buffer) t)))
+           (buffer-prompt
+            (if buffer
+                (concat " in " (buffer-name buffer))
+              "")))
+       ;; Read the argument, offering that number (if any) as default.
+       (list (read-number (format "Goto line%s: " buffer-prompt)
+                          (list default (line-number-at-pos)))
+            buffer))))
+  ;; Switch to the desired buffer, one way or another.
+  (if buffer
+      (let ((window (get-buffer-window buffer)))
+       (if window (select-window window)
+         (switch-to-buffer-other-window buffer))))
+  ;; Leave mark at previous position
+  (or (region-active-p) (push-mark))
+  ;; Move to the specified line number in that buffer.
+  (save-restriction
+    (widen)
+    (goto-char (point-min))
+    (if (eq selective-display t)
+       (re-search-forward "[\n\C-m]" nil 'end (1- line))
+      (forward-line (1- line)))))
+(put 'goto-line 'interactive-only 'forward-line)
+
+(defun count-words-region (start end &optional arg)
+  "Count the number of words in the region.
+If called interactively, print a message reporting the number of
+lines, words, and characters in the region (whether or not the
+region is active); with prefix ARG, report for the entire buffer
+rather than the region.
+
+If called from Lisp, return the number of words between positions
+START and END."
+  (interactive (if current-prefix-arg
+                  (list nil nil current-prefix-arg)
+                (list (region-beginning) (region-end) nil)))
+  (cond ((not (called-interactively-p 'any))
+        (count-words start end))
+       (arg
+        (count-words--buffer-message))
+       (t
+        (count-words--message "Region" start end))))
+
+(defun count-words (start end)
+  "Count words between START and END.
+If called interactively, START and END are normally the start and
+end of the buffer; but if the region is active, START and END are
+the start and end of the region.  Print a message reporting the
+number of lines, words, and chars.
+
+If called from Lisp, return the number of words between START and
+END, without printing any message."
+  (interactive (list nil nil))
+  (cond ((not (called-interactively-p 'any))
+        (let ((words 0))
+          (save-excursion
+            (save-restriction
+              (narrow-to-region start end)
+              (goto-char (point-min))
+              (while (forward-word 1)
+                (setq words (1+ words)))))
+          words))
+       ((use-region-p)
+        (call-interactively 'count-words-region))
+       (t
+        (count-words--buffer-message))))
+
+(defun count-words--buffer-message ()
+  (count-words--message
+   (if (buffer-narrowed-p) "Narrowed part of buffer" "Buffer")
+   (point-min) (point-max)))
+
+(defun count-words--message (str start end)
+  (let ((lines (count-lines start end))
+       (words (count-words start end))
+       (chars (- end start)))
+    (message "%s has %d line%s, %d word%s, and %d character%s."
+            str
+            lines (if (= lines 1) "" "s")
+            words (if (= words 1) "" "s")
+            chars (if (= chars 1) "" "s"))))
+
+(define-obsolete-function-alias 'count-lines-region 'count-words-region "24.1")
+
+(defun what-line ()
+  "Print the current buffer line number and narrowed line number of point."
+  (interactive)
+  (let ((start (point-min))
+       (n (line-number-at-pos)))
+    (if (= start 1)
+       (message "Line %d" n)
+      (save-excursion
+       (save-restriction
+         (widen)
+         (message "line %d (narrowed line %d)"
+                  (+ n (line-number-at-pos start) -1) n))))))
+
+(defun count-lines (start end)
+  "Return number of lines between START and END.
+This is usually the number of newlines between them,
+but can be one more if START is not equal to END
+and the greater of them is not at the start of a line."
+  (save-excursion
+    (save-restriction
+      (narrow-to-region start end)
+      (goto-char (point-min))
+      (if (eq selective-display t)
+         (save-match-data
+           (let ((done 0))
+                     (while (re-search-forward "[\n\C-m]" nil t 40)
+                       (setq done (+ 40 done)))
+                     (while (re-search-forward "[\n\C-m]" nil t 1)
+                       (setq done (+ 1 done)))
+                     (goto-char (point-max))
+                     (if (and (/= start end)
+                      (not (bolp)))
+                 (1+ done)
+               done)))
+       (- (buffer-size) (forward-line (buffer-size)))))))
+
+(defun line-number-at-pos (&optional pos)
+  "Return (narrowed) buffer line number at position POS.
+If POS is nil, use current buffer location.
+Counting starts at (point-min), so the value refers
+to the contents of the accessible portion of the buffer."
+  (let ((opoint (or pos (point))) start)
+    (save-excursion
+      (goto-char (point-min))
+      (setq start (point))
+      (goto-char opoint)
+      (forward-line 0)
+      (1+ (count-lines start (point))))))
+
+(defun what-cursor-position (&optional detail)
+  "Print info on cursor position (on screen and within buffer).
+Also describe the character after point, and give its character code
+in octal, decimal and hex.
+
+For a non-ASCII multibyte character, also give its encoding in the
+buffer's selected coding system if the coding system encodes the
+character safely.  If the character is encoded into one byte, that
+code is shown in hex.  If the character is encoded into more than one
+byte, just \"...\" is shown.
+
+In addition, with prefix argument, show details about that character
+in *Help* buffer.  See also the command `describe-char'."
+  (interactive "P")
+  (let* ((char (following-char))
+        (bidi-fixer
+         (cond ((memq char '(?\x202a ?\x202b ?\x202d ?\x202e))
+                ;; If the character is one of LRE, LRO, RLE, RLO, it
+                ;; will start a directional embedding, which could
+                ;; completely disrupt the rest of the line (e.g., RLO
+                ;; will display the rest of the line right-to-left).
+                ;; So we put an invisible PDF character after these
+                ;; characters, to end the embedding, which eliminates
+                ;; any effects on the rest of the line.
+                (propertize (string ?\x202c) 'invisible t))
+               ;; Strong right-to-left characters cause reordering of
+               ;; the following numerical characters which show the
+               ;; codepoint, so append LRM to countermand that.
+               ((memq (get-char-code-property char 'bidi-class) '(R AL))
+                (propertize (string ?\x200e) 'invisible t))
+               (t
+                "")))
+        (beg (point-min))
+        (end (point-max))
+         (pos (point))
+        (total (buffer-size))
+        (percent (if (> total 50000)
+                     ;; Avoid overflow from multiplying by 100!
+                     (/ (+ (/ total 200) (1- pos)) (max (/ total 100) 1))
+                   (/ (+ (/ total 2) (* 100 (1- pos))) (max total 1))))
+        (hscroll (if (= (window-hscroll) 0)
+                     ""
+                   (format " Hscroll=%d" (window-hscroll))))
+        (col (current-column)))
+    (if (= pos end)
+       (if (or (/= beg 1) (/= end (1+ total)))
+           (message "point=%d of %d (%d%%) <%d-%d> column=%d%s"
+                    pos total percent beg end col hscroll)
+         (message "point=%d of %d (EOB) column=%d%s"
+                  pos total col hscroll))
+      (let ((coding buffer-file-coding-system)
+           encoded encoding-msg display-prop under-display)
+       (if (or (not coding)
+               (eq (coding-system-type coding) t))
+           (setq coding (default-value 'buffer-file-coding-system)))
+       (if (eq (char-charset char) 'eight-bit)
+           (setq encoding-msg
+                 (format "(%d, #o%o, #x%x, raw-byte)" char char char))
+         ;; Check if the character is displayed with some `display'
+         ;; text property.  In that case, set under-display to the
+         ;; buffer substring covered by that property.
+         (setq display-prop (get-char-property pos 'display))
+         (if display-prop
+             (let ((to (or (next-single-char-property-change pos 'display)
+                           (point-max))))
+               (if (< to (+ pos 4))
+                   (setq under-display "")
+                 (setq under-display "..."
+                       to (+ pos 4)))
+               (setq under-display
+                     (concat (buffer-substring-no-properties pos to)
+                             under-display)))
+           (setq encoded (and (>= char 128) (encode-coding-char char coding))))
+         (setq encoding-msg
+               (if display-prop
+                   (if (not (stringp display-prop))
+                       (format "(%d, #o%o, #x%x, part of display \"%s\")"
+                               char char char under-display)
+                     (format "(%d, #o%o, #x%x, part of display \"%s\"->\"%s\")"
+                             char char char under-display display-prop))
+                 (if encoded
+                     (format "(%d, #o%o, #x%x, file %s)"
+                             char char char
+                             (if (> (length encoded) 1)
+                                 "..."
+                               (encoded-string-description encoded coding)))
+                   (format "(%d, #o%o, #x%x)" char char char)))))
+       (if detail
+           ;; We show the detailed information about CHAR.
+           (describe-char (point)))
+       (if (or (/= beg 1) (/= end (1+ total)))
+           (message "Char: %s%s %s point=%d of %d (%d%%) <%d-%d> column=%d%s"
+                    (if (< char 256)
+                        (single-key-description char)
+                      (buffer-substring-no-properties (point) (1+ (point))))
+                    bidi-fixer
+                    encoding-msg pos total percent beg end col hscroll)
+         (message "Char: %s%s %s point=%d of %d (%d%%) column=%d%s"
+                  (if enable-multibyte-characters
+                      (if (< char 128)
+                          (single-key-description char)
+                        (buffer-substring-no-properties (point) (1+ (point))))
+                    (single-key-description char))
+                  bidi-fixer encoding-msg pos total percent col hscroll))))))
+
+;; Initialize read-expression-map.  It is defined at C level.
+(defvar read-expression-map
+  (let ((m (make-sparse-keymap)))
+    (define-key m "\M-\t" 'completion-at-point)
+    ;; Might as well bind TAB to completion, since inserting a TAB char is
+    ;; much too rarely useful.
+    (define-key m "\t" 'completion-at-point)
+    (set-keymap-parent m minibuffer-local-map)
+    m))
+
+(defun read-minibuffer (prompt &optional initial-contents)
+  "Return a Lisp object read using the minibuffer, unevaluated.
+Prompt with PROMPT.  If non-nil, optional second arg INITIAL-CONTENTS
+is a string to insert in the minibuffer before reading.
+\(INITIAL-CONTENTS can also be a cons of a string and an integer.
+Such arguments are used as in `read-from-minibuffer'.)"
+  ;; Used for interactive spec `x'.
+  (read-from-minibuffer prompt initial-contents minibuffer-local-map
+                        t 'minibuffer-history))
+
+(defun eval-minibuffer (prompt &optional initial-contents)
+  "Return value of Lisp expression read using the minibuffer.
+Prompt with PROMPT.  If non-nil, optional second arg INITIAL-CONTENTS
+is a string to insert in the minibuffer before reading.
+\(INITIAL-CONTENTS can also be a cons of a string and an integer.
+Such arguments are used as in `read-from-minibuffer'.)"
+  ;; Used for interactive spec `X'.
+  (eval (read--expression prompt initial-contents)))
+
+(defvar minibuffer-completing-symbol nil
+  "Non-nil means completing a Lisp symbol in the minibuffer.")
+(make-obsolete-variable 'minibuffer-completing-symbol nil "24.1" 'get)
+
+(defvar minibuffer-default nil
+  "The current default value or list of default values in the minibuffer.
+The functions `read-from-minibuffer' and `completing-read' bind
+this variable locally.")
+
+(defcustom eval-expression-print-level 4
+  "Value for `print-level' while printing value in `eval-expression'.
+A value of nil means no limit."
+  :group 'lisp
+  :type '(choice (const :tag "No Limit" nil) integer)
+  :version "21.1")
+
+(defcustom eval-expression-print-length 12
+  "Value for `print-length' while printing value in `eval-expression'.
+A value of nil means no limit."
+  :group 'lisp
+  :type '(choice (const :tag "No Limit" nil) integer)
+  :version "21.1")
+
+(defcustom eval-expression-debug-on-error t
+  "If non-nil set `debug-on-error' to t in `eval-expression'.
+If nil, don't change the value of `debug-on-error'."
+  :group 'lisp
+  :type 'boolean
+  :version "21.1")
+
+(defun eval-expression-print-format (value)
+  "Format VALUE as a result of evaluated expression.
+Return a formatted string which is displayed in the echo area
+in addition to the value printed by prin1 in functions which
+display the result of expression evaluation."
+  (if (and (integerp value)
+          (or (eq standard-output t)
+              (zerop (prefix-numeric-value current-prefix-arg))))
+      (let ((char-string
+            (if (and (characterp value)
+                     (char-displayable-p value))
+                (prin1-char value))))
+        (if char-string
+            (format " (#o%o, #x%x, %s)" value value char-string)
+          (format " (#o%o, #x%x)" value value)))))
+
+(defvar eval-expression-minibuffer-setup-hook nil
+  "Hook run by `eval-expression' when entering the minibuffer.")
+
+(defun read--expression (prompt &optional initial-contents)
+  (let ((minibuffer-completing-symbol t))
+    (minibuffer-with-setup-hook
+        (lambda ()
+          (add-hook 'completion-at-point-functions
+                    #'lisp-completion-at-point nil t)
+          (run-hooks 'eval-expression-minibuffer-setup-hook))
+      (read-from-minibuffer prompt initial-contents
+                            read-expression-map t
+                            'read-expression-history))))
+
+;; We define this, rather than making `eval' interactive,
+;; for the sake of completion of names like eval-region, eval-buffer.
+(defun eval-expression (exp &optional insert-value)
+  "Evaluate EXP and print value in the echo area.
+When called interactively, read an Emacs Lisp expression and evaluate it.
+Value is also consed on to front of the variable `values'.
+Optional argument INSERT-VALUE non-nil (interactively, with prefix
+argument) means insert the result into the current buffer instead of
+printing it in the echo area.
+
+Normally, this function truncates long output according to the value
+of the variables `eval-expression-print-length' and
+`eval-expression-print-level'.  With a prefix argument of zero,
+however, there is no such truncation.  Such a prefix argument
+also causes integers to be printed in several additional formats
+\(octal, hexadecimal, and character).
+
+Runs the hook `eval-expression-minibuffer-setup-hook' on entering the
+minibuffer.
+
+If `eval-expression-debug-on-error' is non-nil, which is the default,
+this command arranges for all errors to enter the debugger."
+  (interactive
+   (list (read--expression "Eval: ")
+        current-prefix-arg))
+
+  (if (null eval-expression-debug-on-error)
+      (push (eval exp lexical-binding) values)
+    (let ((old-value (make-symbol "t")) new-value)
+      ;; Bind debug-on-error to something unique so that we can
+      ;; detect when evalled code changes it.
+      (let ((debug-on-error old-value))
+       (push (eval exp lexical-binding) values)
+       (setq new-value debug-on-error))
+      ;; If evalled code has changed the value of debug-on-error,
+      ;; propagate that change to the global binding.
+      (unless (eq old-value new-value)
+       (setq debug-on-error new-value))))
+
+  (let ((print-length (and (not (zerop (prefix-numeric-value insert-value)))
+                          eval-expression-print-length))
+       (print-level (and (not (zerop (prefix-numeric-value insert-value)))
+                         eval-expression-print-level))
+        (deactivate-mark))
+    (if insert-value
+       (with-no-warnings
+        (let ((standard-output (current-buffer)))
+          (prog1
+              (prin1 (car values))
+            (when (zerop (prefix-numeric-value insert-value))
+              (let ((str (eval-expression-print-format (car values))))
+                (if str (princ str)))))))
+      (prog1
+          (prin1 (car values) t)
+        (let ((str (eval-expression-print-format (car values))))
+          (if str (princ str t)))))))
+
+(defun edit-and-eval-command (prompt command)
+  "Prompting with PROMPT, let user edit COMMAND and eval result.
+COMMAND is a Lisp expression.  Let user edit that expression in
+the minibuffer, then read and evaluate the result."
+  (let ((command
+        (let ((print-level nil)
+              (minibuffer-history-sexp-flag (1+ (minibuffer-depth))))
+          (unwind-protect
+              (read-from-minibuffer prompt
+                                    (prin1-to-string command)
+                                    read-expression-map t
+                                    'command-history)
+            ;; If command was added to command-history as a string,
+            ;; get rid of that.  We want only evaluable expressions there.
+            (if (stringp (car command-history))
+                (setq command-history (cdr command-history)))))))
+
+    ;; If command to be redone does not match front of history,
+    ;; add it to the history.
+    (or (equal command (car command-history))
+       (setq command-history (cons command command-history)))
+    (eval command)))
+
+(defun repeat-complex-command (arg)
+  "Edit and re-evaluate last complex command, or ARGth from last.
+A complex command is one which used the minibuffer.
+The command is placed in the minibuffer as a Lisp form for editing.
+The result is executed, repeating the command as changed.
+If the command has been changed or is not the most recent previous
+command it is added to the front of the command history.
+You can use the minibuffer history commands \
+\\<minibuffer-local-map>\\[next-history-element] and 
\\[previous-history-element]
+to get different commands to edit and resubmit."
+  (interactive "p")
+  (let ((elt (nth (1- arg) command-history))
+       newcmd)
+    (if elt
+       (progn
+         (setq newcmd
+               (let ((print-level nil)
+                     (minibuffer-history-position arg)
+                     (minibuffer-history-sexp-flag (1+ (minibuffer-depth))))
+                 (unwind-protect
+                     (read-from-minibuffer
+                      "Redo: " (prin1-to-string elt) read-expression-map t
+                      (cons 'command-history arg))
+
+                   ;; If command was added to command-history as a
+                   ;; string, get rid of that.  We want only
+                   ;; evaluable expressions there.
+                   (if (stringp (car command-history))
+                       (setq command-history (cdr command-history))))))
+
+         ;; If command to be redone does not match front of history,
+         ;; add it to the history.
+         (or (equal newcmd (car command-history))
+             (setq command-history (cons newcmd command-history)))
+          (unwind-protect
+              (progn
+                ;; Trick called-interactively-p into thinking that `newcmd' is
+                ;; an interactive call (bug#14136).
+                (add-hook 'called-interactively-p-functions
+                          #'repeat-complex-command--called-interactively-skip)
+                (eval newcmd))
+            (remove-hook 'called-interactively-p-functions
+                         #'repeat-complex-command--called-interactively-skip)))
+      (if command-history
+         (error "Argument %d is beyond length of command history" arg)
+       (error "There are no previous complex commands to repeat")))))
+
+(defun repeat-complex-command--called-interactively-skip (i _frame1 frame2)
+  (and (eq 'eval (cadr frame2))
+       (eq 'repeat-complex-command
+           (cadr (backtrace-frame i #'called-interactively-p)))
+       1))
+
+(defvar extended-command-history nil)
+
+(defun read-extended-command ()
+  "Read command name to invoke in `execute-extended-command'."
+  (minibuffer-with-setup-hook
+      (lambda ()
+       (set (make-local-variable 'minibuffer-default-add-function)
+            (lambda ()
+              ;; Get a command name at point in the original buffer
+              ;; to propose it after M-n.
+              (with-current-buffer (window-buffer (minibuffer-selected-window))
+                (and (commandp (function-called-at-point))
+                     (format "%S" (function-called-at-point)))))))
+    ;; Read a string, completing from and restricting to the set of
+    ;; all defined commands.  Don't provide any initial input.
+    ;; Save the command read on the extended-command history list.
+    (completing-read
+     (concat (cond
+             ((eq current-prefix-arg '-) "- ")
+             ((and (consp current-prefix-arg)
+                   (eq (car current-prefix-arg) 4)) "C-u ")
+             ((and (consp current-prefix-arg)
+                   (integerp (car current-prefix-arg)))
+              (format "%d " (car current-prefix-arg)))
+             ((integerp current-prefix-arg)
+              (format "%d " current-prefix-arg)))
+            ;; This isn't strictly correct if `execute-extended-command'
+            ;; is bound to anything else (e.g. [menu]).
+            ;; It could use (key-description (this-single-command-keys)),
+            ;; but actually a prompt other than "M-x" would be confusing,
+            ;; because "M-x" is a well-known prompt to read a command
+            ;; and it serves as a shorthand for "Extended command: ".
+            "M-x ")
+     obarray 'commandp t nil 'extended-command-history)))
+
+(defcustom suggest-key-bindings t
+  "Non-nil means show the equivalent key-binding when M-x command has one.
+The value can be a length of time to show the message for.
+If the value is non-nil and not a number, we wait 2 seconds."
+  :group 'keyboard
+  :type '(choice (const :tag "off" nil)
+                 (integer :tag "time" 2)
+                 (other :tag "on")))
+
+(defun execute-extended-command (prefixarg &optional command-name)
+  ;; Based on Fexecute_extended_command in keyboard.c of Emacs.
+  ;; Aaron S. Hawley <aaron.s.hawley(at)gmail.com> 2009-08-24
+  "Read a command name, then read the arguments and call the command.
+Interactively, to pass a prefix argument to the command you are
+invoking, give a prefix argument to `execute-extended-command'.
+Noninteractively, the argument PREFIXARG is the prefix argument to
+give to the command you invoke."
+  (interactive (list current-prefix-arg (read-extended-command)))
+  ;; Emacs<24 calling-convention was with a single `prefixarg' argument.
+  (if (null command-name)
+      (setq command-name (let ((current-prefix-arg prefixarg)) ; for prompt
+                           (read-extended-command))))
+  (let* ((function (and (stringp command-name) (intern-soft command-name)))
+         (binding (and suggest-key-bindings
+                      (not executing-kbd-macro)
+                      (where-is-internal function overriding-local-map t))))
+    (unless (commandp function)
+      (error "`%s' is not a valid command name" command-name))
+    (setq this-command function)
+    ;; Normally `real-this-command' should never be changed, but here we really
+    ;; want to pretend that M-x <cmd> RET is nothing more than a "key
+    ;; binding" for <cmd>, so the command the user really wanted to run is
+    ;; `function' and not `execute-extended-command'.  The difference is
+    ;; visible in cases such as M-x <cmd> RET and then C-x z (bug#11506).
+    (setq real-this-command function)
+    (let ((prefix-arg prefixarg))
+      (command-execute function 'record))
+    ;; If enabled, show which key runs this command.
+    (when binding
+      ;; But first wait, and skip the message if there is input.
+      (let* ((waited
+              ;; If this command displayed something in the echo area;
+              ;; wait a few seconds, then display our suggestion message.
+              (sit-for (cond
+                        ((zerop (length (current-message))) 0)
+                        ((numberp suggest-key-bindings) suggest-key-bindings)
+                        (t 2)))))
+        (when (and waited (not (consp unread-command-events)))
+          (with-temp-message
+              (format "You can run the command `%s' with %s"
+                      function (key-description binding))
+            (sit-for (if (numberp suggest-key-bindings)
+                         suggest-key-bindings
+                       2))))))))
+
+(defun command-execute (cmd &optional record-flag keys special)
+  ;; BEWARE: Called directly from the C code.
+  "Execute CMD as an editor command.
+CMD must be a symbol that satisfies the `commandp' predicate.
+Optional second arg RECORD-FLAG non-nil
+means unconditionally put this command in the variable `command-history'.
+Otherwise, that is done only if an arg is read using the minibuffer.
+The argument KEYS specifies the value to use instead of (this-command-keys)
+when reading the arguments; if it is nil, (this-command-keys) is used.
+The argument SPECIAL, if non-nil, means that this command is executing
+a special event, so ignore the prefix argument and don't clear it."
+  (setq debug-on-next-call nil)
+  (let ((prefixarg (unless special
+                     (prog1 prefix-arg
+                       (setq current-prefix-arg prefix-arg)
+                       (setq prefix-arg nil)))))
+    (if (and (symbolp cmd)
+             (get cmd 'disabled)
+             disabled-command-function)
+        ;; FIXME: Weird calling convention!
+        (run-hooks 'disabled-command-function)
+      (let ((final cmd))
+        (while
+            (progn
+              (setq final (indirect-function final))
+              (if (autoloadp final)
+                  (setq final (autoload-do-load final cmd)))))
+        (cond
+         ((arrayp final)
+          ;; If requested, place the macro in the command history.  For
+          ;; other sorts of commands, call-interactively takes care of this.
+          (when record-flag
+            (push `(execute-kbd-macro ,final ,prefixarg) command-history)
+            ;; Don't keep command history around forever.
+            (when (and (numberp history-length) (> history-length 0))
+              (let ((cell (nthcdr history-length command-history)))
+                (if (consp cell) (setcdr cell nil)))))
+          (execute-kbd-macro final prefixarg))
+         (t
+          ;; Pass `cmd' rather than `final', for the backtrace's sake.
+          (prog1 (call-interactively cmd record-flag keys)
+            (when (and (symbolp cmd)
+                       (get cmd 'byte-obsolete-info)
+                       (not (get cmd 'command-execute-obsolete-warned)))
+              (put cmd 'command-execute-obsolete-warned t)
+              (message "%s" (macroexp--obsolete-warning
+                             cmd (get cmd 'byte-obsolete-info) 
"command"))))))))))
+
+(defvar minibuffer-history nil
+  "Default minibuffer history list.
+This is used for all minibuffer input
+except when an alternate history list is specified.
+
+Maximum length of the history list is determined by the value
+of `history-length', which see.")
+(defvar minibuffer-history-sexp-flag nil
+  "Control whether history list elements are expressions or strings.
+If the value of this variable equals current minibuffer depth,
+they are expressions; otherwise they are strings.
+\(That convention is designed to do the right thing for
+recursive uses of the minibuffer.)")
+(setq minibuffer-history-variable 'minibuffer-history)
+(setq minibuffer-history-position nil)  ;; Defvar is in C code.
+(defvar minibuffer-history-search-history nil)
+
+(defvar minibuffer-text-before-history nil
+  "Text that was in this minibuffer before any history commands.
+This is nil if there have not yet been any history commands
+in this use of the minibuffer.")
+
+(add-hook 'minibuffer-setup-hook 'minibuffer-history-initialize)
+
+(defun minibuffer-history-initialize ()
+  (setq minibuffer-text-before-history nil))
+
+(defun minibuffer-avoid-prompt (_new _old)
+  "A point-motion hook for the minibuffer, that moves point out of the prompt."
+  (constrain-to-field nil (point-max)))
+
+(defcustom minibuffer-history-case-insensitive-variables nil
+  "Minibuffer history variables for which matching should ignore case.
+If a history variable is a member of this list, then the
+\\[previous-matching-history-element] and \\[next-matching-history-element]\
+ commands ignore case when searching it, regardless of `case-fold-search'."
+  :type '(repeat variable)
+  :group 'minibuffer)
+
+(defun previous-matching-history-element (regexp n)
+  "Find the previous history element that matches REGEXP.
+\(Previous history elements refer to earlier actions.)
+With prefix argument N, search for Nth previous match.
+If N is negative, find the next or Nth next match.
+Normally, history elements are matched case-insensitively if
+`case-fold-search' is non-nil, but an uppercase letter in REGEXP
+makes the search case-sensitive.
+See also `minibuffer-history-case-insensitive-variables'."
+  (interactive
+   (let* ((enable-recursive-minibuffers t)
+         (regexp (read-from-minibuffer "Previous element matching (regexp): "
+                                       nil
+                                       minibuffer-local-map
+                                       nil
+                                       'minibuffer-history-search-history
+                                       (car 
minibuffer-history-search-history))))
+     ;; Use the last regexp specified, by default, if input is empty.
+     (list (if (string= regexp "")
+              (if minibuffer-history-search-history
+                  (car minibuffer-history-search-history)
+                (user-error "No previous history search regexp"))
+            regexp)
+          (prefix-numeric-value current-prefix-arg))))
+  (unless (zerop n)
+    (if (and (zerop minibuffer-history-position)
+            (null minibuffer-text-before-history))
+       (setq minibuffer-text-before-history
+             (minibuffer-contents-no-properties)))
+    (let ((history (symbol-value minibuffer-history-variable))
+         (case-fold-search
+          (if (isearch-no-upper-case-p regexp t) ; assume isearch.el is dumped
+              ;; On some systems, ignore case for file names.
+              (if (memq minibuffer-history-variable
+                        minibuffer-history-case-insensitive-variables)
+                  t
+                ;; Respect the user's setting for case-fold-search:
+                case-fold-search)
+            nil))
+         prevpos
+         match-string
+         match-offset
+         (pos minibuffer-history-position))
+      (while (/= n 0)
+       (setq prevpos pos)
+       (setq pos (min (max 1 (+ pos (if (< n 0) -1 1))) (length history)))
+       (when (= pos prevpos)
+         (user-error (if (= pos 1)
+                          "No later matching history item"
+                        "No earlier matching history item")))
+       (setq match-string
+             (if (eq minibuffer-history-sexp-flag (minibuffer-depth))
+                 (let ((print-level nil))
+                   (prin1-to-string (nth (1- pos) history)))
+               (nth (1- pos) history)))
+       (setq match-offset
+             (if (< n 0)
+                 (and (string-match regexp match-string)
+                      (match-end 0))
+               (and (string-match (concat ".*\\(" regexp "\\)") match-string)
+                    (match-beginning 1))))
+       (when match-offset
+         (setq n (+ n (if (< n 0) 1 -1)))))
+      (setq minibuffer-history-position pos)
+      (goto-char (point-max))
+      (delete-minibuffer-contents)
+      (insert match-string)
+      (goto-char (+ (minibuffer-prompt-end) match-offset))))
+  (if (memq (car (car command-history)) '(previous-matching-history-element
+                                         next-matching-history-element))
+      (setq command-history (cdr command-history))))
+
+(defun next-matching-history-element (regexp n)
+  "Find the next history element that matches REGEXP.
+\(The next history element refers to a more recent action.)
+With prefix argument N, search for Nth next match.
+If N is negative, find the previous or Nth previous match.
+Normally, history elements are matched case-insensitively if
+`case-fold-search' is non-nil, but an uppercase letter in REGEXP
+makes the search case-sensitive."
+  (interactive
+   (let* ((enable-recursive-minibuffers t)
+         (regexp (read-from-minibuffer "Next element matching (regexp): "
+                                       nil
+                                       minibuffer-local-map
+                                       nil
+                                       'minibuffer-history-search-history
+                                       (car 
minibuffer-history-search-history))))
+     ;; Use the last regexp specified, by default, if input is empty.
+     (list (if (string= regexp "")
+              (if minibuffer-history-search-history
+                  (car minibuffer-history-search-history)
+                (user-error "No previous history search regexp"))
+            regexp)
+          (prefix-numeric-value current-prefix-arg))))
+  (previous-matching-history-element regexp (- n)))
+
+(defvar minibuffer-temporary-goal-position nil)
+
+(defvar minibuffer-default-add-function 'minibuffer-default-add-completions
+  "Function run by `goto-history-element' before consuming default values.
+This is useful to dynamically add more elements to the list of default values
+when `goto-history-element' reaches the end of this list.
+Before calling this function `goto-history-element' sets the variable
+`minibuffer-default-add-done' to t, so it will call this function only
+once.  In special cases, when this function needs to be called more
+than once, it can set `minibuffer-default-add-done' to nil explicitly,
+overriding the setting of this variable to t in `goto-history-element'.")
+
+(defvar minibuffer-default-add-done nil
+  "When nil, add more elements to the end of the list of default values.
+The value nil causes `goto-history-element' to add more elements to
+the list of defaults when it reaches the end of this list.  It does
+this by calling a function defined by `minibuffer-default-add-function'.")
+
+(make-variable-buffer-local 'minibuffer-default-add-done)
+
+(defun minibuffer-default-add-completions ()
+  "Return a list of all completions without the default value.
+This function is used to add all elements of the completion table to
+the end of the list of defaults just after the default value."
+  (let ((def minibuffer-default)
+       (all (all-completions ""
+                             minibuffer-completion-table
+                             minibuffer-completion-predicate)))
+    (if (listp def)
+       (append def all)
+      (cons def (delete def all)))))
+
+(defun goto-history-element (nabs)
+  "Puts element of the minibuffer history in the minibuffer.
+The argument NABS specifies the absolute history position."
+  (interactive "p")
+  (when (and (not minibuffer-default-add-done)
+            (functionp minibuffer-default-add-function)
+            (< nabs (- (if (listp minibuffer-default)
+                           (length minibuffer-default)
+                         1))))
+    (setq minibuffer-default-add-done t
+         minibuffer-default (funcall minibuffer-default-add-function)))
+  (let ((minimum (if minibuffer-default
+                    (- (if (listp minibuffer-default)
+                           (length minibuffer-default)
+                         1))
+                  0))
+       elt minibuffer-returned-to-present)
+    (if (and (zerop minibuffer-history-position)
+            (null minibuffer-text-before-history))
+       (setq minibuffer-text-before-history
+             (minibuffer-contents-no-properties)))
+    (if (< nabs minimum)
+       (user-error (if minibuffer-default
+                        "End of defaults; no next item"
+                      "End of history; no default available")))
+    (if (> nabs (length (symbol-value minibuffer-history-variable)))
+       (user-error "Beginning of history; no preceding item"))
+    (unless (memq last-command '(next-history-element
+                                previous-history-element))
+      (let ((prompt-end (minibuffer-prompt-end)))
+       (set (make-local-variable 'minibuffer-temporary-goal-position)
+            (cond ((<= (point) prompt-end) prompt-end)
+                  ((eobp) nil)
+                  (t (point))))))
+    (goto-char (point-max))
+    (delete-minibuffer-contents)
+    (setq minibuffer-history-position nabs)
+    (cond ((< nabs 0)
+          (setq elt (if (listp minibuffer-default)
+                        (nth (1- (abs nabs)) minibuffer-default)
+                      minibuffer-default)))
+         ((= nabs 0)
+          (setq elt (or minibuffer-text-before-history ""))
+          (setq minibuffer-returned-to-present t)
+          (setq minibuffer-text-before-history nil))
+         (t (setq elt (nth (1- minibuffer-history-position)
+                           (symbol-value minibuffer-history-variable)))))
+    (insert
+     (if (and (eq minibuffer-history-sexp-flag (minibuffer-depth))
+             (not minibuffer-returned-to-present))
+        (let ((print-level nil))
+          (prin1-to-string elt))
+       elt))
+    (goto-char (or minibuffer-temporary-goal-position (point-max)))))
+
+(defun next-history-element (n)
+  "Puts next element of the minibuffer history in the minibuffer.
+With argument N, it uses the Nth following element."
+  (interactive "p")
+  (or (zerop n)
+      (goto-history-element (- minibuffer-history-position n))))
+
+(defun previous-history-element (n)
+  "Puts previous element of the minibuffer history in the minibuffer.
+With argument N, it uses the Nth previous element."
+  (interactive "p")
+  (or (zerop n)
+      (goto-history-element (+ minibuffer-history-position n))))
+
+(defun next-complete-history-element (n)
+  "Get next history element which completes the minibuffer before the point.
+The contents of the minibuffer after the point are deleted, and replaced
+by the new completion."
+  (interactive "p")
+  (let ((point-at-start (point)))
+    (next-matching-history-element
+     (concat
+      "^" (regexp-quote (buffer-substring (minibuffer-prompt-end) (point))))
+     n)
+    ;; next-matching-history-element always puts us at (point-min).
+    ;; Move to the position we were at before changing the buffer contents.
+    ;; This is still sensible, because the text before point has not changed.
+    (goto-char point-at-start)))
+
+(defun previous-complete-history-element (n)
+  "\
+Get previous history element which completes the minibuffer before the point.
+The contents of the minibuffer after the point are deleted, and replaced
+by the new completion."
+  (interactive "p")
+  (next-complete-history-element (- n)))
+
+;; For compatibility with the old subr of the same name.
+(defun minibuffer-prompt-width ()
+  "Return the display width of the minibuffer prompt.
+Return 0 if current buffer is not a minibuffer."
+  ;; Return the width of everything before the field at the end of
+  ;; the buffer; this should be 0 for normal buffers.
+  (1- (minibuffer-prompt-end)))
+
+;; isearch minibuffer history
+(add-hook 'minibuffer-setup-hook 'minibuffer-history-isearch-setup)
+
+(defvar minibuffer-history-isearch-message-overlay)
+(make-variable-buffer-local 'minibuffer-history-isearch-message-overlay)
+
+(defun minibuffer-history-isearch-setup ()
+  "Set up a minibuffer for using isearch to search the minibuffer history.
+Intended to be added to `minibuffer-setup-hook'."
+  (set (make-local-variable 'isearch-search-fun-function)
+       'minibuffer-history-isearch-search)
+  (set (make-local-variable 'isearch-message-function)
+       'minibuffer-history-isearch-message)
+  (set (make-local-variable 'isearch-wrap-function)
+       'minibuffer-history-isearch-wrap)
+  (set (make-local-variable 'isearch-push-state-function)
+       'minibuffer-history-isearch-push-state)
+  (add-hook 'isearch-mode-end-hook 'minibuffer-history-isearch-end nil t))
+
+(defun minibuffer-history-isearch-end ()
+  "Clean up the minibuffer after terminating isearch in the minibuffer."
+  (if minibuffer-history-isearch-message-overlay
+      (delete-overlay minibuffer-history-isearch-message-overlay)))
+
+(defun minibuffer-history-isearch-search ()
+  "Return the proper search function, for isearch in minibuffer history."
+  (lambda (string bound noerror)
+    (let ((search-fun
+          ;; Use standard functions to search within minibuffer text
+          (isearch-search-fun-default))
+         found)
+      ;; Avoid lazy-highlighting matches in the minibuffer prompt when
+      ;; searching forward.  Lazy-highlight calls this lambda with the
+      ;; bound arg, so skip the minibuffer prompt.
+      (if (and bound isearch-forward (< (point) (minibuffer-prompt-end)))
+         (goto-char (minibuffer-prompt-end)))
+      (or
+       ;; 1. First try searching in the initial minibuffer text
+       (funcall search-fun string
+               (if isearch-forward bound (minibuffer-prompt-end))
+               noerror)
+       ;; 2. If the above search fails, start putting next/prev history
+       ;; elements in the minibuffer successively, and search the string
+       ;; in them.  Do this only when bound is nil (i.e. not while
+       ;; lazy-highlighting search strings in the current minibuffer text).
+       (unless bound
+        (condition-case nil
+            (progn
+              (while (not found)
+                (cond (isearch-forward
+                       (next-history-element 1)
+                       (goto-char (minibuffer-prompt-end)))
+                      (t
+                       (previous-history-element 1)
+                       (goto-char (point-max))))
+                (setq isearch-barrier (point) isearch-opoint (point))
+                ;; After putting the next/prev history element, search
+                ;; the string in them again, until next-history-element
+                ;; or previous-history-element raises an error at the
+                ;; beginning/end of history.
+                (setq found (funcall search-fun string
+                                     (unless isearch-forward
+                                       ;; For backward search, don't search
+                                       ;; in the minibuffer prompt
+                                       (minibuffer-prompt-end))
+                                     noerror)))
+              ;; Return point of the new search result
+              (point))
+          ;; Return nil when next(prev)-history-element fails
+          (error nil)))))))
+
+(defun minibuffer-history-isearch-message (&optional c-q-hack ellipsis)
+  "Display the minibuffer history search prompt.
+If there are no search errors, this function displays an overlay with
+the isearch prompt which replaces the original minibuffer prompt.
+Otherwise, it displays the standard isearch message returned from
+the function `isearch-message'."
+  (if (not (and (minibufferp) isearch-success (not isearch-error)))
+      ;; Use standard function `isearch-message' when not in the minibuffer,
+      ;; or search fails, or has an error (like incomplete regexp).
+      ;; This function overwrites minibuffer text with isearch message,
+      ;; so it's possible to see what is wrong in the search string.
+      (isearch-message c-q-hack ellipsis)
+    ;; Otherwise, put the overlay with the standard isearch prompt over
+    ;; the initial minibuffer prompt.
+    (if (overlayp minibuffer-history-isearch-message-overlay)
+       (move-overlay minibuffer-history-isearch-message-overlay
+                     (point-min) (minibuffer-prompt-end))
+      (setq minibuffer-history-isearch-message-overlay
+           (make-overlay (point-min) (minibuffer-prompt-end)))
+      (overlay-put minibuffer-history-isearch-message-overlay 'evaporate t))
+    (overlay-put minibuffer-history-isearch-message-overlay
+                'display (isearch-message-prefix c-q-hack ellipsis))
+    ;; And clear any previous isearch message.
+    (message "")))
+
+(defun minibuffer-history-isearch-wrap ()
+  "Wrap the minibuffer history search when search fails.
+Move point to the first history element for a forward search,
+or to the last history element for a backward search."
+  ;; When `minibuffer-history-isearch-search' fails on reaching the
+  ;; beginning/end of the history, wrap the search to the first/last
+  ;; minibuffer history element.
+  (if isearch-forward
+      (goto-history-element (length (symbol-value 
minibuffer-history-variable)))
+    (goto-history-element 0))
+  (setq isearch-success t)
+  (goto-char (if isearch-forward (minibuffer-prompt-end) (point-max))))
+
+(defun minibuffer-history-isearch-push-state ()
+  "Save a function restoring the state of minibuffer history search.
+Save `minibuffer-history-position' to the additional state parameter
+in the search status stack."
+  (let ((pos minibuffer-history-position))
+    (lambda (cmd)
+      (minibuffer-history-isearch-pop-state cmd pos))))
+
+(defun minibuffer-history-isearch-pop-state (_cmd hist-pos)
+  "Restore the minibuffer history search state.
+Go to the history element by the absolute history position HIST-POS."
+  (goto-history-element hist-pos))
+
+
+;Put this on C-x u, so we can force that rather than C-_ into startup msg
+(define-obsolete-function-alias 'advertised-undo 'undo "23.2")
+
+(defconst undo-equiv-table (make-hash-table :test 'eq :weakness t)
+  "Table mapping redo records to the corresponding undo one.
+A redo record for undo-in-region maps to t.
+A redo record for ordinary undo maps to the following (earlier) undo.")
+
+(defvar undo-in-region nil
+  "Non-nil if `pending-undo-list' is not just a tail of `buffer-undo-list'.")
+
+(defvar undo-no-redo nil
+  "If t, `undo' doesn't go through redo entries.")
+
+(defvar pending-undo-list nil
+  "Within a run of consecutive undo commands, list remaining to be undone.
+If t, we undid all the way to the end of it.")
+
+(defun undo (&optional arg)
+  "Undo some previous changes.
+Repeat this command to undo more changes.
+A numeric ARG serves as a repeat count.
+
+In Transient Mark mode when the mark is active, only undo changes within
+the current region.  Similarly, when not in Transient Mark mode, just 
\\[universal-argument]
+as an argument limits undo to changes within the current region."
+  (interactive "*P")
+  ;; Make last-command indicate for the next command that this was an undo.
+  ;; That way, another undo will undo more.
+  ;; If we get to the end of the undo history and get an error,
+  ;; another undo command will find the undo history empty
+  ;; and will get another error.  To begin undoing the undos,
+  ;; you must type some other command.
+  (let* ((modified (buffer-modified-p))
+        ;; For an indirect buffer, look in the base buffer for the
+        ;; auto-save data.
+        (base-buffer (or (buffer-base-buffer) (current-buffer)))
+        (recent-save (with-current-buffer base-buffer
+                       (recent-auto-save-p)))
+        message)
+    ;; If we get an error in undo-start,
+    ;; the next command should not be a "consecutive undo".
+    ;; So set `this-command' to something other than `undo'.
+    (setq this-command 'undo-start)
+
+    (unless (and (eq last-command 'undo)
+                (or (eq pending-undo-list t)
+                    ;; If something (a timer or filter?) changed the buffer
+                    ;; since the previous command, don't continue the undo seq.
+                    (let ((list buffer-undo-list))
+                      (while (eq (car list) nil)
+                        (setq list (cdr list)))
+                      ;; If the last undo record made was made by undo
+                      ;; it shows nothing else happened in between.
+                      (gethash list undo-equiv-table))))
+      (setq undo-in-region
+           (or (region-active-p) (and arg (not (numberp arg)))))
+      (if undo-in-region
+         (undo-start (region-beginning) (region-end))
+       (undo-start))
+      ;; get rid of initial undo boundary
+      (undo-more 1))
+    ;; If we got this far, the next command should be a consecutive undo.
+    (setq this-command 'undo)
+    ;; Check to see whether we're hitting a redo record, and if
+    ;; so, ask the user whether she wants to skip the redo/undo pair.
+    (let ((equiv (gethash pending-undo-list undo-equiv-table)))
+      (or (eq (selected-window) (minibuffer-window))
+         (setq message (format "%s%s!"
+                                (if (or undo-no-redo (not equiv))
+                                    "Undo" "Redo")
+                                (if undo-in-region " in region" ""))))
+      (when (and (consp equiv) undo-no-redo)
+       ;; The equiv entry might point to another redo record if we have done
+       ;; undo-redo-undo-redo-... so skip to the very last equiv.
+       (while (let ((next (gethash equiv undo-equiv-table)))
+                (if next (setq equiv next))))
+       (setq pending-undo-list equiv)))
+    (undo-more
+     (if (numberp arg)
+        (prefix-numeric-value arg)
+       1))
+    ;; Record the fact that the just-generated undo records come from an
+    ;; undo operation--that is, they are redo records.
+    ;; In the ordinary case (not within a region), map the redo
+    ;; record to the following undos.
+    ;; I don't know how to do that in the undo-in-region case.
+    (let ((list buffer-undo-list))
+      ;; Strip any leading undo boundaries there might be, like we do
+      ;; above when checking.
+      (while (eq (car list) nil)
+       (setq list (cdr list)))
+      (puthash list
+               ;; Prevent identity mapping.  This can happen if
+               ;; consecutive nils are erroneously in undo list.
+               (if (or undo-in-region (eq list pending-undo-list))
+                   t
+                 pending-undo-list)
+              undo-equiv-table))
+    ;; Don't specify a position in the undo record for the undo command.
+    ;; Instead, undoing this should move point to where the change is.
+    (let ((tail buffer-undo-list)
+         (prev nil))
+      (while (car tail)
+       (when (integerp (car tail))
+         (let ((pos (car tail)))
+           (if prev
+               (setcdr prev (cdr tail))
+             (setq buffer-undo-list (cdr tail)))
+           (setq tail (cdr tail))
+           (while (car tail)
+             (if (eq pos (car tail))
+                 (if prev
+                     (setcdr prev (cdr tail))
+                   (setq buffer-undo-list (cdr tail)))
+               (setq prev tail))
+             (setq tail (cdr tail)))
+           (setq tail nil)))
+       (setq prev tail tail (cdr tail))))
+    ;; Record what the current undo list says,
+    ;; so the next command can tell if the buffer was modified in between.
+    (and modified (not (buffer-modified-p))
+        (with-current-buffer base-buffer
+          (delete-auto-save-file-if-necessary recent-save)))
+    ;; Display a message announcing success.
+    (if message
+       (message "%s" message))))
+
+(defun buffer-disable-undo (&optional buffer)
+  "Make BUFFER stop keeping undo information.
+No argument or nil as argument means do this for the current buffer."
+  (interactive)
+  (with-current-buffer (if buffer (get-buffer buffer) (current-buffer))
+    (setq buffer-undo-list t)))
+
+(defun undo-only (&optional arg)
+  "Undo some previous changes.
+Repeat this command to undo more changes.
+A numeric ARG serves as a repeat count.
+Contrary to `undo', this will not redo a previous undo."
+  (interactive "*p")
+  (let ((undo-no-redo t)) (undo arg)))
+
+(defvar undo-in-progress nil
+  "Non-nil while performing an undo.
+Some change-hooks test this variable to do something different.")
+
+(defun undo-more (n)
+  "Undo back N undo-boundaries beyond what was already undone recently.
+Call `undo-start' to get ready to undo recent changes,
+then call `undo-more' one or more times to undo them."
+  (or (listp pending-undo-list)
+      (user-error (concat "No further undo information"
+                          (and undo-in-region " for region"))))
+  (let ((undo-in-progress t))
+    ;; Note: The following, while pulling elements off
+    ;; `pending-undo-list' will call primitive change functions which
+    ;; will push more elements onto `buffer-undo-list'.
+    (setq pending-undo-list (primitive-undo n pending-undo-list))
+    (if (null pending-undo-list)
+       (setq pending-undo-list t))))
+
+(defun primitive-undo (n list)
+  "Undo N records from the front of the list LIST.
+Return what remains of the list."
+
+  ;; This is a good feature, but would make undo-start
+  ;; unable to do what is expected.
+  ;;(when (null (car (list)))
+  ;;  ;; If the head of the list is a boundary, it is the boundary
+  ;;  ;; preceding this command.  Get rid of it and don't count it.
+  ;;  (setq list (cdr list))))
+
+  (let ((arg n)
+        ;; In a writable buffer, enable undoing read-only text that is
+        ;; so because of text properties.
+        (inhibit-read-only t)
+        ;; Don't let `intangible' properties interfere with undo.
+        (inhibit-point-motion-hooks t)
+        ;; We use oldlist only to check for EQ.  ++kfs
+        (oldlist buffer-undo-list)
+        (did-apply nil)
+        (next nil))
+    (while (> arg 0)
+      (while (setq next (pop list))     ;Exit inner loop at undo boundary.
+        ;; Handle an integer by setting point to that value.
+        (pcase next
+          ((pred integerp) (goto-char next))
+          ;; Element (t . TIME) records previous modtime.
+          ;; Preserve any flag of NONEXISTENT_MODTIME_NSECS or
+          ;; UNKNOWN_MODTIME_NSECS.
+          (`(t . ,time)
+           ;; If this records an obsolete save
+           ;; (not matching the actual disk file)
+           ;; then don't mark unmodified.
+           (when (or (equal time (visited-file-modtime))
+                     (and (consp time)
+                          (equal (list (car time) (cdr time))
+                                 (visited-file-modtime))))
+             (when (fboundp 'unlock-buffer)
+               (unlock-buffer))
+             (set-buffer-modified-p nil)))
+          ;; Element (nil PROP VAL BEG . END) is property change.
+          (`(nil . ,(or `(,prop ,val ,beg . ,end) pcase--dontcare))
+           (when (or (> (point-min) beg) (< (point-max) end))
+             (error "Changes to be undone are outside visible portion of 
buffer"))
+           (put-text-property beg end prop val))
+          ;; Element (BEG . END) means range was inserted.
+          (`(,(and beg (pred integerp)) . ,(and end (pred integerp)))
+           ;; (and `(,beg . ,end) `(,(pred integerp) . ,(pred integerp)))
+           ;; Ideally: `(,(pred integerp beg) . ,(pred integerp end))
+           (when (or (> (point-min) beg) (< (point-max) end))
+             (error "Changes to be undone are outside visible portion of 
buffer"))
+           ;; Set point first thing, so that undoing this undo
+           ;; does not send point back to where it is now.
+           (goto-char beg)
+           (delete-region beg end))
+          ;; Element (apply FUN . ARGS) means call FUN to undo.
+          (`(apply . ,fun-args)
+           (let ((currbuff (current-buffer)))
+             (if (integerp (car fun-args))
+                 ;; Long format: (apply DELTA START END FUN . ARGS).
+                 (pcase-let* ((`(,delta ,start ,end ,fun . ,args) fun-args)
+                              (start-mark (copy-marker start nil))
+                              (end-mark (copy-marker end t)))
+                   (when (or (> (point-min) start) (< (point-max) end))
+                     (error "Changes to be undone are outside visible portion 
of buffer"))
+                   (apply fun args) ;; Use `save-current-buffer'?
+                   ;; Check that the function did what the entry
+                   ;; said it would do.
+                   (unless (and (= start start-mark)
+                                (= (+ delta end) end-mark))
+                     (error "Changes to be undone by function different than 
announced"))
+                   (set-marker start-mark nil)
+                   (set-marker end-mark nil))
+               (apply fun-args))
+             (unless (eq currbuff (current-buffer))
+               (error "Undo function switched buffer"))
+             (setq did-apply t)))
+          ;; Element (STRING . POS) means STRING was deleted.
+          (`(,(and string (pred stringp)) . ,(and pos (pred integerp)))
+           (when (let ((apos (abs pos)))
+                   (or (< apos (point-min)) (> apos (point-max))))
+             (error "Changes to be undone are outside visible portion of 
buffer"))
+           (let (valid-marker-adjustments)
+             ;; Check that marker adjustments which were recorded
+             ;; with the (STRING . POS) record are still valid, ie
+             ;; the markers haven't moved.  We check their validity
+             ;; before reinserting the string so as we don't need to
+             ;; mind marker insertion-type.
+             (while (and (markerp (car-safe (car list)))
+                         (integerp (cdr-safe (car list))))
+               (let* ((marker-adj (pop list))
+                      (m (car marker-adj)))
+                 (and (eq (marker-buffer m) (current-buffer))
+                      (= pos m)
+                      (push marker-adj valid-marker-adjustments))))
+             ;; Insert string and adjust point
+             (if (< pos 0)
+                 (progn
+                   (goto-char (- pos))
+                   (insert string))
+               (goto-char pos)
+               (insert string)
+               (goto-char pos))
+             ;; Adjust the valid marker adjustments
+             (dolist (adj valid-marker-adjustments)
+               (set-marker (car adj)
+                           (- (car adj) (cdr adj))))))
+          ;; (MARKER . OFFSET) means a marker MARKER was adjusted by OFFSET.
+          (`(,(and marker (pred markerp)) . ,(and offset (pred integerp)))
+           (warn "Encountered %S entry in undo list with no matching (TEXT . 
POS) entry"
+                 next)
+           ;; Even though these elements are not expected in the undo
+           ;; list, adjust them to be conservative for the 24.4
+           ;; release.  (Bug#16818)
+           (when (marker-buffer marker)
+             (set-marker marker
+                         (- marker offset)
+                         (marker-buffer marker))))
+          (_ (error "Unrecognized entry in undo list %S" next))))
+      (setq arg (1- arg)))
+    ;; Make sure an apply entry produces at least one undo entry,
+    ;; so the test in `undo' for continuing an undo series
+    ;; will work right.
+    (if (and did-apply
+             (eq oldlist buffer-undo-list))
+        (setq buffer-undo-list
+              (cons (list 'apply 'cdr nil) buffer-undo-list))))
+  list)
+
+;; Deep copy of a list
+(defun undo-copy-list (list)
+  "Make a copy of undo list LIST."
+  (mapcar 'undo-copy-list-1 list))
+
+(defun undo-copy-list-1 (elt)
+  (if (consp elt)
+      (cons (car elt) (undo-copy-list-1 (cdr elt)))
+    elt))
+
+(defun undo-start (&optional beg end)
+  "Set `pending-undo-list' to the front of the undo list.
+The next call to `undo-more' will undo the most recently made change.
+If BEG and END are specified, then only undo elements
+that apply to text between BEG and END are used; other undo elements
+are ignored.  If BEG and END are nil, all undo elements are used."
+  (if (eq buffer-undo-list t)
+      (user-error "No undo information in this buffer"))
+  (setq pending-undo-list
+       (if (and beg end (not (= beg end)))
+           (undo-make-selective-list (min beg end) (max beg end))
+         buffer-undo-list)))
+
+(defun undo-make-selective-list (start end)
+  "Return a list of undo elements for the region START to END.
+The elements come from `buffer-undo-list', but we keep only
+the elements inside this region, and discard those outside this region.
+If we find an element that crosses an edge of this region,
+we stop and ignore all further elements."
+  (let ((undo-list-copy (undo-copy-list buffer-undo-list))
+       (undo-list (list nil))
+       some-rejected
+       undo-elt temp-undo-list delta)
+    (while undo-list-copy
+      (setq undo-elt (car undo-list-copy))
+      (let ((keep-this
+            (cond ((and (consp undo-elt) (eq (car undo-elt) t))
+                   ;; This is a "was unmodified" element.
+                   ;; Keep it if we have kept everything thus far.
+                   (not some-rejected))
+                   ;; Skip over marker adjustments, instead relying on
+                   ;; finding them after (TEXT . POS) elements
+                   ((markerp (car-safe undo-elt))
+                    nil)
+                  (t
+                   (undo-elt-in-region undo-elt start end)))))
+       (if keep-this
+           (progn
+             (setq end (+ end (cdr (undo-delta undo-elt))))
+             ;; Don't put two nils together in the list
+             (when (not (and (eq (car undo-list) nil)
+                              (eq undo-elt nil)))
+                (setq undo-list (cons undo-elt undo-list))
+                ;; If (TEXT . POS), "keep" its subsequent (MARKER
+                ;; . ADJUSTMENT) whose markers haven't moved.
+                (when (and (stringp (car-safe undo-elt))
+                           (integerp (cdr-safe undo-elt)))
+                  (let ((list-i (cdr undo-list-copy)))
+                    (while (markerp (car-safe (car list-i)))
+                      (let* ((adj-elt (pop list-i))
+                             (m (car adj-elt)))
+                        (and (eq (marker-buffer m) (current-buffer))
+                             (= (cdr undo-elt) m)
+                             (push adj-elt undo-list))))))))
+         (if (undo-elt-crosses-region undo-elt start end)
+             (setq undo-list-copy nil)
+           (setq some-rejected t)
+           (setq temp-undo-list (cdr undo-list-copy))
+           (setq delta (undo-delta undo-elt))
+
+           (when (/= (cdr delta) 0)
+             (let ((position (car delta))
+                   (offset (cdr delta)))
+
+               ;; Loop down the earlier events adjusting their buffer
+               ;; positions to reflect the fact that a change to the buffer
+               ;; isn't being undone. We only need to process those element
+               ;; types which undo-elt-in-region will return as being in
+               ;; the region since only those types can ever get into the
+               ;; output
+
+               (while temp-undo-list
+                 (setq undo-elt (car temp-undo-list))
+                 (cond ((integerp undo-elt)
+                        (if (>= undo-elt position)
+                            (setcar temp-undo-list (- undo-elt offset))))
+                       ((atom undo-elt) nil)
+                       ((stringp (car undo-elt))
+                        ;; (TEXT . POSITION)
+                        (let ((text-pos (abs (cdr undo-elt)))
+                              (point-at-end (< (cdr undo-elt) 0 )))
+                          (if (>= text-pos position)
+                              (setcdr undo-elt (* (if point-at-end -1 1)
+                                                  (- text-pos offset))))))
+                       ((integerp (car undo-elt))
+                        ;; (BEGIN . END)
+                        (when (>= (car undo-elt) position)
+                          (setcar undo-elt (- (car undo-elt) offset))
+                          (setcdr undo-elt (- (cdr undo-elt) offset))))
+                       ((null (car undo-elt))
+                        ;; (nil PROPERTY VALUE BEG . END)
+                        (let ((tail (nthcdr 3 undo-elt)))
+                          (when (>= (car tail) position)
+                            (setcar tail (- (car tail) offset))
+                            (setcdr tail (- (cdr tail) offset))))))
+                 (setq temp-undo-list (cdr temp-undo-list))))))))
+      (setq undo-list-copy (cdr undo-list-copy)))
+    (nreverse undo-list)))
+
+(defun undo-elt-in-region (undo-elt start end)
+  "Determine whether UNDO-ELT falls inside the region START ... END.
+If it crosses the edge, we return nil.
+
+Generally this function is not useful for determining
+whether (MARKER . ADJUSTMENT) undo elements are in the region,
+because markers can be arbitrarily relocated.  Instead, pass the
+marker adjustment's corresponding (TEXT . POS) element."
+  (cond ((integerp undo-elt)
+        (and (>= undo-elt start)
+             (<= undo-elt end)))
+       ((eq undo-elt nil)
+        t)
+       ((atom undo-elt)
+        nil)
+       ((stringp (car undo-elt))
+        ;; (TEXT . POSITION)
+        (and (>= (abs (cdr undo-elt)) start)
+             (<= (abs (cdr undo-elt)) end)))
+       ((and (consp undo-elt) (markerp (car undo-elt)))
+        ;; (MARKER . ADJUSTMENT)
+         (<= start (car undo-elt) end))
+       ((null (car undo-elt))
+        ;; (nil PROPERTY VALUE BEG . END)
+        (let ((tail (nthcdr 3 undo-elt)))
+          (and (>= (car tail) start)
+               (<= (cdr tail) end))))
+       ((integerp (car undo-elt))
+        ;; (BEGIN . END)
+        (and (>= (car undo-elt) start)
+             (<= (cdr undo-elt) end)))))
+
+(defun undo-elt-crosses-region (undo-elt start end)
+  "Test whether UNDO-ELT crosses one edge of that region START ... END.
+This assumes we have already decided that UNDO-ELT
+is not *inside* the region START...END."
+  (cond ((atom undo-elt) nil)
+       ((null (car undo-elt))
+        ;; (nil PROPERTY VALUE BEG . END)
+        (let ((tail (nthcdr 3 undo-elt)))
+          (and (< (car tail) end)
+               (> (cdr tail) start))))
+       ((integerp (car undo-elt))
+        ;; (BEGIN . END)
+        (and (< (car undo-elt) end)
+             (> (cdr undo-elt) start)))))
+
+;; Return the first affected buffer position and the delta for an undo element
+;; delta is defined as the change in subsequent buffer positions if we *did*
+;; the undo.
+(defun undo-delta (undo-elt)
+  (if (consp undo-elt)
+      (cond ((stringp (car undo-elt))
+            ;; (TEXT . POSITION)
+            (cons (abs (cdr undo-elt)) (length (car undo-elt))))
+           ((integerp (car undo-elt))
+            ;; (BEGIN . END)
+            (cons (car undo-elt) (- (car undo-elt) (cdr undo-elt))))
+           (t
+            '(0 . 0)))
+    '(0 . 0)))
+
+(defcustom undo-ask-before-discard nil
+  "If non-nil ask about discarding undo info for the current command.
+Normally, Emacs discards the undo info for the current command if
+it exceeds `undo-outer-limit'.  But if you set this option
+non-nil, it asks in the echo area whether to discard the info.
+If you answer no, there is a slight risk that Emacs might crash, so
+only do it if you really want to undo the command.
+
+This option is mainly intended for debugging.  You have to be
+careful if you use it for other purposes.  Garbage collection is
+inhibited while the question is asked, meaning that Emacs might
+leak memory.  So you should make sure that you do not wait
+excessively long before answering the question."
+  :type 'boolean
+  :group 'undo
+  :version "22.1")
+
+(defvar undo-extra-outer-limit nil
+  "If non-nil, an extra level of size that's ok in an undo item.
+We don't ask the user about truncating the undo list until the
+current item gets bigger than this amount.
+
+This variable only matters if `undo-ask-before-discard' is non-nil.")
+(make-variable-buffer-local 'undo-extra-outer-limit)
+
+;; When the first undo batch in an undo list is longer than
+;; undo-outer-limit, this function gets called to warn the user that
+;; the undo info for the current command was discarded.  Garbage
+;; collection is inhibited around the call, so it had better not do a
+;; lot of consing.
+(setq undo-outer-limit-function 'undo-outer-limit-truncate)
+(defun undo-outer-limit-truncate (size)
+  (if undo-ask-before-discard
+      (when (or (null undo-extra-outer-limit)
+               (> size undo-extra-outer-limit))
+       ;; Don't ask the question again unless it gets even bigger.
+       ;; This applies, in particular, if the user quits from the question.
+       ;; Such a quit quits out of GC, but something else will call GC
+       ;; again momentarily.  It will call this function again,
+       ;; but we don't want to ask the question again.
+       (setq undo-extra-outer-limit (+ size 50000))
+       (if (let (use-dialog-box track-mouse executing-kbd-macro )
+             (yes-or-no-p (format "Buffer `%s' undo info is %d bytes long; 
discard it? "
+                                  (buffer-name) size)))
+           (progn (setq buffer-undo-list nil)
+                  (setq undo-extra-outer-limit nil)
+                  t)
+         nil))
+    (display-warning '(undo discard-info)
+                    (concat
+                     (format "Buffer `%s' undo info was %d bytes long.\n"
+                             (buffer-name) size)
+                     "The undo info was discarded because it exceeded \
+`undo-outer-limit'.
+
+This is normal if you executed a command that made a huge change
+to the buffer.  In that case, to prevent similar problems in the
+future, set `undo-outer-limit' to a value that is large enough to
+cover the maximum size of normal changes you expect a single
+command to make, but not so large that it might exceed the
+maximum memory allotted to Emacs.
+
+If you did not execute any such command, the situation is
+probably due to a bug and you should report it.
+
+You can disable the popping up of this buffer by adding the entry
+\(undo discard-info) to the user option `warning-suppress-types',
+which is defined in the `warnings' library.\n")
+                    :warning)
+    (setq buffer-undo-list nil)
+    t))
+
+(defcustom password-word-equivalents
+  '("password" "passcode" "passphrase" "pass phrase"
+    ; These are sorted according to the GNU en_US locale.
+    "암호"               ; ko
+    "パスワード"    ; ja
+    "ପ୍ରବେଶ ସଙ୍କେତ"    ; or
+    "ពាក្យសម្ងាត់"             ; km
+    "adgangskode"      ; da
+    "contraseña"       ; es
+    "contrasenya"      ; ca
+    "geslo"            ; sl
+    "hasło"            ; pl
+    "heslo"            ; cs, sk
+    "iphasiwedi"       ; zu
+    "jelszó"           ; hu
+    "lösenord"         ; sv
+    "lozinka"          ; hr, sr
+    "mật khẩu"         ; vi
+    "mot de passe"     ; fr
+    "parola"           ; tr
+    "pasahitza"                ; eu
+    "passord"          ; nb
+    "passwort"         ; de
+    "pasvorto"         ; eo
+    "salasana"         ; fi
+    "senha"            ; pt
+    "slaptažodis"      ; lt
+    "wachtwoord"       ; nl
+    "كلمة السر"                ; ar
+    "ססמה"             ; he
+    "лозинка"          ; sr
+    "пароль"           ; kk, ru, uk
+    "गुप्तशब्द"                ; mr
+    "शब्दकूट"          ; hi
+    "પાસવર્ડ"          ; gu
+    "సంకేతపదము"                ; te
+    "ਪਾਸਵਰਡ"           ; pa
+    "ಗುಪ್ತಪದ"          ; kn
+    "கடவுச்சொல்"               ; ta
+    "അടയാളവാക്ക്"              ; ml
+    "গুপ্তশব্দ"                ; as
+    "পাসওয়ার্ড"                ; bn_IN
+    "රහස්පදය"          ; si
+    "密码"               ; zh_CN
+    "密碼"               ; zh_TW
+    )
+  "List of words equivalent to \"password\".
+This is used by Shell mode and other parts of Emacs to recognize
+password prompts, including prompts in languages other than
+English.  Different case choices should not be assumed to be
+included; callers should bind `case-fold-search' to t."
+  :type '(repeat string)
+  :version "24.4"
+  :group 'processes)
+
+(defvar shell-command-history nil
+  "History list for some commands that read shell commands.
+
+Maximum length of the history list is determined by the value
+of `history-length', which see.")
+
+(defvar shell-command-switch (purecopy "-c")
+  "Switch used to have the shell execute its command line argument.")
+
+(defvar shell-command-default-error-buffer nil
+  "Buffer name for `shell-command' and `shell-command-on-region' error output.
+This buffer is used when `shell-command' or `shell-command-on-region'
+is run interactively.  A value of nil means that output to stderr and
+stdout will be intermixed in the output stream.")
+
+(declare-function mailcap-file-default-commands "mailcap" (files))
+(declare-function dired-get-filename "dired" (&optional localp 
no-error-if-not-filep))
+
+(defun minibuffer-default-add-shell-commands ()
+  "Return a list of all commands associated with the current file.
+This function is used to add all related commands retrieved by `mailcap'
+to the end of the list of defaults just after the default value."
+  (interactive)
+  (let* ((filename (if (listp minibuffer-default)
+                      (car minibuffer-default)
+                    minibuffer-default))
+        (commands (and filename (require 'mailcap nil t)
+                       (mailcap-file-default-commands (list filename)))))
+    (setq commands (mapcar (lambda (command)
+                            (concat command " " filename))
+                          commands))
+    (if (listp minibuffer-default)
+       (append minibuffer-default commands)
+      (cons minibuffer-default commands))))
+
+(declare-function shell-completion-vars "shell" ())
+
+(defvar minibuffer-local-shell-command-map
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map minibuffer-local-map)
+    (define-key map "\t" 'completion-at-point)
+    map)
+  "Keymap used for completing shell commands in minibuffer.")
+
+(defun read-shell-command (prompt &optional initial-contents hist &rest args)
+  "Read a shell command from the minibuffer.
+The arguments are the same as the ones of `read-from-minibuffer',
+except READ and KEYMAP are missing and HIST defaults
+to `shell-command-history'."
+  (require 'shell)
+  (minibuffer-with-setup-hook
+      (lambda ()
+        (shell-completion-vars)
+       (set (make-local-variable 'minibuffer-default-add-function)
+            'minibuffer-default-add-shell-commands))
+    (apply 'read-from-minibuffer prompt initial-contents
+          minibuffer-local-shell-command-map
+          nil
+          (or hist 'shell-command-history)
+          args)))
+
+(defcustom async-shell-command-buffer 'confirm-new-buffer
+  "What to do when the output buffer is used by another shell command.
+This option specifies how to resolve the conflict where a new command
+wants to direct its output to the buffer `*Async Shell Command*',
+but this buffer is already taken by another running shell command.
+
+The value `confirm-kill-process' is used to ask for confirmation before
+killing the already running process and running a new process
+in the same buffer, `confirm-new-buffer' for confirmation before running
+the command in a new buffer with a name other than the default buffer name,
+`new-buffer' for doing the same without confirmation,
+`confirm-rename-buffer' for confirmation before renaming the existing
+output buffer and running a new command in the default buffer,
+`rename-buffer' for doing the same without confirmation."
+  :type '(choice (const :tag "Confirm killing of running command"
+                       confirm-kill-process)
+                (const :tag "Confirm creation of a new buffer"
+                       confirm-new-buffer)
+                (const :tag "Create a new buffer"
+                       new-buffer)
+                (const :tag "Confirm renaming of existing buffer"
+                       confirm-rename-buffer)
+                (const :tag "Rename the existing buffer"
+                       rename-buffer))
+  :group 'shell
+  :version "24.3")
+
+(defun async-shell-command (command &optional output-buffer error-buffer)
+  "Execute string COMMAND asynchronously in background.
+
+Like `shell-command', but adds `&' at the end of COMMAND
+to execute it asynchronously.
+
+The output appears in the buffer `*Async Shell Command*'.
+That buffer is in shell mode.
+
+You can configure `async-shell-command-buffer' to specify what to do in
+case when `*Async Shell Command*' buffer is already taken by another
+running shell command.  To run COMMAND without displaying the output
+in a window you can configure `display-buffer-alist' to use the action
+`display-buffer-no-window' for the buffer `*Async Shell Command*'.
+
+In Elisp, you will often be better served by calling `start-process'
+directly, since it offers more control and does not impose the use of a
+shell (with its need to quote arguments)."
+  (interactive
+   (list
+    (read-shell-command "Async shell command: " nil nil
+                       (let ((filename
+                              (cond
+                               (buffer-file-name)
+                               ((eq major-mode 'dired-mode)
+                                (dired-get-filename nil t)))))
+                         (and filename (file-relative-name filename))))
+    current-prefix-arg
+    shell-command-default-error-buffer))
+  (unless (string-match "&[ \t]*\\'" command)
+    (setq command (concat command " &")))
+  (shell-command command output-buffer error-buffer))
+
+(defun shell-command (command &optional output-buffer error-buffer)
+  "Execute string COMMAND in inferior shell; display output, if any.
+With prefix argument, insert the COMMAND's output at point.
+
+If COMMAND ends in `&', execute it asynchronously.
+The output appears in the buffer `*Async Shell Command*'.
+That buffer is in shell mode.  You can also use
+`async-shell-command' that automatically adds `&'.
+
+Otherwise, COMMAND is executed synchronously.  The output appears in
+the buffer `*Shell Command Output*'.  If the output is short enough to
+display in the echo area (which is determined by the variables
+`resize-mini-windows' and `max-mini-window-height'), it is shown
+there, but it is nonetheless available in buffer `*Shell Command
+Output*' even though that buffer is not automatically displayed.
+
+To specify a coding system for converting non-ASCII characters
+in the shell command output, use \\[universal-coding-system-argument] \
+before this command.
+
+Noninteractive callers can specify coding systems by binding
+`coding-system-for-read' and `coding-system-for-write'.
+
+The optional second argument OUTPUT-BUFFER, if non-nil,
+says to put the output in some other buffer.
+If OUTPUT-BUFFER is a buffer or buffer name, put the output there.
+If OUTPUT-BUFFER is not a buffer and not nil,
+insert output in current buffer.  (This cannot be done asynchronously.)
+In either case, the buffer is first erased, and the output is
+inserted after point (leaving mark after it).
+
+If the command terminates without error, but generates output,
+and you did not specify \"insert it in the current buffer\",
+the output can be displayed in the echo area or in its buffer.
+If the output is short enough to display in the echo area
+\(determined by the variable `max-mini-window-height' if
+`resize-mini-windows' is non-nil), it is shown there.
+Otherwise,the buffer containing the output is displayed.
+
+If there is output and an error, and you did not specify \"insert it
+in the current buffer\", a message about the error goes at the end
+of the output.
+
+If there is no output, or if output is inserted in the current buffer,
+then `*Shell Command Output*' is deleted.
+
+If the optional third argument ERROR-BUFFER is non-nil, it is a buffer
+or buffer name to which to direct the command's standard error output.
+If it is nil, error output is mingled with regular output.
+In an interactive call, the variable `shell-command-default-error-buffer'
+specifies the value of ERROR-BUFFER.
+
+In Elisp, you will often be better served by calling `call-process' or
+`start-process' directly, since it offers more control and does not impose
+the use of a shell (with its need to quote arguments)."
+
+  (interactive
+   (list
+    (read-shell-command "Shell command: " nil nil
+                       (let ((filename
+                              (cond
+                               (buffer-file-name)
+                               ((eq major-mode 'dired-mode)
+                                (dired-get-filename nil t)))))
+                         (and filename (file-relative-name filename))))
+    current-prefix-arg
+    shell-command-default-error-buffer))
+  ;; Look for a handler in case default-directory is a remote file name.
+  (let ((handler
+        (find-file-name-handler (directory-file-name default-directory)
+                                'shell-command)))
+    (if handler
+       (funcall handler 'shell-command command output-buffer error-buffer)
+      (if (and output-buffer
+              (not (or (bufferp output-buffer)  (stringp output-buffer))))
+         ;; Output goes in current buffer.
+         (let ((error-file
+                (if error-buffer
+                    (make-temp-file
+                     (expand-file-name "scor"
+                                       (or small-temporary-file-directory
+                                           temporary-file-directory)))
+                  nil)))
+           (barf-if-buffer-read-only)
+           (push-mark nil t)
+           ;; We do not use -f for csh; we will not support broken use of
+           ;; .cshrcs.  Even the BSD csh manual says to use
+           ;; "if ($?prompt) exit" before things which are not useful
+           ;; non-interactively.  Besides, if someone wants their other
+           ;; aliases for shell commands then they can still have them.
+           (call-process shell-file-name nil
+                         (if error-file
+                             (list t error-file)
+                           t)
+                         nil shell-command-switch command)
+           (when (and error-file (file-exists-p error-file))
+             (if (< 0 (nth 7 (file-attributes error-file)))
+                 (with-current-buffer (get-buffer-create error-buffer)
+                   (let ((pos-from-end (- (point-max) (point))))
+                     (or (bobp)
+                         (insert "\f\n"))
+                     ;; Do no formatting while reading error file,
+                     ;; because that can run a shell command, and we
+                     ;; don't want that to cause an infinite recursion.
+                     (format-insert-file error-file nil)
+                     ;; Put point after the inserted errors.
+                     (goto-char (- (point-max) pos-from-end)))
+                   (display-buffer (current-buffer))))
+             (delete-file error-file))
+           ;; This is like exchange-point-and-mark, but doesn't
+           ;; activate the mark.  It is cleaner to avoid activation,
+           ;; even though the command loop would deactivate the mark
+           ;; because we inserted text.
+           (goto-char (prog1 (mark t)
+                        (set-marker (mark-marker) (point)
+                                    (current-buffer)))))
+       ;; Output goes in a separate buffer.
+       ;; Preserve the match data in case called from a program.
+       (save-match-data
+         (if (string-match "[ \t]*&[ \t]*\\'" command)
+             ;; Command ending with ampersand means asynchronous.
+             (let ((buffer (get-buffer-create
+                            (or output-buffer "*Async Shell Command*")))
+                   (directory default-directory)
+                   proc)
+               ;; Remove the ampersand.
+               (setq command (substring command 0 (match-beginning 0)))
+               ;; Ask the user what to do with already running process.
+               (setq proc (get-buffer-process buffer))
+               (when proc
+                 (cond
+                  ((eq async-shell-command-buffer 'confirm-kill-process)
+                   ;; If will kill a process, query first.
+                   (if (yes-or-no-p "A command is running in the default 
buffer.  Kill it? ")
+                       (kill-process proc)
+                     (error "Shell command in progress")))
+                  ((eq async-shell-command-buffer 'confirm-new-buffer)
+                   ;; If will create a new buffer, query first.
+                   (if (yes-or-no-p "A command is running in the default 
buffer.  Use a new buffer? ")
+                       (setq buffer (generate-new-buffer
+                                     (or output-buffer "*Async Shell 
Command*")))
+                     (error "Shell command in progress")))
+                  ((eq async-shell-command-buffer 'new-buffer)
+                   ;; It will create a new buffer.
+                   (setq buffer (generate-new-buffer
+                                 (or output-buffer "*Async Shell Command*"))))
+                  ((eq async-shell-command-buffer 'confirm-rename-buffer)
+                   ;; If will rename the buffer, query first.
+                   (if (yes-or-no-p "A command is running in the default 
buffer.  Rename it? ")
+                       (progn
+                         (with-current-buffer buffer
+                           (rename-uniquely))
+                         (setq buffer (get-buffer-create
+                                       (or output-buffer "*Async Shell 
Command*"))))
+                     (error "Shell command in progress")))
+                  ((eq async-shell-command-buffer 'rename-buffer)
+                   ;; It will rename the buffer.
+                   (with-current-buffer buffer
+                     (rename-uniquely))
+                   (setq buffer (get-buffer-create
+                                 (or output-buffer "*Async Shell 
Command*"))))))
+               (with-current-buffer buffer
+                 (setq buffer-read-only nil)
+                 ;; Setting buffer-read-only to nil doesn't suffice
+                 ;; if some text has a non-nil read-only property,
+                 ;; which comint sometimes adds for prompts.
+                 (let ((inhibit-read-only t))
+                   (erase-buffer))
+                 (display-buffer buffer '(nil (allow-no-window . t)))
+                 (setq default-directory directory)
+                 (setq proc (start-process "Shell" buffer shell-file-name
+                                           shell-command-switch command))
+                 (setq mode-line-process '(":%s"))
+                 (require 'shell) (shell-mode)
+                 (set-process-sentinel proc 'shell-command-sentinel)
+                 ;; Use the comint filter for proper handling of carriage 
motion
+                 ;; (see `comint-inhibit-carriage-motion'),.
+                 (set-process-filter proc 'comint-output-filter)
+                 ))
+           ;; Otherwise, command is executed synchronously.
+           (shell-command-on-region (point) (point) command
+                                    output-buffer nil error-buffer)))))))
+
+(defun display-message-or-buffer (message
+                                 &optional buffer-name not-this-window frame)
+  "Display MESSAGE in the echo area if possible, otherwise in a pop-up buffer.
+MESSAGE may be either a string or a buffer.
+
+A buffer is displayed using `display-buffer' if MESSAGE is too long for
+the maximum height of the echo area, as defined by `max-mini-window-height'
+if `resize-mini-windows' is non-nil.
+
+Returns either the string shown in the echo area, or when a pop-up
+buffer is used, the window used to display it.
+
+If MESSAGE is a string, then the optional argument BUFFER-NAME is the
+name of the buffer used to display it in the case where a pop-up buffer
+is used, defaulting to `*Message*'.  In the case where MESSAGE is a
+string and it is displayed in the echo area, it is not specified whether
+the contents are inserted into the buffer anyway.
+
+Optional arguments NOT-THIS-WINDOW and FRAME are as for `display-buffer',
+and only used if a buffer is displayed."
+  (cond ((and (stringp message) (not (string-match "\n" message)))
+        ;; Trivial case where we can use the echo area
+        (message "%s" message))
+       ((and (stringp message)
+             (= (string-match "\n" message) (1- (length message))))
+        ;; Trivial case where we can just remove single trailing newline
+        (message "%s" (substring message 0 (1- (length message)))))
+       (t
+        ;; General case
+        (with-current-buffer
+            (if (bufferp message)
+                message
+              (get-buffer-create (or buffer-name "*Message*")))
+
+          (unless (bufferp message)
+            (erase-buffer)
+            (insert message))
+
+          (let ((lines
+                 (if (= (buffer-size) 0)
+                     0
+                   (count-screen-lines nil nil nil (minibuffer-window)))))
+            (cond ((= lines 0))
+                  ((and (or (<= lines 1)
+                            (<= lines
+                                (if resize-mini-windows
+                                    (cond ((floatp max-mini-window-height)
+                                           (* (frame-height)
+                                              max-mini-window-height))
+                                          ((integerp max-mini-window-height)
+                                           max-mini-window-height)
+                                          (t
+                                           1))
+                                  1)))
+                        ;; Don't use the echo area if the output buffer is
+                        ;; already displayed in the selected frame.
+                        (not (get-buffer-window (current-buffer))))
+                   ;; Echo area
+                   (goto-char (point-max))
+                   (when (bolp)
+                     (backward-char 1))
+                   (message "%s" (buffer-substring (point-min) (point))))
+                  (t
+                   ;; Buffer
+                   (goto-char (point-min))
+                   (display-buffer (current-buffer)
+                                   not-this-window frame))))))))
+
+
+;; We have a sentinel to prevent insertion of a termination message
+;; in the buffer itself.
+(defun shell-command-sentinel (process signal)
+  (if (memq (process-status process) '(exit signal))
+      (message "%s: %s."
+              (car (cdr (cdr (process-command process))))
+              (substring signal 0 -1))))
+
+(defun shell-command-on-region (start end command
+                                     &optional output-buffer replace
+                                     error-buffer display-error-buffer)
+  "Execute string COMMAND in inferior shell with region as input.
+Normally display output (if any) in temp buffer `*Shell Command Output*';
+Prefix arg means replace the region with it.  Return the exit code of
+COMMAND.
+
+To specify a coding system for converting non-ASCII characters
+in the input and output to the shell command, use 
\\[universal-coding-system-argument]
+before this command.  By default, the input (from the current buffer)
+is encoded using coding-system specified by `process-coding-system-alist',
+falling back to `default-process-coding-system' if no match for COMMAND
+is found in `process-coding-system-alist'.
+
+Noninteractive callers can specify coding systems by binding
+`coding-system-for-read' and `coding-system-for-write'.
+
+If the command generates output, the output may be displayed
+in the echo area or in a buffer.
+If the output is short enough to display in the echo area
+\(determined by the variable `max-mini-window-height' if
+`resize-mini-windows' is non-nil), it is shown there.
+Otherwise it is displayed in the buffer `*Shell Command Output*'.
+The output is available in that buffer in both cases.
+
+If there is output and an error, a message about the error
+appears at the end of the output.  If there is no output, or if
+output is inserted in the current buffer, the buffer `*Shell
+Command Output*' is deleted.
+
+Optional fourth arg OUTPUT-BUFFER specifies where to put the
+command's output.  If the value is a buffer or buffer name,
+put the output there.  If the value is nil, use the buffer
+`*Shell Command Output*'.  Any other value, excluding nil,
+means to insert the output in the current buffer.  In either case,
+the output is inserted after point (leaving mark after it).
+
+Optional fifth arg REPLACE, if non-nil, means to insert the
+output in place of text from START to END, putting point and mark
+around it.
+
+Optional sixth arg ERROR-BUFFER, if non-nil, specifies a buffer
+or buffer name to which to direct the command's standard error
+output.  If nil, error output is mingled with regular output.
+When called interactively, `shell-command-default-error-buffer'
+is used for ERROR-BUFFER.
+
+Optional seventh arg DISPLAY-ERROR-BUFFER, if non-nil, means to
+display the error buffer if there were any errors.  When called
+interactively, this is t."
+  (interactive (let (string)
+                (unless (mark)
+                  (error "The mark is not set now, so there is no region"))
+                ;; Do this before calling region-beginning
+                ;; and region-end, in case subprocess output
+                ;; relocates them while we are in the minibuffer.
+                (setq string (read-shell-command "Shell command on region: "))
+                ;; call-interactively recognizes region-beginning and
+                ;; region-end specially, leaving them in the history.
+                (list (region-beginning) (region-end)
+                      string
+                      current-prefix-arg
+                      current-prefix-arg
+                      shell-command-default-error-buffer
+                      t)))
+  (let ((error-file
+        (if error-buffer
+            (make-temp-file
+             (expand-file-name "scor"
+                               (or small-temporary-file-directory
+                                   temporary-file-directory)))
+          nil))
+       exit-status)
+    (if (or replace
+           (and output-buffer
+                (not (or (bufferp output-buffer) (stringp output-buffer)))))
+       ;; Replace specified region with output from command.
+       (let ((swap (and replace (< start end))))
+         ;; Don't muck with mark unless REPLACE says we should.
+         (goto-char start)
+         (and replace (push-mark (point) 'nomsg))
+         (setq exit-status
+               (call-process-region start end shell-file-name replace
+                                    (if error-file
+                                        (list t error-file)
+                                      t)
+                                    nil shell-command-switch command))
+         ;; It is rude to delete a buffer which the command is not using.
+         ;; (let ((shell-buffer (get-buffer "*Shell Command Output*")))
+         ;;   (and shell-buffer (not (eq shell-buffer (current-buffer)))
+         ;;     (kill-buffer shell-buffer)))
+         ;; Don't muck with mark unless REPLACE says we should.
+         (and replace swap (exchange-point-and-mark)))
+      ;; No prefix argument: put the output in a temp buffer,
+      ;; replacing its entire contents.
+      (let ((buffer (get-buffer-create
+                    (or output-buffer "*Shell Command Output*"))))
+       (unwind-protect
+           (if (eq buffer (current-buffer))
+               ;; If the input is the same buffer as the output,
+               ;; delete everything but the specified region,
+               ;; then replace that region with the output.
+               (progn (setq buffer-read-only nil)
+                      (delete-region (max start end) (point-max))
+                      (delete-region (point-min) (min start end))
+                      (setq exit-status
+                            (call-process-region (point-min) (point-max)
+                                                 shell-file-name t
+                                                 (if error-file
+                                                     (list t error-file)
+                                                   t)
+                                                 nil shell-command-switch
+                                                 command)))
+             ;; Clear the output buffer, then run the command with
+             ;; output there.
+             (let ((directory default-directory))
+               (with-current-buffer buffer
+                 (setq buffer-read-only nil)
+                 (if (not output-buffer)
+                     (setq default-directory directory))
+                 (erase-buffer)))
+             (setq exit-status
+                   (call-process-region start end shell-file-name nil
+                                        (if error-file
+                                            (list buffer error-file)
+                                          buffer)
+                                        nil shell-command-switch command)))
+         ;; Report the output.
+         (with-current-buffer buffer
+           (setq mode-line-process
+                 (cond ((null exit-status)
+                        " - Error")
+                       ((stringp exit-status)
+                        (format " - Signal [%s]" exit-status))
+                       ((not (equal 0 exit-status))
+                        (format " - Exit [%d]" exit-status)))))
+         (if (with-current-buffer buffer (> (point-max) (point-min)))
+             ;; There's some output, display it
+             (display-message-or-buffer buffer)
+           ;; No output; error?
+           (let ((output
+                  (if (and error-file
+                           (< 0 (nth 7 (file-attributes error-file))))
+                      (format "some error output%s"
+                              (if shell-command-default-error-buffer
+                                  (format " to the \"%s\" buffer"
+                                          shell-command-default-error-buffer)
+                                ""))
+                    "no output")))
+             (cond ((null exit-status)
+                    (message "(Shell command failed with error)"))
+                   ((equal 0 exit-status)
+                    (message "(Shell command succeeded with %s)"
+                             output))
+                   ((stringp exit-status)
+                    (message "(Shell command killed by signal %s)"
+                             exit-status))
+                   (t
+                    (message "(Shell command failed with code %d and %s)"
+                             exit-status output))))
+           ;; Don't kill: there might be useful info in the undo-log.
+           ;; (kill-buffer buffer)
+           ))))
+
+    (when (and error-file (file-exists-p error-file))
+      (if (< 0 (nth 7 (file-attributes error-file)))
+         (with-current-buffer (get-buffer-create error-buffer)
+           (let ((pos-from-end (- (point-max) (point))))
+             (or (bobp)
+                 (insert "\f\n"))
+             ;; Do no formatting while reading error file,
+             ;; because that can run a shell command, and we
+             ;; don't want that to cause an infinite recursion.
+             (format-insert-file error-file nil)
+             ;; Put point after the inserted errors.
+             (goto-char (- (point-max) pos-from-end)))
+           (and display-error-buffer
+                (display-buffer (current-buffer)))))
+      (delete-file error-file))
+    exit-status))
+
+(defun shell-command-to-string (command)
+  "Execute shell command COMMAND and return its output as a string."
+  (with-output-to-string
+    (with-current-buffer
+      standard-output
+      (process-file shell-file-name nil t nil shell-command-switch command))))
+
+(defun process-file (program &optional infile buffer display &rest args)
+  "Process files synchronously in a separate process.
+Similar to `call-process', but may invoke a file handler based on
+`default-directory'.  The current working directory of the
+subprocess is `default-directory'.
+
+File names in INFILE and BUFFER are handled normally, but file
+names in ARGS should be relative to `default-directory', as they
+are passed to the process verbatim.  (This is a difference to
+`call-process' which does not support file handlers for INFILE
+and BUFFER.)
+
+Some file handlers might not support all variants, for example
+they might behave as if DISPLAY was nil, regardless of the actual
+value passed."
+  (let ((fh (find-file-name-handler default-directory 'process-file))
+        lc stderr-file)
+    (unwind-protect
+        (if fh (apply fh 'process-file program infile buffer display args)
+          (when infile (setq lc (file-local-copy infile)))
+          (setq stderr-file (when (and (consp buffer) (stringp (cadr buffer)))
+                              (make-temp-file "emacs")))
+          (prog1
+              (apply 'call-process program
+                     (or lc infile)
+                     (if stderr-file (list (car buffer) stderr-file) buffer)
+                     display args)
+            (when stderr-file (copy-file stderr-file (cadr buffer) t))))
+      (when stderr-file (delete-file stderr-file))
+      (when lc (delete-file lc)))))
+
+(defvar process-file-side-effects t
+  "Whether a call of `process-file' changes remote files.
+
+By default, this variable is always set to `t', meaning that a
+call of `process-file' could potentially change any file on a
+remote host.  When set to `nil', a file handler could optimize
+its behavior with respect to remote file attribute caching.
+
+You should only ever change this variable with a let-binding;
+never with `setq'.")
+
+(defun start-file-process (name buffer program &rest program-args)
+  "Start a program in a subprocess.  Return the process object for it.
+
+Similar to `start-process', but may invoke a file handler based on
+`default-directory'.  See Info node `(elisp)Magic File Names'.
+
+This handler ought to run PROGRAM, perhaps on the local host,
+perhaps on a remote host that corresponds to `default-directory'.
+In the latter case, the local part of `default-directory' becomes
+the working directory of the process.
+
+PROGRAM and PROGRAM-ARGS might be file names.  They are not
+objects of file handler invocation.  File handlers might not
+support pty association, if PROGRAM is nil."
+  (let ((fh (find-file-name-handler default-directory 'start-file-process)))
+    (if fh (apply fh 'start-file-process name buffer program program-args)
+      (apply 'start-process name buffer program program-args))))
+
+;;;; Process menu
+
+(defvar tabulated-list-format)
+(defvar tabulated-list-entries)
+(defvar tabulated-list-sort-key)
+(declare-function tabulated-list-init-header  "tabulated-list" ())
+(declare-function tabulated-list-print "tabulated-list"
+                  (&optional remember-pos))
+
+(defvar process-menu-query-only nil)
+
+(define-derived-mode process-menu-mode tabulated-list-mode "Process Menu"
+  "Major mode for listing the processes called by Emacs."
+  (setq tabulated-list-format [("Process" 15 t)
+                              ("Status"   7 t)
+                              ("Buffer"  15 t)
+                              ("TTY"     12 t)
+                              ("Command"  0 t)])
+  (make-local-variable 'process-menu-query-only)
+  (setq tabulated-list-sort-key (cons "Process" nil))
+  (add-hook 'tabulated-list-revert-hook 'list-processes--refresh nil t)
+  (tabulated-list-init-header))
+
+(defun list-processes--refresh ()
+  "Recompute the list of processes for the Process List buffer.
+Also, delete any process that is exited or signaled."
+  (setq tabulated-list-entries nil)
+  (dolist (p (process-list))
+    (cond ((memq (process-status p) '(exit signal closed))
+          (delete-process p))
+         ((or (not process-menu-query-only)
+              (process-query-on-exit-flag p))
+          (let* ((buf (process-buffer p))
+                 (type (process-type p))
+                 (name (process-name p))
+                 (status (symbol-name (process-status p)))
+                 (buf-label (if (buffer-live-p buf)
+                                `(,(buffer-name buf)
+                                  face link
+                                  help-echo ,(concat "Visit buffer `"
+                                                     (buffer-name buf) "'")
+                                  follow-link t
+                                  process-buffer ,buf
+                                  action process-menu-visit-buffer)
+                              "--"))
+                 (tty (or (process-tty-name p) "--"))
+                 (cmd
+                  (if (memq type '(network serial))
+                      (let ((contact (process-contact p t)))
+                        (if (eq type 'network)
+                            (format "(%s %s)"
+                                    (if (plist-get contact :type)
+                                        "datagram"
+                                      "network")
+                                    (if (plist-get contact :server)
+                                        (format "server on %s"
+                                                (or
+                                                 (plist-get contact :host)
+                                                 (plist-get contact :local)))
+                                      (format "connection to %s"
+                                              (plist-get contact :host))))
+                          (format "(serial port %s%s)"
+                                  (or (plist-get contact :port) "?")
+                                  (let ((speed (plist-get contact :speed)))
+                                    (if speed
+                                        (format " at %s b/s" speed)
+                                      "")))))
+                    (mapconcat 'identity (process-command p) " "))))
+            (push (list p (vector name status buf-label tty cmd))
+                  tabulated-list-entries))))))
+
+(defun process-menu-visit-buffer (button)
+  (display-buffer (button-get button 'process-buffer)))
+
+(defun list-processes (&optional query-only buffer)
+  "Display a list of all processes that are Emacs sub-processes.
+If optional argument QUERY-ONLY is non-nil, only processes with
+the query-on-exit flag set are listed.
+Any process listed as exited or signaled is actually eliminated
+after the listing is made.
+Optional argument BUFFER specifies a buffer to use, instead of
+\"*Process List*\".
+The return value is always nil.
+
+This function lists only processes that were launched by Emacs.  To
+see other processes running on the system, use `list-system-processes'."
+  (interactive)
+  (or (fboundp 'process-list)
+      (error "Asynchronous subprocesses are not supported on this system"))
+  (unless (bufferp buffer)
+    (setq buffer (get-buffer-create "*Process List*")))
+  (with-current-buffer buffer
+    (process-menu-mode)
+    (setq process-menu-query-only query-only)
+    (list-processes--refresh)
+    (tabulated-list-print))
+  (display-buffer buffer)
+  nil)
+
+(defvar universal-argument-map
+  (let ((map (make-sparse-keymap))
+        (universal-argument-minus
+         ;; For backward compatibility, minus with no modifiers is an ordinary
+         ;; command if digits have already been entered.
+         `(menu-item "" negative-argument
+                     :filter ,(lambda (cmd)
+                                (if (integerp prefix-arg) nil cmd)))))
+    (define-key map [switch-frame]
+      (lambda (e) (interactive "e")
+        (handle-switch-frame e) (universal-argument--mode)))
+    (define-key map [?\C-u] 'universal-argument-more)
+    (define-key map [?-] universal-argument-minus)
+    (define-key map [?0] 'digit-argument)
+    (define-key map [?1] 'digit-argument)
+    (define-key map [?2] 'digit-argument)
+    (define-key map [?3] 'digit-argument)
+    (define-key map [?4] 'digit-argument)
+    (define-key map [?5] 'digit-argument)
+    (define-key map [?6] 'digit-argument)
+    (define-key map [?7] 'digit-argument)
+    (define-key map [?8] 'digit-argument)
+    (define-key map [?9] 'digit-argument)
+    (define-key map [kp-0] 'digit-argument)
+    (define-key map [kp-1] 'digit-argument)
+    (define-key map [kp-2] 'digit-argument)
+    (define-key map [kp-3] 'digit-argument)
+    (define-key map [kp-4] 'digit-argument)
+    (define-key map [kp-5] 'digit-argument)
+    (define-key map [kp-6] 'digit-argument)
+    (define-key map [kp-7] 'digit-argument)
+    (define-key map [kp-8] 'digit-argument)
+    (define-key map [kp-9] 'digit-argument)
+    (define-key map [kp-subtract] universal-argument-minus)
+    map)
+  "Keymap used while processing \\[universal-argument].")
+
+(defun universal-argument--mode ()
+  (set-transient-map universal-argument-map))
+
+(defun universal-argument ()
+  "Begin a numeric argument for the following command.
+Digits or minus sign following \\[universal-argument] make up the numeric 
argument.
+\\[universal-argument] following the digits or minus sign ends the argument.
+\\[universal-argument] without digits or minus sign provides 4 as argument.
+Repeating \\[universal-argument] without digits or minus sign
+ multiplies the argument by 4 each time.
+For some commands, just \\[universal-argument] by itself serves as a flag
+which is different in effect from any particular numeric argument.
+These commands include \\[set-mark-command] and \\[start-kbd-macro]."
+  (interactive)
+  (setq prefix-arg (list 4))
+  (universal-argument--mode))
+
+(defun universal-argument-more (arg)
+  ;; A subsequent C-u means to multiply the factor by 4 if we've typed
+  ;; nothing but C-u's; otherwise it means to terminate the prefix arg.
+  (interactive "P")
+  (setq prefix-arg (if (consp arg)
+                       (list (* 4 (car arg)))
+                     (if (eq arg '-)
+                         (list -4)
+                       arg)))
+  (when (consp prefix-arg) (universal-argument--mode)))
+
+(defun negative-argument (arg)
+  "Begin a negative numeric argument for the next command.
+\\[universal-argument] following digits or minus sign ends the argument."
+  (interactive "P")
+  (setq prefix-arg (cond ((integerp arg) (- arg))
+                         ((eq arg '-) nil)
+                         (t '-)))
+  (universal-argument--mode))
+
+(defun digit-argument (arg)
+  "Part of the numeric argument for the next command.
+\\[universal-argument] following digits or minus sign ends the argument."
+  (interactive "P")
+  (let* ((char (if (integerp last-command-event)
+                  last-command-event
+                (get last-command-event 'ascii-character)))
+        (digit (- (logand char ?\177) ?0)))
+    (setq prefix-arg (cond ((integerp arg)
+                            (+ (* arg 10)
+                              (if (< arg 0) (- digit) digit)))
+                           ((eq arg '-)
+                            ;; Treat -0 as just -, so that -01 will work.
+                            (if (zerop digit) '- (- digit)))
+                           (t
+                            digit))))
+  (universal-argument--mode))
+
+
+(defvar filter-buffer-substring-functions nil
+  "This variable is a wrapper hook around `buffer-substring--filter'.")
+(make-obsolete-variable 'filter-buffer-substring-functions
+                        'filter-buffer-substring-function "24.4")
+
+(defvar filter-buffer-substring-function #'buffer-substring--filter
+  "Function to perform the filtering in `filter-buffer-substring'.
+The function is called with the same 3 arguments (BEG END DELETE)
+that `filter-buffer-substring' received.  It should return the
+buffer substring between BEG and END, after filtering.  If DELETE is
+non-nil, it should delete the text between BEG and END from the buffer.")
+
+(defvar buffer-substring-filters nil
+  "List of filter functions for `buffer-substring--filter'.
+Each function must accept a single argument, a string, and return a string.
+The buffer substring is passed to the first function in the list,
+and the return value of each function is passed to the next.
+As a special convention, point is set to the start of the buffer text
+being operated on (i.e., the first argument of `buffer-substring--filter')
+before these functions are called.")
+(make-obsolete-variable 'buffer-substring-filters
+                        'filter-buffer-substring-function "24.1")
+
+(defun filter-buffer-substring (beg end &optional delete)
+  "Return the buffer substring between BEG and END, after filtering.
+If DELETE is non-nil, delete the text between BEG and END from the buffer.
+
+This calls the function that `filter-buffer-substring-function' specifies
+\(passing the same three arguments that it received) to do the work,
+and returns whatever it does.  The default function does no filtering,
+unless a hook has been set.
+
+Use `filter-buffer-substring' instead of `buffer-substring',
+`buffer-substring-no-properties', or `delete-and-extract-region' when
+you want to allow filtering to take place.  For example, major or minor
+modes can use `filter-buffer-substring-function' to extract characters
+that are special to a buffer, and should not be copied into other buffers."
+  (funcall filter-buffer-substring-function beg end delete))
+
+(defun buffer-substring--filter (beg end &optional delete)
+  "Default function to use for `filter-buffer-substring-function'.
+Its arguments and return value are as specified for `filter-buffer-substring'.
+This respects the wrapper hook `filter-buffer-substring-functions',
+and the abnormal hook `buffer-substring-filters'.
+No filtering is done unless a hook says to."
+  (with-wrapper-hook filter-buffer-substring-functions (beg end delete)
+    (cond
+     ((or delete buffer-substring-filters)
+      (save-excursion
+        (goto-char beg)
+        (let ((string (if delete (delete-and-extract-region beg end)
+                        (buffer-substring beg end))))
+          (dolist (filter buffer-substring-filters)
+            (setq string (funcall filter string)))
+          string)))
+     (t
+      (buffer-substring beg end)))))
+
+
+;;;; Window system cut and paste hooks.
+
+(defvar interprogram-cut-function nil
+  "Function to call to make a killed region available to other programs.
+Most window systems provide a facility for cutting and pasting
+text between different programs, such as the clipboard on X and
+MS-Windows, or the pasteboard on Nextstep/Mac OS.
+
+This variable holds a function that Emacs calls whenever text is
+put in the kill ring, to make the new kill available to other
+programs.  The function takes one argument, TEXT, which is a
+string containing the text which should be made available.")
+
+(defvar interprogram-paste-function nil
+  "Function to call to get text cut from other programs.
+Most window systems provide a facility for cutting and pasting
+text between different programs, such as the clipboard on X and
+MS-Windows, or the pasteboard on Nextstep/Mac OS.
+
+This variable holds a function that Emacs calls to obtain text
+that other programs have provided for pasting.  The function is
+called with no arguments.  If no other program has provided text
+to paste, the function should return nil (in which case the
+caller, usually `current-kill', should use the top of the Emacs
+kill ring).  If another program has provided text to paste, the
+function should return that text as a string (in which case the
+caller should put this string in the kill ring as the latest
+kill).
+
+The function may also return a list of strings if the window
+system supports multiple selections.  The first string will be
+used as the pasted text, but the other will be placed in the kill
+ring for easy access via `yank-pop'.
+
+Note that the function should return a string only if a program
+other than Emacs has provided a string for pasting; if Emacs
+provided the most recent string, the function should return nil.
+If it is difficult to tell whether Emacs or some other program
+provided the current string, it is probably good enough to return
+nil if the string is equal (according to `string=') to the last
+text Emacs provided.")
+
+
+
+;;;; The kill ring data structure.
+
+(defvar kill-ring nil
+  "List of killed text sequences.
+Since the kill ring is supposed to interact nicely with cut-and-paste
+facilities offered by window systems, use of this variable should
+interact nicely with `interprogram-cut-function' and
+`interprogram-paste-function'.  The functions `kill-new',
+`kill-append', and `current-kill' are supposed to implement this
+interaction; you may want to use them instead of manipulating the kill
+ring directly.")
+
+(defcustom kill-ring-max 60
+  "Maximum length of kill ring before oldest elements are thrown away."
+  :type 'integer
+  :group 'killing)
+
+(defvar kill-ring-yank-pointer nil
+  "The tail of the kill ring whose car is the last thing yanked.")
+
+(defcustom save-interprogram-paste-before-kill nil
+  "Save clipboard strings into kill ring before replacing them.
+When one selects something in another program to paste it into Emacs,
+but kills something in Emacs before actually pasting it,
+this selection is gone unless this variable is non-nil,
+in which case the other program's selection is saved in the `kill-ring'
+before the Emacs kill and one can still paste it using \\[yank] \\[yank-pop]."
+  :type 'boolean
+  :group 'killing
+  :version "23.2")
+
+(defcustom kill-do-not-save-duplicates nil
+  "Do not add a new string to `kill-ring' if it duplicates the last one.
+The comparison is done using `equal-including-properties'."
+  :type 'boolean
+  :group 'killing
+  :version "23.2")
+
+(defun kill-new (string &optional replace)
+  "Make STRING the latest kill in the kill ring.
+Set `kill-ring-yank-pointer' to point to it.
+If `interprogram-cut-function' is non-nil, apply it to STRING.
+Optional second argument REPLACE non-nil means that STRING will replace
+the front of the kill ring, rather than being added to the list.
+
+When `save-interprogram-paste-before-kill' and `interprogram-paste-function'
+are non-nil, saves the interprogram paste string(s) into `kill-ring' before
+STRING.
+
+When the yank handler has a non-nil PARAM element, the original STRING
+argument is not used by `insert-for-yank'.  However, since Lisp code
+may access and use elements from the kill ring directly, the STRING
+argument should still be a \"useful\" string for such uses."
+  (unless (and kill-do-not-save-duplicates
+              ;; Due to text properties such as 'yank-handler that
+              ;; can alter the contents to yank, comparison using
+              ;; `equal' is unsafe.
+              (equal-including-properties string (car kill-ring)))
+    (if (fboundp 'menu-bar-update-yank-menu)
+       (menu-bar-update-yank-menu string (and replace (car kill-ring)))))
+  (when save-interprogram-paste-before-kill
+    (let ((interprogram-paste (and interprogram-paste-function
+                                   (funcall interprogram-paste-function))))
+      (when interprogram-paste
+        (dolist (s (if (listp interprogram-paste)
+                      (nreverse interprogram-paste)
+                    (list interprogram-paste)))
+         (unless (and kill-do-not-save-duplicates
+                      (equal-including-properties s (car kill-ring)))
+           (push s kill-ring))))))
+  (unless (and kill-do-not-save-duplicates
+              (equal-including-properties string (car kill-ring)))
+    (if (and replace kill-ring)
+       (setcar kill-ring string)
+      (push string kill-ring)
+      (if (> (length kill-ring) kill-ring-max)
+         (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))))
+  (setq kill-ring-yank-pointer kill-ring)
+  (if interprogram-cut-function
+      (funcall interprogram-cut-function string)))
+
+(defun kill-append (string before-p)
+  "Append STRING to the end of the latest kill in the kill ring.
+If BEFORE-P is non-nil, prepend STRING to the kill.
+If `interprogram-cut-function' is set, pass the resulting kill to it."
+  (let* ((cur (car kill-ring)))
+    (kill-new (if before-p (concat string cur) (concat cur string))
+             (or (= (length cur) 0)
+                 (equal nil (get-text-property 0 'yank-handler cur))))))
+
+(defcustom yank-pop-change-selection nil
+  "Whether rotating the kill ring changes the window system selection.
+If non-nil, whenever the kill ring is rotated (usually via the
+`yank-pop' command), Emacs also calls `interprogram-cut-function'
+to copy the new kill to the window system selection."
+  :type 'boolean
+  :group 'killing
+  :version "23.1")
+
+(defun current-kill (n &optional do-not-move)
+  "Rotate the yanking point by N places, and then return that kill.
+If N is zero and `interprogram-paste-function' is set to a
+function that returns a string or a list of strings, and if that
+function doesn't return nil, then that string (or list) is added
+to the front of the kill ring and the string (or first string in
+the list) is returned as the latest kill.
+
+If N is not zero, and if `yank-pop-change-selection' is
+non-nil, use `interprogram-cut-function' to transfer the
+kill at the new yank point into the window system selection.
+
+If optional arg DO-NOT-MOVE is non-nil, then don't actually
+move the yanking point; just return the Nth kill forward."
+
+  (let ((interprogram-paste (and (= n 0)
+                                interprogram-paste-function
+                                (funcall interprogram-paste-function))))
+    (if interprogram-paste
+       (progn
+         ;; Disable the interprogram cut function when we add the new
+         ;; text to the kill ring, so Emacs doesn't try to own the
+         ;; selection, with identical text.
+         (let ((interprogram-cut-function nil))
+           (if (listp interprogram-paste)
+             (mapc 'kill-new (nreverse interprogram-paste))
+             (kill-new interprogram-paste)))
+         (car kill-ring))
+      (or kill-ring (error "Kill ring is empty"))
+      (let ((ARGth-kill-element
+            (nthcdr (mod (- n (length kill-ring-yank-pointer))
+                         (length kill-ring))
+                    kill-ring)))
+       (unless do-not-move
+         (setq kill-ring-yank-pointer ARGth-kill-element)
+         (when (and yank-pop-change-selection
+                    (> n 0)
+                    interprogram-cut-function)
+           (funcall interprogram-cut-function (car ARGth-kill-element))))
+       (car ARGth-kill-element)))))
+
+
+
+;;;; Commands for manipulating the kill ring.
+
+(defcustom kill-read-only-ok nil
+  "Non-nil means don't signal an error for killing read-only text."
+  :type 'boolean
+  :group 'killing)
+
+(defun kill-region (beg end &optional region)
+  "Kill (\"cut\") text between point and mark.
+This deletes the text from the buffer and saves it in the kill ring.
+The command \\[yank] can retrieve it from there.
+\(If you want to save the region without killing it, use \\[kill-ring-save].)
+
+If you want to append the killed region to the last killed text,
+use \\[append-next-kill] before \\[kill-region].
+
+If the buffer is read-only, Emacs will beep and refrain from deleting
+the text, but put the text in the kill ring anyway.  This means that
+you can use the killing commands to copy text from a read-only buffer.
+
+Lisp programs should use this function for killing text.
+ (To delete text, use `delete-region'.)
+Supply two arguments, character positions indicating the stretch of text
+ to be killed.
+Any command that calls this function is a \"kill command\".
+If the previous command was also a kill command,
+the text killed this time appends to the text killed last time
+to make one entry in the kill ring.
+
+The optional argument REGION if non-nil, indicates that we're not just killing
+some text between BEG and END, but we're killing the region."
+  ;; Pass mark first, then point, because the order matters when
+  ;; calling `kill-append'.
+  (interactive (list (mark) (point) 'region))
+  (unless (and beg end)
+    (error "The mark is not set now, so there is no region"))
+  (condition-case nil
+      (let ((string (if region
+                        (funcall region-extract-function 'delete)
+                      (filter-buffer-substring beg end 'delete))))
+       (when string                    ;STRING is nil if BEG = END
+         ;; Add that string to the kill ring, one way or another.
+         (if (eq last-command 'kill-region)
+             (kill-append string (< end beg))
+           (kill-new string nil)))
+       (when (or string (eq last-command 'kill-region))
+         (setq this-command 'kill-region))
+       (setq deactivate-mark t)
+       nil)
+    ((buffer-read-only text-read-only)
+     ;; The code above failed because the buffer, or some of the characters
+     ;; in the region, are read-only.
+     ;; We should beep, in case the user just isn't aware of this.
+     ;; However, there's no harm in putting
+     ;; the region's text in the kill ring, anyway.
+     (copy-region-as-kill beg end region)
+     ;; Set this-command now, so it will be set even if we get an error.
+     (setq this-command 'kill-region)
+     ;; This should barf, if appropriate, and give us the correct error.
+     (if kill-read-only-ok
+        (progn (message "Read only text copied to kill ring") nil)
+       ;; Signal an error if the buffer is read-only.
+       (barf-if-buffer-read-only)
+       ;; If the buffer isn't read-only, the text is.
+       (signal 'text-read-only (list (current-buffer)))))))
+
+;; copy-region-as-kill no longer sets this-command, because it's confusing
+;; to get two copies of the text when the user accidentally types M-w and
+;; then corrects it with the intended C-w.
+(defun copy-region-as-kill (beg end &optional region)
+  "Save the region as if killed, but don't kill it.
+In Transient Mark mode, deactivate the mark.
+If `interprogram-cut-function' is non-nil, also save the text for a window
+system cut and paste.
+
+The optional argument REGION if non-nil, indicates that we're not just copying
+some text between BEG and END, but we're copying the region.
+
+This command's old key binding has been given to `kill-ring-save'."
+  ;; Pass mark first, then point, because the order matters when
+  ;; calling `kill-append'.
+  (interactive (list (mark) (point)
+                    (prefix-numeric-value current-prefix-arg)))
+  (let ((str (if region
+                 (funcall region-extract-function nil)
+               (filter-buffer-substring beg end))))
+  (if (eq last-command 'kill-region)
+        (kill-append str (< end beg))
+      (kill-new str)))
+  (setq deactivate-mark t)
+  nil)
+
+(defun kill-ring-save (beg end &optional region)
+  "Save the region as if killed, but don't kill it.
+In Transient Mark mode, deactivate the mark.
+If `interprogram-cut-function' is non-nil, also save the text for a window
+system cut and paste.
+
+If you want to append the killed line to the last killed text,
+use \\[append-next-kill] before \\[kill-ring-save].
+
+The optional argument REGION if non-nil, indicates that we're not just copying
+some text between BEG and END, but we're copying the region.
+
+This command is similar to `copy-region-as-kill', except that it gives
+visual feedback indicating the extent of the region being copied."
+  ;; Pass mark first, then point, because the order matters when
+  ;; calling `kill-append'.
+  (interactive (list (mark) (point)
+                    (prefix-numeric-value current-prefix-arg)))
+  (copy-region-as-kill beg end region)
+  ;; This use of called-interactively-p is correct because the code it
+  ;; controls just gives the user visual feedback.
+  (if (called-interactively-p 'interactive)
+      (indicate-copied-region)))
+
+(defun indicate-copied-region (&optional message-len)
+  "Indicate that the region text has been copied interactively.
+If the mark is visible in the selected window, blink the cursor
+between point and mark if there is currently no active region
+highlighting.
+
+If the mark lies outside the selected window, display an
+informative message containing a sample of the copied text.  The
+optional argument MESSAGE-LEN, if non-nil, specifies the length
+of this sample text; it defaults to 40."
+  (let ((mark (mark t))
+       (point (point))
+       ;; Inhibit quitting so we can make a quit here
+       ;; look like a C-g typed as a command.
+       (inhibit-quit t))
+    (if (pos-visible-in-window-p mark (selected-window))
+       ;; Swap point-and-mark quickly so as to show the region that
+       ;; was selected.  Don't do it if the region is highlighted.
+       (unless (and (region-active-p)
+                    (face-background 'region))
+         ;; Swap point and mark.
+         (set-marker (mark-marker) (point) (current-buffer))
+         (goto-char mark)
+         (sit-for blink-matching-delay)
+         ;; Swap back.
+         (set-marker (mark-marker) mark (current-buffer))
+         (goto-char point)
+         ;; If user quit, deactivate the mark
+         ;; as C-g would as a command.
+         (and quit-flag mark-active
+              (deactivate-mark)))
+      (let ((len (min (abs (- mark point))
+                     (or message-len 40))))
+       (if (< point mark)
+           ;; Don't say "killed"; that is misleading.
+           (message "Saved text until \"%s\""
+                    (buffer-substring-no-properties (- mark len) mark))
+         (message "Saved text from \"%s\""
+                  (buffer-substring-no-properties mark (+ mark len))))))))
+
+(defun append-next-kill (&optional interactive)
+  "Cause following command, if it kills, to add to previous kill.
+If the next command kills forward from point, the kill is
+appended to the previous killed text.  If the command kills
+backward, the kill is prepended.  Kill commands that act on the
+region, such as `kill-region', are regarded as killing forward if
+point is after mark, and killing backward if point is before
+mark.
+
+If the next command is not a kill command, `append-next-kill' has
+no effect.
+
+The argument is used for internal purposes; do not supply one."
+  (interactive "p")
+  ;; We don't use (interactive-p), since that breaks kbd macros.
+  (if interactive
+      (progn
+       (setq this-command 'kill-region)
+       (message "If the next command is a kill, it will append"))
+    (setq last-command 'kill-region)))
+
+;; Yanking.
+
+(defcustom yank-handled-properties
+  '((font-lock-face . yank-handle-font-lock-face-property)
+    (category . yank-handle-category-property))
+  "List of special text property handling conditions for yanking.
+Each element should have the form (PROP . FUN), where PROP is a
+property symbol and FUN is a function.  When the `yank' command
+inserts text into the buffer, it scans the inserted text for
+stretches of text that have `eq' values of the text property
+PROP; for each such stretch of text, FUN is called with three
+arguments: the property's value in that text, and the start and
+end positions of the text.
+
+This is done prior to removing the properties specified by
+`yank-excluded-properties'."
+  :group 'killing
+  :type '(repeat (cons (symbol :tag "property symbol")
+                       function))
+  :version "24.3")
+
+;; This is actually used in subr.el but defcustom does not work there.
+(defcustom yank-excluded-properties
+  '(category field follow-link fontified font-lock-face help-echo
+    intangible invisible keymap local-map mouse-face read-only
+    yank-handler)
+  "Text properties to discard when yanking.
+The value should be a list of text properties to discard or t,
+which means to discard all text properties.
+
+See also `yank-handled-properties'."
+  :type '(choice (const :tag "All" t) (repeat symbol))
+  :group 'killing
+  :version "24.3")
+
+(defvar yank-window-start nil)
+(defvar yank-undo-function nil
+  "If non-nil, function used by `yank-pop' to delete last stretch of yanked 
text.
+Function is called with two parameters, START and END corresponding to
+the value of the mark and point; it is guaranteed that START <= END.
+Normally set from the UNDO element of a yank-handler; see `insert-for-yank'.")
+
+(defun yank-pop (&optional arg)
+  "Replace just-yanked stretch of killed text with a different stretch.
+This command is allowed only immediately after a `yank' or a `yank-pop'.
+At such a time, the region contains a stretch of reinserted
+previously-killed text.  `yank-pop' deletes that text and inserts in its
+place a different stretch of killed text.
+
+With no argument, the previous kill is inserted.
+With argument N, insert the Nth previous kill.
+If N is negative, this is a more recent kill.
+
+The sequence of kills wraps around, so that after the oldest one
+comes the newest one.
+
+When this command inserts killed text into the buffer, it honors
+`yank-excluded-properties' and `yank-handler' as described in the
+doc string for `insert-for-yank-1', which see."
+  (interactive "*p")
+  (if (not (eq last-command 'yank))
+      (error "Previous command was not a yank"))
+  (setq this-command 'yank)
+  (unless arg (setq arg 1))
+  (let ((inhibit-read-only t)
+       (before (< (point) (mark t))))
+    (if before
+       (funcall (or yank-undo-function 'delete-region) (point) (mark t))
+      (funcall (or yank-undo-function 'delete-region) (mark t) (point)))
+    (setq yank-undo-function nil)
+    (set-marker (mark-marker) (point) (current-buffer))
+    (insert-for-yank (current-kill arg))
+    ;; Set the window start back where it was in the yank command,
+    ;; if possible.
+    (set-window-start (selected-window) yank-window-start t)
+    (if before
+       ;; This is like exchange-point-and-mark, but doesn't activate the mark.
+       ;; It is cleaner to avoid activation, even though the command
+       ;; loop would deactivate the mark because we inserted text.
+       (goto-char (prog1 (mark t)
+                    (set-marker (mark-marker) (point) (current-buffer))))))
+  nil)
+
+(defun yank (&optional arg)
+  "Reinsert (\"paste\") the last stretch of killed text.
+More precisely, reinsert the most recent kill, which is the
+stretch of killed text most recently killed OR yanked.  Put point
+at the end, and set mark at the beginning without activating it.
+With just \\[universal-argument] as argument, put point at beginning, and mark 
at end.
+With argument N, reinsert the Nth most recent kill.
+
+When this command inserts text into the buffer, it honors the
+`yank-handled-properties' and `yank-excluded-properties'
+variables, and the `yank-handler' text property.  See
+`insert-for-yank-1' for details.
+
+See also the command `yank-pop' (\\[yank-pop])."
+  (interactive "*P")
+  (setq yank-window-start (window-start))
+  ;; If we don't get all the way thru, make last-command indicate that
+  ;; for the following command.
+  (setq this-command t)
+  (push-mark (point))
+  (insert-for-yank (current-kill (cond
+                                 ((listp arg) 0)
+                                 ((eq arg '-) -2)
+                                 (t (1- arg)))))
+  (if (consp arg)
+      ;; This is like exchange-point-and-mark, but doesn't activate the mark.
+      ;; It is cleaner to avoid activation, even though the command
+      ;; loop would deactivate the mark because we inserted text.
+      (goto-char (prog1 (mark t)
+                  (set-marker (mark-marker) (point) (current-buffer)))))
+  ;; If we do get all the way thru, make this-command indicate that.
+  (if (eq this-command t)
+      (setq this-command 'yank))
+  nil)
+
+(defun rotate-yank-pointer (arg)
+  "Rotate the yanking point in the kill ring.
+With ARG, rotate that many kills forward (or backward, if negative)."
+  (interactive "p")
+  (current-kill arg))
+
+;; Some kill commands.
+
+;; Internal subroutine of delete-char
+(defun kill-forward-chars (arg)
+  (if (listp arg) (setq arg (car arg)))
+  (if (eq arg '-) (setq arg -1))
+  (kill-region (point) (+ (point) arg)))
+
+;; Internal subroutine of backward-delete-char
+(defun kill-backward-chars (arg)
+  (if (listp arg) (setq arg (car arg)))
+  (if (eq arg '-) (setq arg -1))
+  (kill-region (point) (- (point) arg)))
+
+(defcustom backward-delete-char-untabify-method 'untabify
+  "The method for untabifying when deleting backward.
+Can be `untabify' -- turn a tab to many spaces, then delete one space;
+       `hungry' -- delete all whitespace, both tabs and spaces;
+       `all' -- delete all whitespace, including tabs, spaces and newlines;
+       nil -- just delete one character."
+  :type '(choice (const untabify) (const hungry) (const all) (const nil))
+  :version "20.3"
+  :group 'killing)
+
+(defun backward-delete-char-untabify (arg &optional killp)
+  "Delete characters backward, changing tabs into spaces.
+The exact behavior depends on `backward-delete-char-untabify-method'.
+Delete ARG chars, and kill (save in kill ring) if KILLP is non-nil.
+Interactively, ARG is the prefix arg (default 1)
+and KILLP is t if a prefix arg was specified."
+  (interactive "*p\nP")
+  (when (eq backward-delete-char-untabify-method 'untabify)
+    (let ((count arg))
+      (save-excursion
+       (while (and (> count 0) (not (bobp)))
+         (if (= (preceding-char) ?\t)
+             (let ((col (current-column)))
+               (forward-char -1)
+               (setq col (- col (current-column)))
+               (insert-char ?\s col)
+               (delete-char 1)))
+         (forward-char -1)
+         (setq count (1- count))))))
+  (let* ((skip (cond ((eq backward-delete-char-untabify-method 'hungry) " \t")
+                     ((eq backward-delete-char-untabify-method 'all)
+                      " \t\n\r")))
+         (n (if skip
+                (let* ((oldpt (point))
+                       (wh (- oldpt (save-excursion
+                                      (skip-chars-backward skip)
+                                      (constrain-to-field nil oldpt)))))
+                  (+ arg (if (zerop wh) 0 (1- wh))))
+              arg)))
+    ;; Avoid warning about delete-backward-char
+    (with-no-warnings (delete-backward-char n killp))))
+
+(defun zap-to-char (arg char)
+  "Kill up to and including ARGth occurrence of CHAR.
+Case is ignored if `case-fold-search' is non-nil in the current buffer.
+Goes backward if ARG is negative; error if CHAR not found."
+  (interactive (list (prefix-numeric-value current-prefix-arg)
+                    (read-char "Zap to char: " t)))
+  ;; Avoid "obsolete" warnings for translation-table-for-input.
+  (with-no-warnings
+    (if (char-table-p translation-table-for-input)
+       (setq char (or (aref translation-table-for-input char) char))))
+  (kill-region (point) (progn
+                        (search-forward (char-to-string char) nil nil arg)
+                        (point))))
+
+;; kill-line and its subroutines.
+
+(defcustom kill-whole-line nil
+  "If non-nil, `kill-line' with no arg at start of line kills the whole line."
+  :type 'boolean
+  :group 'killing)
+
+(defun kill-line (&optional arg)
+  "Kill the rest of the current line; if no nonblanks there, kill thru newline.
+With prefix argument ARG, kill that many lines from point.
+Negative arguments kill lines backward.
+With zero argument, kills the text before point on the current line.
+
+When calling from a program, nil means \"no arg\",
+a number counts as a prefix arg.
+
+To kill a whole line, when point is not at the beginning, type \
+\\[move-beginning-of-line] \\[kill-line] \\[kill-line].
+
+If `show-trailing-whitespace' is non-nil, this command will just
+kill the rest of the current line, even if there are only
+nonblanks there.
+
+If option `kill-whole-line' is non-nil, then this command kills the whole line
+including its terminating newline, when used at the beginning of a line
+with no argument.  As a consequence, you can always kill a whole line
+by typing \\[move-beginning-of-line] \\[kill-line].
+
+If you want to append the killed line to the last killed text,
+use \\[append-next-kill] before \\[kill-line].
+
+If the buffer is read-only, Emacs will beep and refrain from deleting
+the line, but put the line in the kill ring anyway.  This means that
+you can use this command to copy text from a read-only buffer.
+\(If the variable `kill-read-only-ok' is non-nil, then this won't
+even beep.)"
+  (interactive "P")
+  (kill-region (point)
+              ;; It is better to move point to the other end of the kill
+              ;; before killing.  That way, in a read-only buffer, point
+              ;; moves across the text that is copied to the kill ring.
+              ;; The choice has no effect on undo now that undo records
+              ;; the value of point from before the command was run.
+              (progn
+                (if arg
+                    (forward-visible-line (prefix-numeric-value arg))
+                  (if (eobp)
+                      (signal 'end-of-buffer nil))
+                  (let ((end
+                         (save-excursion
+                           (end-of-visible-line) (point))))
+                    (if (or (save-excursion
+                              ;; If trailing whitespace is visible,
+                              ;; don't treat it as nothing.
+                              (unless show-trailing-whitespace
+                                (skip-chars-forward " \t" end))
+                              (= (point) end))
+                            (and kill-whole-line (bolp)))
+                        (forward-visible-line 1)
+                      (goto-char end))))
+                (point))))
+
+(defun kill-whole-line (&optional arg)
+  "Kill current line.
+With prefix ARG, kill that many lines starting from the current line.
+If ARG is negative, kill backward.  Also kill the preceding newline.
+\(This is meant to make \\[repeat] work well with negative arguments.)
+If ARG is zero, kill current line but exclude the trailing newline."
+  (interactive "p")
+  (or arg (setq arg 1))
+  (if (and (> arg 0) (eobp) (save-excursion (forward-visible-line 0) (eobp)))
+      (signal 'end-of-buffer nil))
+  (if (and (< arg 0) (bobp) (save-excursion (end-of-visible-line) (bobp)))
+      (signal 'beginning-of-buffer nil))
+  (unless (eq last-command 'kill-region)
+    (kill-new "")
+    (setq last-command 'kill-region))
+  (cond ((zerop arg)
+        ;; We need to kill in two steps, because the previous command
+        ;; could have been a kill command, in which case the text
+        ;; before point needs to be prepended to the current kill
+        ;; ring entry and the text after point appended.  Also, we
+        ;; need to use save-excursion to avoid copying the same text
+        ;; twice to the kill ring in read-only buffers.
+        (save-excursion
+          (kill-region (point) (progn (forward-visible-line 0) (point))))
+        (kill-region (point) (progn (end-of-visible-line) (point))))
+       ((< arg 0)
+        (save-excursion
+          (kill-region (point) (progn (end-of-visible-line) (point))))
+        (kill-region (point)
+                     (progn (forward-visible-line (1+ arg))
+                            (unless (bobp) (backward-char))
+                            (point))))
+       (t
+        (save-excursion
+          (kill-region (point) (progn (forward-visible-line 0) (point))))
+        (kill-region (point)
+                     (progn (forward-visible-line arg) (point))))))
+
+(defun forward-visible-line (arg)
+  "Move forward by ARG lines, ignoring currently invisible newlines only.
+If ARG is negative, move backward -ARG lines.
+If ARG is zero, move to the beginning of the current line."
+  (condition-case nil
+      (if (> arg 0)
+         (progn
+           (while (> arg 0)
+             (or (zerop (forward-line 1))
+                 (signal 'end-of-buffer nil))
+             ;; If the newline we just skipped is invisible,
+             ;; don't count it.
+             (let ((prop
+                    (get-char-property (1- (point)) 'invisible)))
+               (if (if (eq buffer-invisibility-spec t)
+                       prop
+                     (or (memq prop buffer-invisibility-spec)
+                         (assq prop buffer-invisibility-spec)))
+                   (setq arg (1+ arg))))
+             (setq arg (1- arg)))
+           ;; If invisible text follows, and it is a number of complete lines,
+           ;; skip it.
+           (let ((opoint (point)))
+             (while (and (not (eobp))
+                         (let ((prop
+                                (get-char-property (point) 'invisible)))
+                           (if (eq buffer-invisibility-spec t)
+                               prop
+                             (or (memq prop buffer-invisibility-spec)
+                                 (assq prop buffer-invisibility-spec)))))
+               (goto-char
+                (if (get-text-property (point) 'invisible)
+                    (or (next-single-property-change (point) 'invisible)
+                        (point-max))
+                  (next-overlay-change (point)))))
+             (unless (bolp)
+               (goto-char opoint))))
+       (let ((first t))
+         (while (or first (<= arg 0))
+           (if first
+               (beginning-of-line)
+             (or (zerop (forward-line -1))
+                 (signal 'beginning-of-buffer nil)))
+           ;; If the newline we just moved to is invisible,
+           ;; don't count it.
+           (unless (bobp)
+             (let ((prop
+                    (get-char-property (1- (point)) 'invisible)))
+               (unless (if (eq buffer-invisibility-spec t)
+                           prop
+                         (or (memq prop buffer-invisibility-spec)
+                             (assq prop buffer-invisibility-spec)))
+                 (setq arg (1+ arg)))))
+           (setq first nil))
+         ;; If invisible text follows, and it is a number of complete lines,
+         ;; skip it.
+         (let ((opoint (point)))
+           (while (and (not (bobp))
+                       (let ((prop
+                              (get-char-property (1- (point)) 'invisible)))
+                         (if (eq buffer-invisibility-spec t)
+                             prop
+                           (or (memq prop buffer-invisibility-spec)
+                               (assq prop buffer-invisibility-spec)))))
+             (goto-char
+              (if (get-text-property (1- (point)) 'invisible)
+                  (or (previous-single-property-change (point) 'invisible)
+                      (point-min))
+                (previous-overlay-change (point)))))
+           (unless (bolp)
+             (goto-char opoint)))))
+    ((beginning-of-buffer end-of-buffer)
+     nil)))
+
+(defun end-of-visible-line ()
+  "Move to end of current visible line."
+  (end-of-line)
+  ;; If the following character is currently invisible,
+  ;; skip all characters with that same `invisible' property value,
+  ;; then find the next newline.
+  (while (and (not (eobp))
+             (save-excursion
+               (skip-chars-forward "^\n")
+               (let ((prop
+                      (get-char-property (point) 'invisible)))
+                 (if (eq buffer-invisibility-spec t)
+                     prop
+                   (or (memq prop buffer-invisibility-spec)
+                       (assq prop buffer-invisibility-spec))))))
+    (skip-chars-forward "^\n")
+    (if (get-text-property (point) 'invisible)
+       (goto-char (or (next-single-property-change (point) 'invisible)
+                      (point-max)))
+      (goto-char (next-overlay-change (point))))
+    (end-of-line)))
+
+(defun insert-buffer (buffer)
+  "Insert after point the contents of BUFFER.
+Puts mark after the inserted text.
+BUFFER may be a buffer or a buffer name.
+
+This function is meant for the user to run interactively.
+Don't call it from programs: use `insert-buffer-substring' instead!"
+  (interactive
+   (list
+    (progn
+      (barf-if-buffer-read-only)
+      (read-buffer "Insert buffer: "
+                  (if (eq (selected-window) (next-window))
+                      (other-buffer (current-buffer))
+                    (window-buffer (next-window)))
+                  t))))
+  (push-mark
+   (save-excursion
+     (insert-buffer-substring (get-buffer buffer))
+     (point)))
+  nil)
+(put 'insert-buffer 'interactive-only 'insert-buffer-substring)
+
+(defun append-to-buffer (buffer start end)
+  "Append to specified buffer the text of the region.
+It is inserted into that buffer before its point.
+
+When calling from a program, give three arguments:
+BUFFER (or buffer name), START and END.
+START and END specify the portion of the current buffer to be copied."
+  (interactive
+   (list (read-buffer "Append to buffer: " (other-buffer (current-buffer) t))
+        (region-beginning) (region-end)))
+  (let* ((oldbuf (current-buffer))
+         (append-to (get-buffer-create buffer))
+         (windows (get-buffer-window-list append-to t t))
+         point)
+    (save-excursion
+      (with-current-buffer append-to
+        (setq point (point))
+        (barf-if-buffer-read-only)
+        (insert-buffer-substring oldbuf start end)
+        (dolist (window windows)
+          (when (= (window-point window) point)
+            (set-window-point window (point))))))))
+
+(defun prepend-to-buffer (buffer start end)
+  "Prepend to specified buffer the text of the region.
+It is inserted into that buffer after its point.
+
+When calling from a program, give three arguments:
+BUFFER (or buffer name), START and END.
+START and END specify the portion of the current buffer to be copied."
+  (interactive "BPrepend to buffer: \nr")
+  (let ((oldbuf (current-buffer)))
+    (with-current-buffer (get-buffer-create buffer)
+      (barf-if-buffer-read-only)
+      (save-excursion
+       (insert-buffer-substring oldbuf start end)))))
+
+(defun copy-to-buffer (buffer start end)
+  "Copy to specified buffer the text of the region.
+It is inserted into that buffer, replacing existing text there.
+
+When calling from a program, give three arguments:
+BUFFER (or buffer name), START and END.
+START and END specify the portion of the current buffer to be copied."
+  (interactive "BCopy to buffer: \nr")
+  (let ((oldbuf (current-buffer)))
+    (with-current-buffer (get-buffer-create buffer)
+      (barf-if-buffer-read-only)
+      (erase-buffer)
+      (save-excursion
+       (insert-buffer-substring oldbuf start end)))))
+
+(define-error 'mark-inactive (purecopy "The mark is not active now"))
+
+(defvar activate-mark-hook nil
+  "Hook run when the mark becomes active.
+It is also run at the end of a command, if the mark is active and
+it is possible that the region may have changed.")
+
+(defvar deactivate-mark-hook nil
+  "Hook run when the mark becomes inactive.")
+
+(defun mark (&optional force)
+  "Return this buffer's mark value as integer, or nil if never set.
+
+In Transient Mark mode, this function signals an error if
+the mark is not active.  However, if `mark-even-if-inactive' is non-nil,
+or the argument FORCE is non-nil, it disregards whether the mark
+is active, and returns an integer or nil in the usual way.
+
+If you are using this in an editing command, you are most likely making
+a mistake; see the documentation of `set-mark'."
+  (if (or force (not transient-mark-mode) mark-active mark-even-if-inactive)
+      (marker-position (mark-marker))
+    (signal 'mark-inactive nil)))
+
+;; Behind display-selections-p.
+(declare-function x-selection-owner-p "xselect.c"
+                  (&optional selection terminal))
+(declare-function x-selection-exists-p "xselect.c"
+                  (&optional selection terminal))
+
+(defun deactivate-mark (&optional force)
+  "Deactivate the mark.
+If Transient Mark mode is disabled, this function normally does
+nothing; but if FORCE is non-nil, it deactivates the mark anyway.
+
+Deactivating the mark sets `mark-active' to nil, updates the
+primary selection according to `select-active-regions', and runs
+`deactivate-mark-hook'.
+
+If Transient Mark mode was temporarily enabled, reset the value
+of the variable `transient-mark-mode'; if this causes Transient
+Mark mode to be disabled, don't change `mark-active' to nil or
+run `deactivate-mark-hook'."
+  (when (or transient-mark-mode force)
+    (when (and (if (eq select-active-regions 'only)
+                  (eq (car-safe transient-mark-mode) 'only)
+                select-active-regions)
+              (region-active-p)
+              (display-selections-p))
+      ;; The var `saved-region-selection', if non-nil, is the text in
+      ;; the region prior to the last command modifying the buffer.
+      ;; Set the selection to that, or to the current region.
+      (cond (saved-region-selection
+            (if (x-selection-owner-p 'PRIMARY)
+                (x-set-selection 'PRIMARY saved-region-selection))
+            (setq saved-region-selection nil))
+           ;; If another program has acquired the selection, region
+           ;; deactivation should not clobber it (Bug#11772).
+           ((and (/= (region-beginning) (region-end))
+                 (or (x-selection-owner-p 'PRIMARY)
+                     (null (x-selection-exists-p 'PRIMARY))))
+            (x-set-selection 'PRIMARY
+                              (funcall region-extract-function nil)))))
+    (when mark-active (force-mode-line-update)) ;Refresh toolbar (bug#16382).
+    (cond
+     ((eq (car-safe transient-mark-mode) 'only)
+      (setq transient-mark-mode (cdr transient-mark-mode)))
+     ((eq transient-mark-mode 'lambda)
+      (setq transient-mark-mode nil)))
+    (setq mark-active nil)
+    (run-hooks 'deactivate-mark-hook)
+    (redisplay--update-region-highlight (selected-window))))
+
+(defun activate-mark (&optional no-tmm)
+  "Activate the mark.
+If NO-TMM is non-nil, leave `transient-mark-mode' alone."
+  (when (mark t)
+    (unless (region-active-p)
+      (force-mode-line-update) ;Refresh toolbar (bug#16382).
+      (setq mark-active t)
+      (unless (or transient-mark-mode no-tmm)
+        (setq transient-mark-mode 'lambda))
+      (run-hooks 'activate-mark-hook))))
+
+(defun set-mark (pos)
+  "Set this buffer's mark to POS.  Don't use this function!
+That is to say, don't use this function unless you want
+the user to see that the mark has moved, and you want the previous
+mark position to be lost.
+
+Normally, when a new mark is set, the old one should go on the stack.
+This is why most applications should use `push-mark', not `set-mark'.
+
+Novice Emacs Lisp programmers often try to use the mark for the wrong
+purposes.  The mark saves a location for the user's convenience.
+Most editing commands should not alter the mark.
+To remember a location for internal use in the Lisp program,
+store it in a Lisp variable.  Example:
+
+   (let ((beg (point))) (forward-line 1) (delete-region beg (point)))."
+  (if pos
+      (progn
+        (set-marker (mark-marker) pos (current-buffer))
+        (activate-mark 'no-tmm))
+    ;; Normally we never clear mark-active except in Transient Mark mode.
+    ;; But when we actually clear out the mark value too, we must
+    ;; clear mark-active in any mode.
+    (deactivate-mark t)
+    ;; `deactivate-mark' sometimes leaves mark-active non-nil, but
+    ;; it should never be nil if the mark is nil.
+    (setq mark-active nil)
+    (set-marker (mark-marker) nil)))
+
+(defcustom use-empty-active-region nil
+  "Whether \"region-aware\" commands should act on empty regions.
+If nil, region-aware commands treat empty regions as inactive.
+If non-nil, region-aware commands treat the region as active as
+long as the mark is active, even if the region is empty.
+
+Region-aware commands are those that act on the region if it is
+active and Transient Mark mode is enabled, and on the text near
+point otherwise."
+  :type 'boolean
+  :version "23.1"
+  :group 'editing-basics)
+
+(defun use-region-p ()
+  "Return t if the region is active and it is appropriate to act on it.
+This is used by commands that act specially on the region under
+Transient Mark mode.
+
+The return value is t if Transient Mark mode is enabled and the
+mark is active; furthermore, if `use-empty-active-region' is nil,
+the region must not be empty.  Otherwise, the return value is nil.
+
+For some commands, it may be appropriate to ignore the value of
+`use-empty-active-region'; in that case, use `region-active-p'."
+  (and (region-active-p)
+       (or use-empty-active-region (> (region-end) (region-beginning)))))
+
+(defun region-active-p ()
+  "Return t if Transient Mark mode is enabled and the mark is active.
+
+Some commands act specially on the region when Transient Mark
+mode is enabled.  Usually, such commands should use
+`use-region-p' instead of this function, because `use-region-p'
+also checks the value of `use-empty-active-region'."
+  (and transient-mark-mode mark-active
+       ;; FIXME: Somehow we sometimes end up with mark-active non-nil but
+       ;; without the mark being set (e.g. bug#17324).  We really should fix
+       ;; that problem, but in the mean time, let's make sure we don't say the
+       ;; region is active when there's no mark.
+       (mark)))
+
+
+(defvar redisplay-unhighlight-region-function
+  (lambda (rol) (when (overlayp rol) (delete-overlay rol))))
+
+(defvar redisplay-highlight-region-function
+  (lambda (start end window rol)
+    (if (not (overlayp rol))
+        (let ((nrol (make-overlay start end)))
+          (funcall redisplay-unhighlight-region-function rol)
+          (overlay-put nrol 'window window)
+          (overlay-put nrol 'face 'region)
+          ;; Normal priority so that a large region doesn't hide all the
+          ;; overlays within it, but high secondary priority so that if it
+          ;; ends/starts in the middle of a small overlay, that small overlay
+          ;; won't hide the region's boundaries.
+          (overlay-put nrol 'priority '(nil . 100))
+          nrol)
+      (unless (and (eq (overlay-buffer rol) (current-buffer))
+                   (eq (overlay-start rol) start)
+                   (eq (overlay-end rol) end))
+        (move-overlay rol start end (current-buffer)))
+      rol)))
+
+(defun redisplay--update-region-highlight (window)
+  (with-current-buffer (window-buffer window)
+    (let ((rol (window-parameter window 'internal-region-overlay)))
+      (if (not (region-active-p))
+          (funcall redisplay-unhighlight-region-function rol)
+        (let* ((pt (window-point window))
+               (mark (mark))
+               (start (min pt mark))
+               (end   (max pt mark))
+               (new
+                (funcall redisplay-highlight-region-function
+                         start end window rol)))
+          (unless (equal new rol)
+            (set-window-parameter window 'internal-region-overlay
+                                  new)))))))
+
+(defun redisplay--update-region-highlights (windows)
+  (with-demoted-errors "redisplay--update-region-highlights: %S"
+    (if (null windows)
+        (redisplay--update-region-highlight (selected-window))
+      (unless (listp windows) (setq windows (window-list-1 nil nil t)))
+      (if highlight-nonselected-windows
+          (mapc #'redisplay--update-region-highlight windows)
+        (let ((msw (and (window-minibuffer-p) (minibuffer-selected-window))))
+          (dolist (w windows)
+            (if (or (eq w (selected-window)) (eq w msw))
+                (redisplay--update-region-highlight w)
+              (funcall redisplay-unhighlight-region-function
+                       (window-parameter w 'internal-region-overlay)))))))))
+
+(add-function :before pre-redisplay-function
+              #'redisplay--update-region-highlights)
+
+
+(defvar-local mark-ring nil
+  "The list of former marks of the current buffer, most recent first.")
+(put 'mark-ring 'permanent-local t)
+
+(defcustom mark-ring-max 16
+  "Maximum size of mark ring.  Start discarding off end if gets this big."
+  :type 'integer
+  :group 'editing-basics)
+
+(defvar global-mark-ring nil
+  "The list of saved global marks, most recent first.")
+
+(defcustom global-mark-ring-max 16
+  "Maximum size of global mark ring.  \
+Start discarding off end if gets this big."
+  :type 'integer
+  :group 'editing-basics)
+
+(defun pop-to-mark-command ()
+  "Jump to mark, and pop a new position for mark off the ring.
+\(Does not affect global mark ring)."
+  (interactive)
+  (if (null (mark t))
+      (error "No mark set in this buffer")
+    (if (= (point) (mark t))
+       (message "Mark popped"))
+    (goto-char (mark t))
+    (pop-mark)))
+
+(defun push-mark-command (arg &optional nomsg)
+  "Set mark at where point is.
+If no prefix ARG and mark is already set there, just activate it.
+Display `Mark set' unless the optional second arg NOMSG is non-nil."
+  (interactive "P")
+  (let ((mark (mark t)))
+    (if (or arg (null mark) (/= mark (point)))
+       (push-mark nil nomsg t)
+      (activate-mark 'no-tmm)
+      (unless nomsg
+       (message "Mark activated")))))
+
+(defcustom set-mark-command-repeat-pop nil
+  "Non-nil means repeating \\[set-mark-command] after popping mark pops it 
again.
+That means that C-u \\[set-mark-command] \\[set-mark-command]
+will pop the mark twice, and
+C-u \\[set-mark-command] \\[set-mark-command] \\[set-mark-command]
+will pop the mark three times.
+
+A value of nil means \\[set-mark-command]'s behavior does not change
+after C-u \\[set-mark-command]."
+  :type 'boolean
+  :group 'editing-basics)
+
+(defun set-mark-command (arg)
+  "Set the mark where point is, or jump to the mark.
+Setting the mark also alters the region, which is the text
+between point and mark; this is the closest equivalent in
+Emacs to what some editors call the \"selection\".
+
+With no prefix argument, set the mark at point, and push the
+old mark position on local mark ring.  Also push the old mark on
+global mark ring, if the previous mark was set in another buffer.
+
+When Transient Mark Mode is off, immediately repeating this
+command activates `transient-mark-mode' temporarily.
+
+With prefix argument (e.g., \\[universal-argument] \\[set-mark-command]), \
+jump to the mark, and set the mark from
+position popped off the local mark ring (this does not affect the global
+mark ring).  Use \\[pop-global-mark] to jump to a mark popped off the global
+mark ring (see `pop-global-mark').
+
+If `set-mark-command-repeat-pop' is non-nil, repeating
+the \\[set-mark-command] command with no prefix argument pops the next position
+off the local (or global) mark ring and jumps there.
+
+With \\[universal-argument] \\[universal-argument] as prefix
+argument, unconditionally set mark where point is, even if
+`set-mark-command-repeat-pop' is non-nil.
+
+Novice Emacs Lisp programmers often try to use the mark for the wrong
+purposes.  See the documentation of `set-mark' for more information."
+  (interactive "P")
+  (cond ((eq transient-mark-mode 'lambda)
+        (setq transient-mark-mode nil))
+       ((eq (car-safe transient-mark-mode) 'only)
+        (deactivate-mark)))
+  (cond
+   ((and (consp arg) (> (prefix-numeric-value arg) 4))
+    (push-mark-command nil))
+   ((not (eq this-command 'set-mark-command))
+    (if arg
+       (pop-to-mark-command)
+      (push-mark-command t)))
+   ((and set-mark-command-repeat-pop
+        (eq last-command 'pop-to-mark-command))
+    (setq this-command 'pop-to-mark-command)
+    (pop-to-mark-command))
+   ((and set-mark-command-repeat-pop
+        (eq last-command 'pop-global-mark)
+        (not arg))
+    (setq this-command 'pop-global-mark)
+    (pop-global-mark))
+   (arg
+    (setq this-command 'pop-to-mark-command)
+    (pop-to-mark-command))
+   ((eq last-command 'set-mark-command)
+    (if (region-active-p)
+        (progn
+          (deactivate-mark)
+          (message "Mark deactivated"))
+      (activate-mark)
+      (message "Mark activated")))
+   (t
+    (push-mark-command nil))))
+
+(defun push-mark (&optional location nomsg activate)
+  "Set mark at LOCATION (point, by default) and push old mark on mark ring.
+If the last global mark pushed was not in the current buffer,
+also push LOCATION on the global mark ring.
+Display `Mark set' unless the optional second arg NOMSG is non-nil.
+
+Novice Emacs Lisp programmers often try to use the mark for the wrong
+purposes.  See the documentation of `set-mark' for more information.
+
+In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil."
+  (unless (null (mark t))
+    (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
+    (when (> (length mark-ring) mark-ring-max)
+      (move-marker (car (nthcdr mark-ring-max mark-ring)) nil)
+      (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil)))
+  (set-marker (mark-marker) (or location (point)) (current-buffer))
+  ;; Now push the mark on the global mark ring.
+  (if (and global-mark-ring
+          (eq (marker-buffer (car global-mark-ring)) (current-buffer)))
+      ;; The last global mark pushed was in this same buffer.
+      ;; Don't push another one.
+      nil
+    (setq global-mark-ring (cons (copy-marker (mark-marker)) global-mark-ring))
+    (when (> (length global-mark-ring) global-mark-ring-max)
+      (move-marker (car (nthcdr global-mark-ring-max global-mark-ring)) nil)
+      (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil)))
+  (or nomsg executing-kbd-macro (> (minibuffer-depth) 0)
+      (message "Mark set"))
+  (if (or activate (not transient-mark-mode))
+      (set-mark (mark t)))
+  nil)
+
+(defun pop-mark ()
+  "Pop off mark ring into the buffer's actual mark.
+Does not set point.  Does nothing if mark ring is empty."
+  (when mark-ring
+    (setq mark-ring (nconc mark-ring (list (copy-marker (mark-marker)))))
+    (set-marker (mark-marker) (+ 0 (car mark-ring)) (current-buffer))
+    (move-marker (car mark-ring) nil)
+    (if (null (mark t)) (ding))
+    (setq mark-ring (cdr mark-ring)))
+  (deactivate-mark))
+
+(define-obsolete-function-alias
+  'exchange-dot-and-mark 'exchange-point-and-mark "23.3")
+(defun exchange-point-and-mark (&optional arg)
+  "Put the mark where point is now, and point where the mark is now.
+This command works even when the mark is not active,
+and it reactivates the mark.
+
+If Transient Mark mode is on, a prefix ARG deactivates the mark
+if it is active, and otherwise avoids reactivating it.  If
+Transient Mark mode is off, a prefix ARG enables Transient Mark
+mode temporarily."
+  (interactive "P")
+  (let ((omark (mark t))
+       (temp-highlight (eq (car-safe transient-mark-mode) 'only)))
+    (if (null omark)
+        (error "No mark set in this buffer"))
+    (set-mark (point))
+    (goto-char omark)
+    (cond (temp-highlight
+          (setq transient-mark-mode (cons 'only transient-mark-mode)))
+         ((or (and arg (region-active-p)) ; (xor arg (not (region-active-p)))
+              (not (or arg (region-active-p))))
+          (deactivate-mark))
+         (t (activate-mark)))
+    nil))
+
+(defcustom shift-select-mode t
+  "When non-nil, shifted motion keys activate the mark momentarily.
+
+While the mark is activated in this way, any shift-translated point
+motion key extends the region, and if Transient Mark mode was off, it
+is temporarily turned on.  Furthermore, the mark will be deactivated
+by any subsequent point motion key that was not shift-translated, or
+by any action that normally deactivates the mark in Transient Mark mode.
+
+See `this-command-keys-shift-translated' for the meaning of
+shift-translation."
+  :type 'boolean
+  :group 'editing-basics)
+
+(defun handle-shift-selection ()
+  "Activate/deactivate mark depending on invocation thru shift translation.
+This function is called by `call-interactively' when a command
+with a `^' character in its `interactive' spec is invoked, before
+running the command itself.
+
+If `shift-select-mode' is enabled and the command was invoked
+through shift translation, set the mark and activate the region
+temporarily, unless it was already set in this way.  See
+`this-command-keys-shift-translated' for the meaning of shift
+translation.
+
+Otherwise, if the region has been activated temporarily,
+deactivate it, and restore the variable `transient-mark-mode' to
+its earlier value."
+  (cond ((and shift-select-mode this-command-keys-shift-translated)
+         (unless (and mark-active
+                     (eq (car-safe transient-mark-mode) 'only))
+          (setq transient-mark-mode
+                 (cons 'only
+                       (unless (eq transient-mark-mode 'lambda)
+                         transient-mark-mode)))
+           (push-mark nil nil t)))
+        ((eq (car-safe transient-mark-mode) 'only)
+         (setq transient-mark-mode (cdr transient-mark-mode))
+         (deactivate-mark))))
+
+(define-minor-mode transient-mark-mode
+  "Toggle Transient Mark mode.
+With a prefix argument ARG, enable Transient Mark mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+Transient Mark mode if ARG is omitted or nil.
+
+Transient Mark mode is a global minor mode.  When enabled, the
+region is highlighted with the `region' face whenever the mark
+is active.  The mark is \"deactivated\" by changing the buffer,
+and after certain other operations that set the mark but whose
+main purpose is something else--for example, incremental search,
+\\[beginning-of-buffer], and \\[end-of-buffer].
+
+You can also deactivate the mark by typing \\[keyboard-quit] or
+\\[keyboard-escape-quit].
+
+Many commands change their behavior when Transient Mark mode is
+in effect and the mark is active, by acting on the region instead
+of their usual default part of the buffer's text.  Examples of
+such commands include \\[comment-dwim], \\[flush-lines], \\[keep-lines],
+\\[query-replace], \\[query-replace-regexp], \\[ispell], and \\[undo].
+To see the documentation of commands which are sensitive to the
+Transient Mark mode, invoke \\[apropos-documentation] and type \"transient\"
+or \"mark.*active\" at the prompt."
+  :global t
+  ;; It's defined in C/cus-start, this stops the d-m-m macro defining it again.
+  :variable transient-mark-mode)
+
+(defvar widen-automatically t
+  "Non-nil means it is ok for commands to call `widen' when they want to.
+Some commands will do this in order to go to positions outside
+the current accessible part of the buffer.
+
+If `widen-automatically' is nil, these commands will do something else
+as a fallback, and won't change the buffer bounds.")
+
+(defvar non-essential nil
+  "Whether the currently executing code is performing an essential task.
+This variable should be non-nil only when running code which should not
+disturb the user.  E.g. it can be used to prevent Tramp from prompting the
+user for a password when we are simply scanning a set of files in the
+background or displaying possible completions before the user even asked
+for it.")
+
+(defun pop-global-mark ()
+  "Pop off global mark ring and jump to the top location."
+  (interactive)
+  ;; Pop entries which refer to non-existent buffers.
+  (while (and global-mark-ring (not (marker-buffer (car global-mark-ring))))
+    (setq global-mark-ring (cdr global-mark-ring)))
+  (or global-mark-ring
+      (error "No global mark set"))
+  (let* ((marker (car global-mark-ring))
+        (buffer (marker-buffer marker))
+        (position (marker-position marker)))
+    (setq global-mark-ring (nconc (cdr global-mark-ring)
+                                 (list (car global-mark-ring))))
+    (set-buffer buffer)
+    (or (and (>= position (point-min))
+            (<= position (point-max)))
+       (if widen-automatically
+           (widen)
+         (error "Global mark position is outside accessible part of buffer")))
+    (goto-char position)
+    (switch-to-buffer buffer)))
+
+(defcustom next-line-add-newlines nil
+  "If non-nil, `next-line' inserts newline to avoid `end of buffer' error."
+  :type 'boolean
+  :version "21.1"
+  :group 'editing-basics)
+
+(defun next-line (&optional arg try-vscroll)
+  "Move cursor vertically down ARG lines.
+Interactively, vscroll tall lines if `auto-window-vscroll' is enabled.
+Non-interactively, use TRY-VSCROLL to control whether to vscroll tall
+lines: if either `auto-window-vscroll' or TRY-VSCROLL is nil, this
+function will not vscroll.
+
+ARG defaults to 1.
+
+If there is no character in the target line exactly under the current column,
+the cursor is positioned after the character in that line which spans this
+column, or at the end of the line if it is not long enough.
+If there is no line in the buffer after this one, behavior depends on the
+value of `next-line-add-newlines'.  If non-nil, it inserts a newline character
+to create a line, and moves the cursor to that line.  Otherwise it moves the
+cursor to the end of the buffer.
+
+If the variable `line-move-visual' is non-nil, this command moves
+by display lines.  Otherwise, it moves by buffer lines, without
+taking variable-width characters or continued lines into account.
+
+The command \\[set-goal-column] can be used to create
+a semipermanent goal column for this command.
+Then instead of trying to move exactly vertically (or as close as possible),
+this command moves to the specified goal column (or as close as possible).
+The goal column is stored in the variable `goal-column', which is nil
+when there is no goal column.  Note that setting `goal-column'
+overrides `line-move-visual' and causes this command to move by buffer
+lines rather than by display lines.
+
+If you are thinking of using this in a Lisp program, consider
+using `forward-line' instead.  It is usually easier to use
+and more reliable (no dependence on goal column, etc.)."
+  (interactive "^p\np")
+  (or arg (setq arg 1))
+  (if (and next-line-add-newlines (= arg 1))
+      (if (save-excursion (end-of-line) (eobp))
+         ;; When adding a newline, don't expand an abbrev.
+         (let ((abbrev-mode nil))
+           (end-of-line)
+           (insert (if use-hard-newlines hard-newline "\n")))
+       (line-move arg nil nil try-vscroll))
+    (if (called-interactively-p 'interactive)
+       (condition-case err
+           (line-move arg nil nil try-vscroll)
+         ((beginning-of-buffer end-of-buffer)
+          (signal (car err) (cdr err))))
+      (line-move arg nil nil try-vscroll)))
+  nil)
+(put 'next-line 'interactive-only 'forward-line)
+
+(defun previous-line (&optional arg try-vscroll)
+  "Move cursor vertically up ARG lines.
+Interactively, vscroll tall lines if `auto-window-vscroll' is enabled.
+Non-interactively, use TRY-VSCROLL to control whether to vscroll tall
+lines: if either `auto-window-vscroll' or TRY-VSCROLL is nil, this
+function will not vscroll.
+
+ARG defaults to 1.
+
+If there is no character in the target line exactly over the current column,
+the cursor is positioned after the character in that line which spans this
+column, or at the end of the line if it is not long enough.
+
+If the variable `line-move-visual' is non-nil, this command moves
+by display lines.  Otherwise, it moves by buffer lines, without
+taking variable-width characters or continued lines into account.
+
+The command \\[set-goal-column] can be used to create
+a semipermanent goal column for this command.
+Then instead of trying to move exactly vertically (or as close as possible),
+this command moves to the specified goal column (or as close as possible).
+The goal column is stored in the variable `goal-column', which is nil
+when there is no goal column.  Note that setting `goal-column'
+overrides `line-move-visual' and causes this command to move by buffer
+lines rather than by display lines.
+
+If you are thinking of using this in a Lisp program, consider using
+`forward-line' with a negative argument instead.  It is usually easier
+to use and more reliable (no dependence on goal column, etc.)."
+  (interactive "^p\np")
+  (or arg (setq arg 1))
+  (if (called-interactively-p 'interactive)
+      (condition-case err
+         (line-move (- arg) nil nil try-vscroll)
+       ((beginning-of-buffer end-of-buffer)
+        (signal (car err) (cdr err))))
+    (line-move (- arg) nil nil try-vscroll))
+  nil)
+(put 'previous-line 'interactive-only
+     "use `forward-line' with negative argument instead.")
+
+(defcustom track-eol nil
+  "Non-nil means vertical motion starting at end of line keeps to ends of 
lines.
+This means moving to the end of each line moved onto.
+The beginning of a blank line does not count as the end of a line.
+This has no effect when the variable `line-move-visual' is non-nil."
+  :type 'boolean
+  :group 'editing-basics)
+
+(defcustom goal-column nil
+  "Semipermanent goal column for vertical motion, as set by 
\\[set-goal-column], or nil.
+A non-nil setting overrides the variable `line-move-visual', which see."
+  :type '(choice integer
+                (const :tag "None" nil))
+  :group 'editing-basics)
+(make-variable-buffer-local 'goal-column)
+
+(defvar temporary-goal-column 0
+  "Current goal column for vertical motion.
+It is the column where point was at the start of the current run
+of vertical motion commands.
+
+When moving by visual lines via the function `line-move-visual', it is a cons
+cell (COL . HSCROLL), where COL is the x-position, in pixels,
+divided by the default column width, and HSCROLL is the number of
+columns by which window is scrolled from left margin.
+
+When the `track-eol' feature is doing its job, the value is
+`most-positive-fixnum'.")
+
+(defcustom line-move-ignore-invisible t
+  "Non-nil means commands that move by lines ignore invisible newlines.
+When this option is non-nil, \\[next-line], \\[previous-line], 
\\[move-end-of-line], and \\[move-beginning-of-line] behave
+as if newlines that are invisible didn't exist, and count
+only visible newlines.  Thus, moving across across 2 newlines
+one of which is invisible will be counted as a one-line move.
+Also, a non-nil value causes invisible text to be ignored when
+counting columns for the purposes of keeping point in the same
+column by \\[next-line] and \\[previous-line].
+
+Outline mode sets this."
+  :type 'boolean
+  :group 'editing-basics)
+
+(defcustom line-move-visual t
+  "When non-nil, `line-move' moves point by visual lines.
+This movement is based on where the cursor is displayed on the
+screen, instead of relying on buffer contents alone.  It takes
+into account variable-width characters and line continuation.
+If nil, `line-move' moves point by logical lines.
+A non-nil setting of `goal-column' overrides the value of this variable
+and forces movement by logical lines.
+A window that is  horizontally scrolled also forces movement by logical
+lines."
+  :type 'boolean
+  :group 'editing-basics
+  :version "23.1")
+
+;; Only used if display-graphic-p.
+(declare-function font-info "font.c" (name &optional frame))
+
+(defun default-font-height ()
+  "Return the height in pixels of the current buffer's default face font."
+  (let ((default-font (face-font 'default)))
+    (cond
+     ((and (display-multi-font-p)
+          ;; Avoid calling font-info if the frame's default font was
+          ;; not changed since the frame was created.  That's because
+          ;; font-info is expensive for some fonts, see bug #14838.
+          (not (string= (frame-parameter nil 'font) default-font)))
+      (aref (font-info default-font) 3))
+     (t (frame-char-height)))))
+
+(defun default-line-height ()
+  "Return the pixel height of current buffer's default-face text line.
+
+The value includes `line-spacing', if any, defined for the buffer
+or the frame."
+  (let ((dfh (default-font-height))
+       (lsp (if (display-graphic-p)
+                (or line-spacing
+                    (default-value 'line-spacing)
+                    (frame-parameter nil 'line-spacing)
+                    0)
+              0)))
+    (if (floatp lsp)
+       (setq lsp (truncate (* (frame-char-height) lsp))))
+    (+ dfh lsp)))
+
+(defun window-screen-lines ()
+  "Return the number of screen lines in the text area of the selected window.
+
+This is different from `window-text-height' in that this function counts
+lines in units of the height of the font used by the default face displayed
+in the window, not in units of the frame's default font, and also accounts
+for `line-spacing', if any, defined for the window's buffer or frame.
+
+The value is a floating-point number."
+  (let ((edges (window-inside-pixel-edges))
+       (dlh (default-line-height)))
+    (/ (float (- (nth 3 edges) (nth 1 edges))) dlh)))
+
+;; Returns non-nil if partial move was done.
+(defun line-move-partial (arg noerror to-end)
+  (if (< arg 0)
+      ;; Move backward (up).
+      ;; If already vscrolled, reduce vscroll
+      (let ((vs (window-vscroll nil t))
+           (dlh (default-line-height)))
+       (when (> vs dlh)
+         (set-window-vscroll nil (- vs dlh) t)))
+
+    ;; Move forward (down).
+    (let* ((lh (window-line-height -1))
+          (rowh (car lh))
+          (vpos (nth 1 lh))
+          (ypos (nth 2 lh))
+          (rbot (nth 3 lh))
+          (this-lh (window-line-height))
+          (this-height (car this-lh))
+          (this-ypos (nth 2 this-lh))
+          (dlh (default-line-height))
+          (wslines (window-screen-lines))
+          (edges (window-inside-pixel-edges))
+          (winh (- (nth 3 edges) (nth 1 edges) 1))
+          py vs last-line)
+      (if (> (mod wslines 1.0) 0.0)
+         (setq wslines (round (+ wslines 0.5))))
+      (when (or (null lh)
+               (>= rbot dlh)
+               (<= ypos (- dlh))
+               (null this-lh)
+               (<= this-ypos (- dlh)))
+       (unless lh
+         (let ((wend (pos-visible-in-window-p t nil t)))
+           (setq rbot (nth 3 wend)
+                 rowh  (nth 4 wend)
+                 vpos (nth 5 wend))))
+       (unless this-lh
+         (let ((wstart (pos-visible-in-window-p nil nil t)))
+           (setq this-ypos (nth 2 wstart)
+                 this-height (nth 4 wstart))))
+       (setq py
+             (or (nth 1 this-lh)
+                 (let ((ppos (posn-at-point))
+                       col-row)
+                   (setq col-row (posn-actual-col-row ppos))
+                   (if col-row
+                       (- (cdr col-row) (window-vscroll))
+                     (cdr (posn-col-row ppos))))))
+       ;; VPOS > 0 means the last line is only partially visible.
+       ;; But if the part that is visible is at least as tall as the
+       ;; default font, that means the line is actually fully
+       ;; readable, and something like line-spacing is hidden.  So in
+       ;; that case we accept the last line in the window as still
+       ;; visible, and consider the margin as starting one line
+       ;; later.
+       (if (and vpos (> vpos 0))
+           (if (and rowh
+                    (>= rowh (default-font-height))
+                    (< rowh dlh))
+               (setq last-line (min (- wslines scroll-margin) vpos))
+             (setq last-line (min (- wslines scroll-margin 1) (1- vpos)))))
+       (cond
+        ;; If last line of window is fully visible, and vscrolling
+        ;; more would make this line invisible, move forward.
+        ((and (or (< (setq vs (window-vscroll nil t)) dlh)
+                  (null this-height)
+                  (<= this-height dlh))
+              (or (null rbot) (= rbot 0)))
+         nil)
+        ;; If cursor is not in the bottom scroll margin, and the
+        ;; current line is is not too tall, move forward.
+        ((and (or (null this-height) (<= this-height winh))
+              vpos
+              (> vpos 0)
+              (< py last-line))
+         nil)
+        ;; When already vscrolled, we vscroll some more if we can,
+        ;; or clear vscroll and move forward at end of tall image.
+        ((> vs 0)
+         (when (or (and rbot (> rbot 0))
+                   (and this-height (> this-height dlh)))
+           (set-window-vscroll nil (+ vs dlh) t)))
+        ;; If cursor just entered the bottom scroll margin, move forward,
+        ;; but also optionally vscroll one line so redisplay won't recenter.
+        ((and vpos
+              (> vpos 0)
+              (= py last-line))
+         ;; Don't vscroll if the partially-visible line at window
+         ;; bottom is not too tall (a.k.a. "just one more text
+         ;; line"): in that case, we do want redisplay to behave
+         ;; normally, i.e. recenter or whatever.
+         ;;
+         ;; Note: ROWH + RBOT from the value returned by
+         ;; pos-visible-in-window-p give the total height of the
+         ;; partially-visible glyph row at the end of the window.  As
+         ;; we are dealing with floats, we disregard sub-pixel
+         ;; discrepancies between that and DLH.
+         (if (and rowh rbot (>= (- (+ rowh rbot) winh) 1))
+             (set-window-vscroll nil dlh t))
+         (line-move-1 arg noerror to-end)
+         t)
+        ;; If there are lines above the last line, scroll-up one line.
+        ((and vpos (> vpos 0))
+         (scroll-up 1)
+         t)
+        ;; Finally, start vscroll.
+        (t
+         (set-window-vscroll nil dlh t)))))))
+
+
+;; This is like line-move-1 except that it also performs
+;; vertical scrolling of tall images if appropriate.
+;; That is not really a clean thing to do, since it mixes
+;; scrolling with cursor motion.  But so far we don't have
+;; a cleaner solution to the problem of making C-n do something
+;; useful given a tall image.
+(defun line-move (arg &optional noerror to-end try-vscroll)
+  "Move forward ARG lines.
+If NOERROR, don't signal an error if we can't move ARG lines.
+TO-END is unused.
+TRY-VSCROLL controls whether to vscroll tall lines: if either
+`auto-window-vscroll' or TRY-VSCROLL is nil, this function will
+not vscroll."
+  (if noninteractive
+      (line-move-1 arg noerror to-end)
+    (unless (and auto-window-vscroll try-vscroll
+                ;; Only vscroll for single line moves
+                (= (abs arg) 1)
+                ;; Under scroll-conservatively, the display engine
+                ;; does this better.
+                (zerop scroll-conservatively)
+                ;; But don't vscroll in a keyboard macro.
+                (not defining-kbd-macro)
+                (not executing-kbd-macro)
+                (line-move-partial arg noerror to-end))
+      (set-window-vscroll nil 0 t)
+      (if (and line-move-visual
+              ;; Display-based column are incompatible with goal-column.
+              (not goal-column)
+              ;; When the text in the window is scrolled to the left,
+              ;; display-based motion doesn't make sense (because each
+              ;; logical line occupies exactly one screen line).
+              (not (> (window-hscroll) 0))
+              ;; Likewise when the text _was_ scrolled to the left
+              ;; when the current run of vertical motion commands
+              ;; started.
+              (not (and (memq last-command
+                              `(next-line previous-line ,this-command))
+                        auto-hscroll-mode
+                        (numberp temporary-goal-column)
+                        (>= temporary-goal-column
+                           (- (window-width) hscroll-margin)))))
+         (prog1 (line-move-visual arg noerror)
+           ;; If we moved into a tall line, set vscroll to make
+           ;; scrolling through tall images more smooth.
+           (let ((lh (line-pixel-height))
+                 (edges (window-inside-pixel-edges))
+                 (dlh (default-line-height))
+                 winh)
+             (setq winh (- (nth 3 edges) (nth 1 edges) 1))
+             (if (and (< arg 0)
+                      (< (point) (window-start))
+                      (> lh winh))
+                 (set-window-vscroll
+                  nil
+                  (- lh dlh) t))))
+       (line-move-1 arg noerror to-end)))))
+
+;; Display-based alternative to line-move-1.
+;; Arg says how many lines to move.  The value is t if we can move the
+;; specified number of lines.
+(defun line-move-visual (arg &optional noerror)
+  "Move ARG lines forward.
+If NOERROR, don't signal an error if we can't move that many lines."
+  (let ((opoint (point))
+       (hscroll (window-hscroll))
+       target-hscroll)
+    ;; Check if the previous command was a line-motion command, or if
+    ;; we were called from some other command.
+    (if (and (consp temporary-goal-column)
+            (memq last-command `(next-line previous-line ,this-command)))
+       ;; If so, there's no need to reset `temporary-goal-column',
+       ;; but we may need to hscroll.
+       (if (or (/= (cdr temporary-goal-column) hscroll)
+               (>  (cdr temporary-goal-column) 0))
+           (setq target-hscroll (cdr temporary-goal-column)))
+      ;; Otherwise, we should reset `temporary-goal-column'.
+      (let ((posn (posn-at-point))
+           x-pos)
+       (cond
+        ;; Handle the `overflow-newline-into-fringe' case:
+        ((eq (nth 1 posn) 'right-fringe)
+         (setq temporary-goal-column (cons (- (window-width) 1) hscroll)))
+        ((car (posn-x-y posn))
+         (setq x-pos (car (posn-x-y posn)))
+         ;; In R2L lines, the X pixel coordinate is measured from the
+         ;; left edge of the window, but columns are still counted
+         ;; from the logical-order beginning of the line, i.e. from
+         ;; the right edge in this case.  We need to adjust for that.
+         (if (eq (current-bidi-paragraph-direction) 'right-to-left)
+             (setq x-pos (- (window-body-width nil t) 1 x-pos)))
+         (setq temporary-goal-column
+               (cons (/ (float x-pos)
+                        (frame-char-width))
+                      hscroll))))))
+    (if target-hscroll
+       (set-window-hscroll (selected-window) target-hscroll))
+    ;; vertical-motion can move more than it was asked to if it moves
+    ;; across display strings with newlines.  We don't want to ring
+    ;; the bell and announce beginning/end of buffer in that case.
+    (or (and (or (and (>= arg 0)
+                     (>= (vertical-motion
+                          (cons (or goal-column
+                                    (if (consp temporary-goal-column)
+                                        (car temporary-goal-column)
+                                      temporary-goal-column))
+                                arg))
+                         arg))
+                (and (< arg 0)
+                     (<= (vertical-motion
+                          (cons (or goal-column
+                                    (if (consp temporary-goal-column)
+                                        (car temporary-goal-column)
+                                      temporary-goal-column))
+                                arg))
+                         arg)))
+            (or (>= arg 0)
+                (/= (point) opoint)
+                ;; If the goal column lies on a display string,
+                ;; `vertical-motion' advances the cursor to the end
+                ;; of the string.  For arg < 0, this can cause the
+                ;; cursor to get stuck.  (Bug#3020).
+                (= (vertical-motion arg) arg)))
+       (unless noerror
+         (signal (if (< arg 0) 'beginning-of-buffer 'end-of-buffer)
+                 nil)))))
+
+;; This is the guts of next-line and previous-line.
+;; Arg says how many lines to move.
+;; The value is t if we can move the specified number of lines.
+(defun line-move-1 (arg &optional noerror _to-end)
+  ;; Don't run any point-motion hooks, and disregard intangibility,
+  ;; for intermediate positions.
+  (let ((inhibit-point-motion-hooks t)
+       (opoint (point))
+       (orig-arg arg))
+    (if (consp temporary-goal-column)
+       (setq temporary-goal-column (+ (car temporary-goal-column)
+                                      (cdr temporary-goal-column))))
+    (unwind-protect
+       (progn
+         (if (not (memq last-command '(next-line previous-line)))
+             (setq temporary-goal-column
+                   (if (and track-eol (eolp)
+                            ;; Don't count beg of empty line as end of line
+                            ;; unless we just did explicit end-of-line.
+                            (or (not (bolp)) (eq last-command 
'move-end-of-line)))
+                       most-positive-fixnum
+                     (current-column))))
+
+         (if (not (or (integerp selective-display)
+                       line-move-ignore-invisible))
+             ;; Use just newline characters.
+             ;; Set ARG to 0 if we move as many lines as requested.
+             (or (if (> arg 0)
+                     (progn (if (> arg 1) (forward-line (1- arg)))
+                            ;; This way of moving forward ARG lines
+                            ;; verifies that we have a newline after the last 
one.
+                            ;; It doesn't get confused by intangible text.
+                            (end-of-line)
+                            (if (zerop (forward-line 1))
+                                (setq arg 0)))
+                   (and (zerop (forward-line arg))
+                        (bolp)
+                        (setq arg 0)))
+                 (unless noerror
+                   (signal (if (< arg 0)
+                               'beginning-of-buffer
+                             'end-of-buffer)
+                           nil)))
+           ;; Move by arg lines, but ignore invisible ones.
+           (let (done)
+             (while (and (> arg 0) (not done))
+               ;; If the following character is currently invisible,
+               ;; skip all characters with that same `invisible' property 
value.
+               (while (and (not (eobp)) (invisible-p (point)))
+                 (goto-char (next-char-property-change (point))))
+               ;; Move a line.
+               ;; We don't use `end-of-line', since we want to escape
+               ;; from field boundaries occurring exactly at point.
+               (goto-char (constrain-to-field
+                           (let ((inhibit-field-text-motion t))
+                             (line-end-position))
+                           (point) t t
+                           'inhibit-line-move-field-capture))
+               ;; If there's no invisibility here, move over the newline.
+               (cond
+                ((eobp)
+                 (if (not noerror)
+                     (signal 'end-of-buffer nil)
+                   (setq done t)))
+                ((and (> arg 1)  ;; Use vertical-motion for last move
+                      (not (integerp selective-display))
+                      (not (invisible-p (point))))
+                 ;; We avoid vertical-motion when possible
+                 ;; because that has to fontify.
+                 (forward-line 1))
+                ;; Otherwise move a more sophisticated way.
+                ((zerop (vertical-motion 1))
+                 (if (not noerror)
+                     (signal 'end-of-buffer nil)
+                   (setq done t))))
+               (unless done
+                 (setq arg (1- arg))))
+             ;; The logic of this is the same as the loop above,
+             ;; it just goes in the other direction.
+             (while (and (< arg 0) (not done))
+               ;; For completely consistency with the forward-motion
+               ;; case, we should call beginning-of-line here.
+               ;; However, if point is inside a field and on a
+               ;; continued line, the call to (vertical-motion -1)
+               ;; below won't move us back far enough; then we return
+               ;; to the same column in line-move-finish, and point
+               ;; gets stuck -- cyd
+               (forward-line 0)
+               (cond
+                ((bobp)
+                 (if (not noerror)
+                     (signal 'beginning-of-buffer nil)
+                   (setq done t)))
+                ((and (< arg -1) ;; Use vertical-motion for last move
+                      (not (integerp selective-display))
+                      (not (invisible-p (1- (point)))))
+                 (forward-line -1))
+                ((zerop (vertical-motion -1))
+                 (if (not noerror)
+                     (signal 'beginning-of-buffer nil)
+                   (setq done t))))
+               (unless done
+                 (setq arg (1+ arg))
+                 (while (and ;; Don't move over previous invis lines
+                         ;; if our target is the middle of this line.
+                         (or (zerop (or goal-column temporary-goal-column))
+                             (< arg 0))
+                         (not (bobp)) (invisible-p (1- (point))))
+                   (goto-char (previous-char-property-change (point))))))))
+         ;; This is the value the function returns.
+         (= arg 0))
+
+      (cond ((> arg 0)
+            ;; If we did not move down as far as desired, at least go
+            ;; to end of line.  Be sure to call point-entered and
+            ;; point-left-hooks.
+            (let* ((npoint (prog1 (line-end-position)
+                             (goto-char opoint)))
+                   (inhibit-point-motion-hooks nil))
+              (goto-char npoint)))
+           ((< arg 0)
+            ;; If we did not move up as far as desired,
+            ;; at least go to beginning of line.
+            (let* ((npoint (prog1 (line-beginning-position)
+                             (goto-char opoint)))
+                   (inhibit-point-motion-hooks nil))
+              (goto-char npoint)))
+           (t
+            (line-move-finish (or goal-column temporary-goal-column)
+                              opoint (> orig-arg 0)))))))
+
+(defun line-move-finish (column opoint forward)
+  (let ((repeat t))
+    (while repeat
+      ;; Set REPEAT to t to repeat the whole thing.
+      (setq repeat nil)
+
+      (let (new
+           (old (point))
+           (line-beg (line-beginning-position))
+           (line-end
+            ;; Compute the end of the line
+            ;; ignoring effectively invisible newlines.
+            (save-excursion
+              ;; Like end-of-line but ignores fields.
+              (skip-chars-forward "^\n")
+              (while (and (not (eobp)) (invisible-p (point)))
+                (goto-char (next-char-property-change (point)))
+                (skip-chars-forward "^\n"))
+              (point))))
+
+       ;; Move to the desired column.
+       (line-move-to-column (truncate column))
+
+       ;; Corner case: suppose we start out in a field boundary in
+       ;; the middle of a continued line.  When we get to
+       ;; line-move-finish, point is at the start of a new *screen*
+       ;; line but the same text line; then line-move-to-column would
+       ;; move us backwards.  Test using C-n with point on the "x" in
+       ;;   (insert "a" (propertize "x" 'field t) (make-string 89 ?y))
+       (and forward
+            (< (point) old)
+            (goto-char old))
+
+       (setq new (point))
+
+       ;; Process intangibility within a line.
+       ;; With inhibit-point-motion-hooks bound to nil, a call to
+       ;; goto-char moves point past intangible text.
+
+       ;; However, inhibit-point-motion-hooks controls both the
+       ;; intangibility and the point-entered/point-left hooks.  The
+       ;; following hack avoids calling the point-* hooks
+       ;; unnecessarily.  Note that we move *forward* past intangible
+       ;; text when the initial and final points are the same.
+       (goto-char new)
+       (let ((inhibit-point-motion-hooks nil))
+         (goto-char new)
+
+         ;; If intangibility moves us to a different (later) place
+         ;; in the same line, use that as the destination.
+         (if (<= (point) line-end)
+             (setq new (point))
+           ;; If that position is "too late",
+           ;; try the previous allowable position.
+           ;; See if it is ok.
+           (backward-char)
+           (if (if forward
+                   ;; If going forward, don't accept the previous
+                   ;; allowable position if it is before the target line.
+                   (< line-beg (point))
+                 ;; If going backward, don't accept the previous
+                 ;; allowable position if it is still after the target line.
+                 (<= (point) line-end))
+               (setq new (point))
+             ;; As a last resort, use the end of the line.
+             (setq new line-end))))
+
+       ;; Now move to the updated destination, processing fields
+       ;; as well as intangibility.
+       (goto-char opoint)
+       (let ((inhibit-point-motion-hooks nil))
+         (goto-char
+          ;; Ignore field boundaries if the initial and final
+          ;; positions have the same `field' property, even if the
+          ;; fields are non-contiguous.  This seems to be "nicer"
+          ;; behavior in many situations.
+          (if (eq (get-char-property new 'field)
+                  (get-char-property opoint 'field))
+              new
+            (constrain-to-field new opoint t t
+                                'inhibit-line-move-field-capture))))
+
+       ;; If all this moved us to a different line,
+       ;; retry everything within that new line.
+       (when (or (< (point) line-beg) (> (point) line-end))
+         ;; Repeat the intangibility and field processing.
+         (setq repeat t))))))
+
+(defun line-move-to-column (col)
+  "Try to find column COL, considering invisibility.
+This function works only in certain cases,
+because what we really need is for `move-to-column'
+and `current-column' to be able to ignore invisible text."
+  (if (zerop col)
+      (beginning-of-line)
+    (move-to-column col))
+
+  (when (and line-move-ignore-invisible
+            (not (bolp)) (invisible-p (1- (point))))
+    (let ((normal-location (point))
+         (normal-column (current-column)))
+      ;; If the following character is currently invisible,
+      ;; skip all characters with that same `invisible' property value.
+      (while (and (not (eobp))
+                 (invisible-p (point)))
+       (goto-char (next-char-property-change (point))))
+      ;; Have we advanced to a larger column position?
+      (if (> (current-column) normal-column)
+         ;; We have made some progress towards the desired column.
+         ;; See if we can make any further progress.
+         (line-move-to-column (+ (current-column) (- col normal-column)))
+       ;; Otherwise, go to the place we originally found
+       ;; and move back over invisible text.
+       ;; that will get us to the same place on the screen
+       ;; but with a more reasonable buffer position.
+       (goto-char normal-location)
+       (let ((line-beg (line-beginning-position)))
+         (while (and (not (bolp)) (invisible-p (1- (point))))
+           (goto-char (previous-char-property-change (point) line-beg))))))))
+
+(defun move-end-of-line (arg)
+  "Move point to end of current line as displayed.
+With argument ARG not nil or 1, move forward ARG - 1 lines first.
+If point reaches the beginning or end of buffer, it stops there.
+
+To ignore the effects of the `intangible' text or overlay
+property, bind `inhibit-point-motion-hooks' to t.
+If there is an image in the current line, this function
+disregards newlines that are part of the text on which the image
+rests."
+  (interactive "^p")
+  (or arg (setq arg 1))
+  (let (done)
+    (while (not done)
+      (let ((newpos
+            (save-excursion
+              (let ((goal-column 0)
+                    (line-move-visual nil))
+                (and (line-move arg t)
+                     ;; With bidi reordering, we may not be at bol,
+                     ;; so make sure we are.
+                     (skip-chars-backward "^\n")
+                     (not (bobp))
+                     (progn
+                       (while (and (not (bobp)) (invisible-p (1- (point))))
+                         (goto-char (previous-single-char-property-change
+                                      (point) 'invisible)))
+                       (backward-char 1)))
+                (point)))))
+       (goto-char newpos)
+       (if (and (> (point) newpos)
+                (eq (preceding-char) ?\n))
+           (backward-char 1)
+         (if (and (> (point) newpos) (not (eobp))
+                  (not (eq (following-char) ?\n)))
+             ;; If we skipped something intangible and now we're not
+             ;; really at eol, keep going.
+             (setq arg 1)
+           (setq done t)))))))
+
+(defun move-beginning-of-line (arg)
+  "Move point to beginning of current line as displayed.
+\(If there's an image in the line, this disregards newlines
+which are part of the text that the image rests on.)
+
+With argument ARG not nil or 1, move forward ARG - 1 lines first.
+If point reaches the beginning or end of buffer, it stops there.
+To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
+  (interactive "^p")
+  (or arg (setq arg 1))
+
+  (let ((orig (point))
+       first-vis first-vis-field-value)
+
+    ;; Move by lines, if ARG is not 1 (the default).
+    (if (/= arg 1)
+       (let ((line-move-visual nil))
+         (line-move (1- arg) t)))
+
+    ;; Move to beginning-of-line, ignoring fields and invisible text.
+    (skip-chars-backward "^\n")
+    (while (and (not (bobp)) (invisible-p (1- (point))))
+      (goto-char (previous-char-property-change (point)))
+      (skip-chars-backward "^\n"))
+
+    ;; Now find first visible char in the line.
+    (while (and (< (point) orig) (invisible-p (point)))
+      (goto-char (next-char-property-change (point) orig)))
+    (setq first-vis (point))
+
+    ;; See if fields would stop us from reaching FIRST-VIS.
+    (setq first-vis-field-value
+         (constrain-to-field first-vis orig (/= arg 1) t nil))
+
+    (goto-char (if (/= first-vis-field-value first-vis)
+                  ;; If yes, obey them.
+                  first-vis-field-value
+                ;; Otherwise, move to START with attention to fields.
+                ;; (It is possible that fields never matter in this case.)
+                (constrain-to-field (point) orig
+                                    (/= arg 1) t nil)))))
+
+
+;; Many people have said they rarely use this feature, and often type
+;; it by accident.  Maybe it shouldn't even be on a key.
+(put 'set-goal-column 'disabled t)
+
+(defun set-goal-column (arg)
+  "Set the current horizontal position as a goal for \\[next-line] and 
\\[previous-line].
+Those commands will move to this position in the line moved to
+rather than trying to keep the same horizontal position.
+With a non-nil argument ARG, clears out the goal column
+so that \\[next-line] and \\[previous-line] resume vertical motion.
+The goal column is stored in the variable `goal-column'."
+  (interactive "P")
+  (if arg
+      (progn
+        (setq goal-column nil)
+        (message "No goal column"))
+    (setq goal-column (current-column))
+    ;; The older method below can be erroneous if `set-goal-column' is bound
+    ;; to a sequence containing %
+    ;;(message (substitute-command-keys
+    ;;"Goal column %d (use \\[set-goal-column] with an arg to unset it)")
+    ;;goal-column)
+    (message "%s"
+            (concat
+             (format "Goal column %d " goal-column)
+             (substitute-command-keys
+              "(use \\[set-goal-column] with an arg to unset it)")))
+
+    )
+  nil)
+
+;;; Editing based on visual lines, as opposed to logical lines.
+
+(defun end-of-visual-line (&optional n)
+  "Move point to end of current visual line.
+With argument N not nil or 1, move forward N - 1 visual lines first.
+If point reaches the beginning or end of buffer, it stops there.
+To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
+  (interactive "^p")
+  (or n (setq n 1))
+  (if (/= n 1)
+      (let ((line-move-visual t))
+       (line-move (1- n) t)))
+  ;; Unlike `move-beginning-of-line', `move-end-of-line' doesn't
+  ;; constrain to field boundaries, so we don't either.
+  (vertical-motion (cons (window-width) 0)))
+
+(defun beginning-of-visual-line (&optional n)
+  "Move point to beginning of current visual line.
+With argument N not nil or 1, move forward N - 1 visual lines first.
+If point reaches the beginning or end of buffer, it stops there.
+To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
+  (interactive "^p")
+  (or n (setq n 1))
+  (let ((opoint (point)))
+    (if (/= n 1)
+       (let ((line-move-visual t))
+         (line-move (1- n) t)))
+    (vertical-motion 0)
+    ;; Constrain to field boundaries, like `move-beginning-of-line'.
+    (goto-char (constrain-to-field (point) opoint (/= n 1)))))
+
+(defun kill-visual-line (&optional arg)
+  "Kill the rest of the visual line.
+With prefix argument ARG, kill that many visual lines from point.
+If ARG is negative, kill visual lines backward.
+If ARG is zero, kill the text before point on the current visual
+line.
+
+If you want to append the killed line to the last killed text,
+use \\[append-next-kill] before \\[kill-line].
+
+If the buffer is read-only, Emacs will beep and refrain from deleting
+the line, but put the line in the kill ring anyway.  This means that
+you can use this command to copy text from a read-only buffer.
+\(If the variable `kill-read-only-ok' is non-nil, then this won't
+even beep.)"
+  (interactive "P")
+  ;; Like in `kill-line', it's better to move point to the other end
+  ;; of the kill before killing.
+  (let ((opoint (point))
+       (kill-whole-line (and kill-whole-line (bolp))))
+    (if arg
+       (vertical-motion (prefix-numeric-value arg))
+      (end-of-visual-line 1)
+      (if (= (point) opoint)
+         (vertical-motion 1)
+       ;; Skip any trailing whitespace at the end of the visual line.
+       ;; We used to do this only if `show-trailing-whitespace' is
+       ;; nil, but that's wrong; the correct thing would be to check
+       ;; whether the trailing whitespace is highlighted.  But, it's
+       ;; OK to just do this unconditionally.
+       (skip-chars-forward " \t")))
+    (kill-region opoint (if (and kill-whole-line (looking-at "\n"))
+                           (1+ (point))
+                         (point)))))
+
+(defun next-logical-line (&optional arg try-vscroll)
+  "Move cursor vertically down ARG lines.
+This is identical to `next-line', except that it always moves
+by logical lines instead of visual lines, ignoring the value of
+the variable `line-move-visual'."
+  (interactive "^p\np")
+  (let ((line-move-visual nil))
+    (with-no-warnings
+      (next-line arg try-vscroll))))
+
+(defun previous-logical-line (&optional arg try-vscroll)
+  "Move cursor vertically up ARG lines.
+This is identical to `previous-line', except that it always moves
+by logical lines instead of visual lines, ignoring the value of
+the variable `line-move-visual'."
+  (interactive "^p\np")
+  (let ((line-move-visual nil))
+    (with-no-warnings
+      (previous-line arg try-vscroll))))
+
+(defgroup visual-line nil
+  "Editing based on visual lines."
+  :group 'convenience
+  :version "23.1")
+
+(defvar visual-line-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map [remap kill-line] 'kill-visual-line)
+    (define-key map [remap move-beginning-of-line] 'beginning-of-visual-line)
+    (define-key map [remap move-end-of-line]  'end-of-visual-line)
+    ;; These keybindings interfere with xterm function keys.  Are
+    ;; there any other suitable bindings?
+    ;; (define-key map "\M-[" 'previous-logical-line)
+    ;; (define-key map "\M-]" 'next-logical-line)
+    map))
+
+(defcustom visual-line-fringe-indicators '(nil nil)
+  "How fringe indicators are shown for wrapped lines in `visual-line-mode'.
+The value should be a list of the form (LEFT RIGHT), where LEFT
+and RIGHT are symbols representing the bitmaps to display, to
+indicate wrapped lines, in the left and right fringes respectively.
+See also `fringe-indicator-alist'.
+The default is not to display fringe indicators for wrapped lines.
+This variable does not affect fringe indicators displayed for
+other purposes."
+  :type '(list (choice (const :tag "Hide left indicator" nil)
+                      (const :tag "Left curly arrow" left-curly-arrow)
+                      (symbol :tag "Other bitmap"))
+              (choice (const :tag "Hide right indicator" nil)
+                      (const :tag "Right curly arrow" right-curly-arrow)
+                      (symbol :tag "Other bitmap")))
+  :set (lambda (symbol value)
+        (dolist (buf (buffer-list))
+          (with-current-buffer buf
+            (when (and (boundp 'visual-line-mode)
+                       (symbol-value 'visual-line-mode))
+              (setq fringe-indicator-alist
+                    (cons (cons 'continuation value)
+                          (assq-delete-all
+                           'continuation
+                           (copy-tree fringe-indicator-alist)))))))
+        (set-default symbol value)))
+
+(defvar visual-line--saved-state nil)
+
+(define-minor-mode visual-line-mode
+  "Toggle visual line based editing (Visual Line mode).
+With a prefix argument ARG, enable Visual Line mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+When Visual Line mode is enabled, `word-wrap' is turned on in
+this buffer, and simple editing commands are redefined to act on
+visual lines, not logical lines.  See Info node `Visual Line
+Mode' for details."
+  :keymap visual-line-mode-map
+  :group 'visual-line
+  :lighter " Wrap"
+  (if visual-line-mode
+      (progn
+       (set (make-local-variable 'visual-line--saved-state) nil)
+       ;; Save the local values of some variables, to be restored if
+       ;; visual-line-mode is turned off.
+       (dolist (var '(line-move-visual truncate-lines
+                      truncate-partial-width-windows
+                      word-wrap fringe-indicator-alist))
+         (if (local-variable-p var)
+             (push (cons var (symbol-value var))
+                   visual-line--saved-state)))
+       (set (make-local-variable 'line-move-visual) t)
+       (set (make-local-variable 'truncate-partial-width-windows) nil)
+       (setq truncate-lines nil
+             word-wrap t
+             fringe-indicator-alist
+             (cons (cons 'continuation visual-line-fringe-indicators)
+                   fringe-indicator-alist)))
+    (kill-local-variable 'line-move-visual)
+    (kill-local-variable 'word-wrap)
+    (kill-local-variable 'truncate-lines)
+    (kill-local-variable 'truncate-partial-width-windows)
+    (kill-local-variable 'fringe-indicator-alist)
+    (dolist (saved visual-line--saved-state)
+      (set (make-local-variable (car saved)) (cdr saved)))
+    (kill-local-variable 'visual-line--saved-state)))
+
+(defun turn-on-visual-line-mode ()
+  (visual-line-mode 1))
+
+(define-globalized-minor-mode global-visual-line-mode
+  visual-line-mode turn-on-visual-line-mode)
+
+
+(defun transpose-chars (arg)
+  "Interchange characters around point, moving forward one character.
+With prefix arg ARG, effect is to take character before point
+and drag it forward past ARG other characters (backward if ARG negative).
+If no argument and at end of line, the previous two chars are exchanged."
+  (interactive "*P")
+  (and (null arg) (eolp) (forward-char -1))
+  (transpose-subr 'forward-char (prefix-numeric-value arg)))
+
+(defun transpose-words (arg)
+  "Interchange words around point, leaving point at end of them.
+With prefix arg ARG, effect is to take word before or around point
+and drag it forward past ARG other words (backward if ARG negative).
+If ARG is zero, the words around or after point and around or after mark
+are interchanged."
+  ;; FIXME: `foo a!nd bar' should transpose into `bar and foo'.
+  (interactive "*p")
+  (transpose-subr 'forward-word arg))
+
+(defun transpose-sexps (arg)
+  "Like \\[transpose-words] but applies to sexps.
+Does not work on a sexp that point is in the middle of
+if it is a list or string."
+  (interactive "*p")
+  (transpose-subr
+   (lambda (arg)
+     ;; Here we should try to simulate the behavior of
+     ;; (cons (progn (forward-sexp x) (point))
+     ;;       (progn (forward-sexp (- x)) (point)))
+     ;; Except that we don't want to rely on the second forward-sexp
+     ;; putting us back to where we want to be, since forward-sexp-function
+     ;; might do funny things like infix-precedence.
+     (if (if (> arg 0)
+            (looking-at "\\sw\\|\\s_")
+          (and (not (bobp))
+               (save-excursion (forward-char -1) (looking-at "\\sw\\|\\s_"))))
+        ;; Jumping over a symbol.  We might be inside it, mind you.
+        (progn (funcall (if (> arg 0)
+                            'skip-syntax-backward 'skip-syntax-forward)
+                        "w_")
+               (cons (save-excursion (forward-sexp arg) (point)) (point)))
+       ;; Otherwise, we're between sexps.  Take a step back before jumping
+       ;; to make sure we'll obey the same precedence no matter which direction
+       ;; we're going.
+       (funcall (if (> arg 0) 'skip-syntax-backward 'skip-syntax-forward) " .")
+       (cons (save-excursion (forward-sexp arg) (point))
+            (progn (while (or (forward-comment (if (> arg 0) 1 -1))
+                              (not (zerop (funcall (if (> arg 0)
+                                                       'skip-syntax-forward
+                                                     'skip-syntax-backward)
+                                                   ".")))))
+                   (point)))))
+   arg 'special))
+
+(defun transpose-lines (arg)
+  "Exchange current line and previous line, leaving point after both.
+With argument ARG, takes previous line and moves it past ARG lines.
+With argument 0, interchanges line point is in with line mark is in."
+  (interactive "*p")
+  (transpose-subr (function
+                  (lambda (arg)
+                    (if (> arg 0)
+                        (progn
+                          ;; Move forward over ARG lines,
+                          ;; but create newlines if necessary.
+                          (setq arg (forward-line arg))
+                          (if (/= (preceding-char) ?\n)
+                              (setq arg (1+ arg)))
+                          (if (> arg 0)
+                              (newline arg)))
+                      (forward-line arg))))
+                 arg))
+
+;; FIXME seems to leave point BEFORE the current object when ARG = 0,
+;; which seems inconsistent with the ARG /= 0 case.
+;; FIXME document SPECIAL.
+(defun transpose-subr (mover arg &optional special)
+  "Subroutine to do the work of transposing objects.
+Works for lines, sentences, paragraphs, etc.  MOVER is a function that
+moves forward by units of the given object (e.g. forward-sentence,
+forward-paragraph).  If ARG is zero, exchanges the current object
+with the one containing mark.  If ARG is an integer, moves the
+current object past ARG following (if ARG is positive) or
+preceding (if ARG is negative) objects, leaving point after the
+current object."
+  (let ((aux (if special mover
+              (lambda (x)
+                (cons (progn (funcall mover x) (point))
+                      (progn (funcall mover (- x)) (point))))))
+       pos1 pos2)
+    (cond
+     ((= arg 0)
+      (save-excursion
+       (setq pos1 (funcall aux 1))
+       (goto-char (or (mark) (error "No mark set in this buffer")))
+       (setq pos2 (funcall aux 1))
+       (transpose-subr-1 pos1 pos2))
+      (exchange-point-and-mark))
+     ((> arg 0)
+      (setq pos1 (funcall aux -1))
+      (setq pos2 (funcall aux arg))
+      (transpose-subr-1 pos1 pos2)
+      (goto-char (car pos2)))
+     (t
+      (setq pos1 (funcall aux -1))
+      (goto-char (car pos1))
+      (setq pos2 (funcall aux arg))
+      (transpose-subr-1 pos1 pos2)))))
+
+(defun transpose-subr-1 (pos1 pos2)
+  (when (> (car pos1) (cdr pos1)) (setq pos1 (cons (cdr pos1) (car pos1))))
+  (when (> (car pos2) (cdr pos2)) (setq pos2 (cons (cdr pos2) (car pos2))))
+  (when (> (car pos1) (car pos2))
+    (let ((swap pos1))
+      (setq pos1 pos2 pos2 swap)))
+  (if (> (cdr pos1) (car pos2)) (error "Don't have two things to transpose"))
+  (atomic-change-group
+    ;; This sequence of insertions attempts to preserve marker
+    ;; positions at the start and end of the transposed objects.
+    (let* ((word (buffer-substring (car pos2) (cdr pos2)))
+          (len1 (- (cdr pos1) (car pos1)))
+          (len2 (length word))
+          (boundary (make-marker)))
+      (set-marker boundary (car pos2))
+      (goto-char (cdr pos1))
+      (insert-before-markers word)
+      (setq word (delete-and-extract-region (car pos1) (+ (car pos1) len1)))
+      (goto-char boundary)
+      (insert word)
+      (goto-char (+ boundary len1))
+      (delete-region (point) (+ (point) len2))
+      (set-marker boundary nil))))
+
+(defun backward-word (&optional arg)
+  "Move backward until encountering the beginning of a word.
+With argument ARG, do this that many times.
+If ARG is omitted or nil, move point backward one word."
+  (interactive "^p")
+  (forward-word (- (or arg 1))))
+
+(defun mark-word (&optional arg allow-extend)
+  "Set mark ARG words away from point.
+The place mark goes is the same place \\[forward-word] would
+move to with the same argument.
+Interactively, if this command is repeated
+or (in Transient Mark mode) if the mark is active,
+it marks the next ARG words after the ones already marked."
+  (interactive "P\np")
+  (cond ((and allow-extend
+             (or (and (eq last-command this-command) (mark t))
+                 (region-active-p)))
+        (setq arg (if arg (prefix-numeric-value arg)
+                    (if (< (mark) (point)) -1 1)))
+        (set-mark
+         (save-excursion
+           (goto-char (mark))
+           (forward-word arg)
+           (point))))
+       (t
+        (push-mark
+         (save-excursion
+           (forward-word (prefix-numeric-value arg))
+           (point))
+         nil t))))
+
+(defun kill-word (arg)
+  "Kill characters forward until encountering the end of a word.
+With argument ARG, do this that many times."
+  (interactive "p")
+  (kill-region (point) (progn (forward-word arg) (point))))
+
+(defun backward-kill-word (arg)
+  "Kill characters backward until encountering the beginning of a word.
+With argument ARG, do this that many times."
+  (interactive "p")
+  (kill-word (- arg)))
+
+(defun current-word (&optional strict really-word)
+  "Return the symbol or word that point is on (or a nearby one) as a string.
+The return value includes no text properties.
+If optional arg STRICT is non-nil, return nil unless point is within
+or adjacent to a symbol or word.  In all cases the value can be nil
+if there is no word nearby.
+The function, belying its name, normally finds a symbol.
+If optional arg REALLY-WORD is non-nil, it finds just a word."
+  (save-excursion
+    (let* ((oldpoint (point)) (start (point)) (end (point))
+          (syntaxes (if really-word "w" "w_"))
+          (not-syntaxes (concat "^" syntaxes)))
+      (skip-syntax-backward syntaxes) (setq start (point))
+      (goto-char oldpoint)
+      (skip-syntax-forward syntaxes) (setq end (point))
+      (when (and (eq start oldpoint) (eq end oldpoint)
+                ;; Point is neither within nor adjacent to a word.
+                (not strict))
+       ;; Look for preceding word in same line.
+       (skip-syntax-backward not-syntaxes (line-beginning-position))
+       (if (bolp)
+           ;; No preceding word in same line.
+           ;; Look for following word in same line.
+           (progn
+             (skip-syntax-forward not-syntaxes (line-end-position))
+             (setq start (point))
+             (skip-syntax-forward syntaxes)
+             (setq end (point)))
+         (setq end (point))
+         (skip-syntax-backward syntaxes)
+         (setq start (point))))
+      ;; If we found something nonempty, return it as a string.
+      (unless (= start end)
+       (buffer-substring-no-properties start end)))))
+
+(defcustom fill-prefix nil
+  "String for filling to insert at front of new line, or nil for none."
+  :type '(choice (const :tag "None" nil)
+                string)
+  :group 'fill)
+(make-variable-buffer-local 'fill-prefix)
+(put 'fill-prefix 'safe-local-variable 'string-or-null-p)
+
+(defcustom auto-fill-inhibit-regexp nil
+  "Regexp to match lines which should not be auto-filled."
+  :type '(choice (const :tag "None" nil)
+                regexp)
+  :group 'fill)
+
+(defun do-auto-fill ()
+  "The default value for `normal-auto-fill-function'.
+This is the default auto-fill function, some major modes use a different one.
+Returns t if it really did any work."
+  (let (fc justify give-up
+          (fill-prefix fill-prefix))
+    (if (or (not (setq justify (current-justification)))
+           (null (setq fc (current-fill-column)))
+           (and (eq justify 'left)
+                (<= (current-column) fc))
+           (and auto-fill-inhibit-regexp
+                (save-excursion (beginning-of-line)
+                                (looking-at auto-fill-inhibit-regexp))))
+       nil ;; Auto-filling not required
+      (if (memq justify '(full center right))
+         (save-excursion (unjustify-current-line)))
+
+      ;; Choose a fill-prefix automatically.
+      (when (and adaptive-fill-mode
+                (or (null fill-prefix) (string= fill-prefix "")))
+       (let ((prefix
+              (fill-context-prefix
+               (save-excursion (fill-forward-paragraph -1) (point))
+               (save-excursion (fill-forward-paragraph 1) (point)))))
+         (and prefix (not (equal prefix ""))
+              ;; Use auto-indentation rather than a guessed empty prefix.
+              (not (and fill-indent-according-to-mode
+                        (string-match "\\`[ \t]*\\'" prefix)))
+              (setq fill-prefix prefix))))
+
+      (while (and (not give-up) (> (current-column) fc))
+       ;; Determine where to split the line.
+       (let* (after-prefix
+              (fill-point
+               (save-excursion
+                 (beginning-of-line)
+                 (setq after-prefix (point))
+                 (and fill-prefix
+                      (looking-at (regexp-quote fill-prefix))
+                      (setq after-prefix (match-end 0)))
+                 (move-to-column (1+ fc))
+                 (fill-move-to-break-point after-prefix)
+                 (point))))
+
+         ;; See whether the place we found is any good.
+         (if (save-excursion
+               (goto-char fill-point)
+               (or (bolp)
+                   ;; There is no use breaking at end of line.
+                   (save-excursion (skip-chars-forward " ") (eolp))
+                   ;; It is futile to split at the end of the prefix
+                   ;; since we would just insert the prefix again.
+                   (and after-prefix (<= (point) after-prefix))
+                   ;; Don't split right after a comment starter
+                   ;; since we would just make another comment starter.
+                   (and comment-start-skip
+                        (let ((limit (point)))
+                          (beginning-of-line)
+                          (and (re-search-forward comment-start-skip
+                                                  limit t)
+                               (eq (point) limit))))))
+             ;; No good place to break => stop trying.
+             (setq give-up t)
+           ;; Ok, we have a useful place to break the line.  Do it.
+           (let ((prev-column (current-column)))
+             ;; If point is at the fill-point, do not `save-excursion'.
+             ;; Otherwise, if a comment prefix or fill-prefix is inserted,
+             ;; point will end up before it rather than after it.
+             (if (save-excursion
+                   (skip-chars-backward " \t")
+                   (= (point) fill-point))
+                 (default-indent-new-line t)
+               (save-excursion
+                 (goto-char fill-point)
+                 (default-indent-new-line t)))
+             ;; Now do justification, if required
+             (if (not (eq justify 'left))
+                 (save-excursion
+                   (end-of-line 0)
+                   (justify-current-line justify nil t)))
+             ;; If making the new line didn't reduce the hpos of
+             ;; the end of the line, then give up now;
+             ;; trying again will not help.
+             (if (>= (current-column) prev-column)
+                 (setq give-up t))))))
+      ;; Justify last line.
+      (justify-current-line justify t t)
+      t)))
+
+(defvar comment-line-break-function 'comment-indent-new-line
+  "Mode-specific function which line breaks and continues a comment.
+This function is called during auto-filling when a comment syntax
+is defined.
+The function should take a single optional argument, which is a flag
+indicating whether it should use soft newlines.")
+
+(defun default-indent-new-line (&optional soft)
+  "Break line at point and indent.
+If a comment syntax is defined, call `comment-indent-new-line'.
+
+The inserted newline is marked hard if variable `use-hard-newlines' is true,
+unless optional argument SOFT is non-nil."
+  (interactive)
+  (if comment-start
+      (funcall comment-line-break-function soft)
+    ;; Insert the newline before removing empty space so that markers
+    ;; get preserved better.
+    (if soft (insert-and-inherit ?\n) (newline 1))
+    (save-excursion (forward-char -1) (delete-horizontal-space))
+    (delete-horizontal-space)
+
+    (if (and fill-prefix (not adaptive-fill-mode))
+       ;; Blindly trust a non-adaptive fill-prefix.
+       (progn
+         (indent-to-left-margin)
+         (insert-before-markers-and-inherit fill-prefix))
+
+      (cond
+       ;; If there's an adaptive prefix, use it unless we're inside
+       ;; a comment and the prefix is not a comment starter.
+       (fill-prefix
+       (indent-to-left-margin)
+       (insert-and-inherit fill-prefix))
+       ;; If we're not inside a comment, just try to indent.
+       (t (indent-according-to-mode))))))
+
+(defvar normal-auto-fill-function 'do-auto-fill
+  "The function to use for `auto-fill-function' if Auto Fill mode is turned on.
+Some major modes set this.")
+
+(put 'auto-fill-function :minor-mode-function 'auto-fill-mode)
+;; `functions' and `hooks' are usually unsafe to set, but setting
+;; auto-fill-function to nil in a file-local setting is safe and
+;; can be useful to prevent auto-filling.
+(put 'auto-fill-function 'safe-local-variable 'null)
+
+(define-minor-mode auto-fill-mode
+  "Toggle automatic line breaking (Auto Fill mode).
+With a prefix argument ARG, enable Auto Fill mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+When Auto Fill mode is enabled, inserting a space at a column
+beyond `current-fill-column' automatically breaks the line at a
+previous space.
+
+When `auto-fill-mode' is on, the `auto-fill-function' variable is
+non-`nil'.
+
+The value of `normal-auto-fill-function' specifies the function to use
+for `auto-fill-function' when turning Auto Fill mode on."
+  :variable (auto-fill-function
+             . (lambda (v) (setq auto-fill-function
+                            (if v normal-auto-fill-function)))))
+
+;; This holds a document string used to document auto-fill-mode.
+(defun auto-fill-function ()
+  "Automatically break line at a previous space, in insertion of text."
+  nil)
+
+(defun turn-on-auto-fill ()
+  "Unconditionally turn on Auto Fill mode."
+  (auto-fill-mode 1))
+
+(defun turn-off-auto-fill ()
+  "Unconditionally turn off Auto Fill mode."
+  (auto-fill-mode -1))
+
+(custom-add-option 'text-mode-hook 'turn-on-auto-fill)
+
+(defun set-fill-column (arg)
+  "Set `fill-column' to specified argument.
+Use \\[universal-argument] followed by a number to specify a column.
+Just \\[universal-argument] as argument means to use the current column."
+  (interactive
+   (list (or current-prefix-arg
+             ;; We used to use current-column silently, but C-x f is too easily
+             ;; typed as a typo for C-x C-f, so we turned it into an error and
+             ;; now an interactive prompt.
+             (read-number "Set fill-column to: " (current-column)))))
+  (if (consp arg)
+      (setq arg (current-column)))
+  (if (not (integerp arg))
+      ;; Disallow missing argument; it's probably a typo for C-x C-f.
+      (error "set-fill-column requires an explicit argument")
+    (message "Fill column set to %d (was %d)" arg fill-column)
+    (setq fill-column arg)))
+
+(defun set-selective-display (arg)
+  "Set `selective-display' to ARG; clear it if no arg.
+When the value of `selective-display' is a number > 0,
+lines whose indentation is >= that value are not displayed.
+The variable `selective-display' has a separate value for each buffer."
+  (interactive "P")
+  (if (eq selective-display t)
+      (error "selective-display already in use for marked lines"))
+  (let ((current-vpos
+        (save-restriction
+          (narrow-to-region (point-min) (point))
+          (goto-char (window-start))
+          (vertical-motion (window-height)))))
+    (setq selective-display
+         (and arg (prefix-numeric-value arg)))
+    (recenter current-vpos))
+  (set-window-start (selected-window) (window-start))
+  (princ "selective-display set to " t)
+  (prin1 selective-display t)
+  (princ "." t))
+
+(defvaralias 'indicate-unused-lines 'indicate-empty-lines)
+
+(defun toggle-truncate-lines (&optional arg)
+  "Toggle truncating of long lines for the current buffer.
+When truncating is off, long lines are folded.
+With prefix argument ARG, truncate long lines if ARG is positive,
+otherwise fold them.  Note that in side-by-side windows, this
+command has no effect if `truncate-partial-width-windows' is
+non-nil."
+  (interactive "P")
+  (setq truncate-lines
+       (if (null arg)
+           (not truncate-lines)
+         (> (prefix-numeric-value arg) 0)))
+  (force-mode-line-update)
+  (unless truncate-lines
+    (let ((buffer (current-buffer)))
+      (walk-windows (lambda (window)
+                     (if (eq buffer (window-buffer window))
+                         (set-window-hscroll window 0)))
+                   nil t)))
+  (message "Truncate long lines %s"
+          (if truncate-lines "enabled" "disabled")))
+
+(defun toggle-word-wrap (&optional arg)
+  "Toggle whether to use word-wrapping for continuation lines.
+With prefix argument ARG, wrap continuation lines at word boundaries
+if ARG is positive, otherwise wrap them at the right screen edge.
+This command toggles the value of `word-wrap'.  It has no effect
+if long lines are truncated."
+  (interactive "P")
+  (setq word-wrap
+       (if (null arg)
+           (not word-wrap)
+         (> (prefix-numeric-value arg) 0)))
+  (force-mode-line-update)
+  (message "Word wrapping %s"
+          (if word-wrap "enabled" "disabled")))
+
+(defvar overwrite-mode-textual (purecopy " Ovwrt")
+  "The string displayed in the mode line when in overwrite mode.")
+(defvar overwrite-mode-binary (purecopy " Bin Ovwrt")
+  "The string displayed in the mode line when in binary overwrite mode.")
+
+(define-minor-mode overwrite-mode
+  "Toggle Overwrite mode.
+With a prefix argument ARG, enable Overwrite mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+When Overwrite mode is enabled, printing characters typed in
+replace existing text on a one-for-one basis, rather than pushing
+it to the right.  At the end of a line, such characters extend
+the line.  Before a tab, such characters insert until the tab is
+filled in.  \\[quoted-insert] still inserts characters in
+overwrite mode; this is supposed to make it easier to insert
+characters when necessary."
+  :variable (overwrite-mode
+             . (lambda (v) (setq overwrite-mode (if v 
'overwrite-mode-textual)))))
+
+(define-minor-mode binary-overwrite-mode
+  "Toggle Binary Overwrite mode.
+With a prefix argument ARG, enable Binary Overwrite mode if ARG
+is positive, and disable it otherwise.  If called from Lisp,
+enable the mode if ARG is omitted or nil.
+
+When Binary Overwrite mode is enabled, printing characters typed
+in replace existing text.  Newlines are not treated specially, so
+typing at the end of a line joins the line to the next, with the
+typed character between them.  Typing before a tab character
+simply replaces the tab with the character typed.
+\\[quoted-insert] replaces the text at the cursor, just as
+ordinary typing characters do.
+
+Note that Binary Overwrite mode is not its own minor mode; it is
+a specialization of overwrite mode, entered by setting the
+`overwrite-mode' variable to `overwrite-mode-binary'."
+  :variable (overwrite-mode
+             . (lambda (v) (setq overwrite-mode (if v 
'overwrite-mode-binary)))))
+
+(define-minor-mode line-number-mode
+  "Toggle line number display in the mode line (Line Number mode).
+With a prefix argument ARG, enable Line Number mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+Line numbers do not appear for very large buffers and buffers
+with very long lines; see variables `line-number-display-limit'
+and `line-number-display-limit-width'."
+  :init-value t :global t :group 'mode-line)
+
+(define-minor-mode column-number-mode
+  "Toggle column number display in the mode line (Column Number mode).
+With a prefix argument ARG, enable Column Number mode if ARG is
+positive, and disable it otherwise.
+
+If called from Lisp, enable the mode if ARG is omitted or nil."
+  :global t :group 'mode-line)
+
+(define-minor-mode size-indication-mode
+  "Toggle buffer size display in the mode line (Size Indication mode).
+With a prefix argument ARG, enable Size Indication mode if ARG is
+positive, and disable it otherwise.
+
+If called from Lisp, enable the mode if ARG is omitted or nil."
+  :global t :group 'mode-line)
+
+(define-minor-mode auto-save-mode
+  "Toggle auto-saving in the current buffer (Auto Save mode).
+With a prefix argument ARG, enable Auto Save mode if ARG is
+positive, and disable it otherwise.
+
+If called from Lisp, enable the mode if ARG is omitted or nil."
+  :variable ((and buffer-auto-save-file-name
+                  ;; If auto-save is off because buffer has shrunk,
+                  ;; then toggling should turn it on.
+                  (>= buffer-saved-size 0))
+             . (lambda (val)
+                 (setq buffer-auto-save-file-name
+                       (cond
+                        ((null val) nil)
+                        ((and buffer-file-name auto-save-visited-file-name
+                              (not buffer-read-only))
+                         buffer-file-name)
+                        (t (make-auto-save-file-name))))))
+  ;; If -1 was stored here, to temporarily turn off saving,
+  ;; turn it back on.
+  (and (< buffer-saved-size 0)
+       (setq buffer-saved-size 0)))
+
+(defgroup paren-blinking nil
+  "Blinking matching of parens and expressions."
+  :prefix "blink-matching-"
+  :group 'paren-matching)
+
+(defcustom blink-matching-paren t
+  "Non-nil means show matching open-paren when close-paren is inserted.
+If t, highlight the paren.  If `jump', move cursor to its position."
+  :type '(choice
+          (const :tag "Disable" nil)
+          (const :tag "Highlight" t)
+          (const :tag "Move cursor" jump))
+  :group 'paren-blinking)
+
+(defcustom blink-matching-paren-on-screen t
+  "Non-nil means show matching open-paren when it is on screen.
+If nil, don't show it (but the open-paren can still be shown
+when it is off screen).
+
+This variable has no effect if `blink-matching-paren' is nil.
+\(In that case, the open-paren is never shown.)
+It is also ignored if `show-paren-mode' is enabled."
+  :type 'boolean
+  :group 'paren-blinking)
+
+(defcustom blink-matching-paren-distance (* 100 1024)
+  "If non-nil, maximum distance to search backwards for matching open-paren.
+If nil, search stops at the beginning of the accessible portion of the buffer."
+  :version "23.2"                       ; 25->100k
+  :type '(choice (const nil) integer)
+  :group 'paren-blinking)
+
+(defcustom blink-matching-delay 1
+  "Time in seconds to delay after showing a matching paren."
+  :type 'number
+  :group 'paren-blinking)
+
+(defcustom blink-matching-paren-dont-ignore-comments nil
+  "If nil, `blink-matching-paren' ignores comments.
+More precisely, when looking for the matching parenthesis,
+it skips the contents of comments that end before point."
+  :type 'boolean
+  :group 'paren-blinking)
+
+(defun blink-matching-check-mismatch (start end)
+  "Return whether or not START...END are matching parens.
+END is the current point and START is the blink position.
+START might be nil if no matching starter was found.
+Returns non-nil if we find there is a mismatch."
+  (let* ((end-syntax (syntax-after (1- end)))
+         (matching-paren (and (consp end-syntax)
+                              (eq (syntax-class end-syntax) 5)
+                              (cdr end-syntax))))
+    ;; For self-matched chars like " and $, we can't know when they're
+    ;; mismatched or unmatched, so we can only do it for parens.
+    (when matching-paren
+      (not (and start
+                (or
+                 (eq (char-after start) matching-paren)
+                 ;; The cdr might hold a new paren-class info rather than
+                 ;; a matching-char info, in which case the two CDRs
+                 ;; should match.
+                 (eq matching-paren (cdr-safe (syntax-after start)))))))))
+
+(defvar blink-matching-check-function #'blink-matching-check-mismatch
+  "Function to check parentheses mismatches.
+The function takes two arguments (START and END) where START is the
+position just before the opening token and END is the position right after.
+START can be nil, if it was not found.
+The function should return non-nil if the two tokens do not match.")
+
+(defvar blink-matching--overlay
+  (let ((ol (make-overlay (point) (point) nil t)))
+    (overlay-put ol 'face 'show-paren-match)
+    (delete-overlay ol)
+    ol)
+  "Overlay used to highlight the matching paren.")
+
+(defun blink-matching-open ()
+  "Momentarily highlight the beginning of the sexp before point."
+  (interactive)
+  (when (and (not (bobp))
+            blink-matching-paren)
+    (let* ((oldpos (point))
+          (message-log-max nil) ; Don't log messages about paren matching.
+          (blinkpos
+            (save-excursion
+              (save-restriction
+                (if blink-matching-paren-distance
+                    (narrow-to-region
+                     (max (minibuffer-prompt-end) ;(point-min) unless minibuf.
+                          (- (point) blink-matching-paren-distance))
+                     oldpos))
+                (let ((parse-sexp-ignore-comments
+                       (and parse-sexp-ignore-comments
+                            (not blink-matching-paren-dont-ignore-comments))))
+                  (condition-case ()
+                      (progn
+                        (forward-sexp -1)
+                        ;; backward-sexp skips backward over prefix chars,
+                        ;; so move back to the matching paren.
+                        (while (and (< (point) (1- oldpos))
+                                    (let ((code (syntax-after (point))))
+                                      (or (eq (syntax-class code) 6)
+                                          (eq (logand 1048576 (car code))
+                                              1048576))))
+                          (forward-char 1))
+                        (point))
+                    (error nil))))))
+           (mismatch (funcall blink-matching-check-function blinkpos oldpos)))
+      (cond
+       (mismatch
+        (if blinkpos
+            (if (minibufferp)
+                (minibuffer-message "Mismatched parentheses")
+              (message "Mismatched parentheses"))
+          (if (minibufferp)
+              (minibuffer-message "No matching parenthesis found")
+            (message "No matching parenthesis found"))))
+       ((not blinkpos) nil)
+       ((pos-visible-in-window-p blinkpos)
+        ;; Matching open within window, temporarily move to or highlight
+        ;; char after blinkpos but only if `blink-matching-paren-on-screen'
+        ;; is non-nil.
+        (and blink-matching-paren-on-screen
+             (not show-paren-mode)
+             (if (eq blink-matching-paren 'jump)
+                 (save-excursion
+                   (goto-char blinkpos)
+                   (sit-for blink-matching-delay))
+               (unwind-protect
+                   (progn
+                     (move-overlay blink-matching--overlay blinkpos (1+ 
blinkpos)
+                                   (current-buffer))
+                     (sit-for blink-matching-delay))
+                 (delete-overlay blink-matching--overlay)))))
+       (t
+        (save-excursion
+          (goto-char blinkpos)
+          (let ((open-paren-line-string
+                 ;; Show what precedes the open in its line, if anything.
+                 (cond
+                  ((save-excursion (skip-chars-backward " \t") (not (bolp)))
+                   (buffer-substring (line-beginning-position)
+                                     (1+ blinkpos)))
+                  ;; Show what follows the open in its line, if anything.
+                  ((save-excursion
+                     (forward-char 1)
+                     (skip-chars-forward " \t")
+                     (not (eolp)))
+                   (buffer-substring blinkpos
+                                     (line-end-position)))
+                  ;; Otherwise show the previous nonblank line,
+                  ;; if there is one.
+                  ((save-excursion (skip-chars-backward "\n \t") (not (bobp)))
+                   (concat
+                    (buffer-substring (progn
+                                        (skip-chars-backward "\n \t")
+                                        (line-beginning-position))
+                                      (progn (end-of-line)
+                                             (skip-chars-backward " \t")
+                                             (point)))
+                    ;; Replace the newline and other whitespace with `...'.
+                    "..."
+                    (buffer-substring blinkpos (1+ blinkpos))))
+                  ;; There is nothing to show except the char itself.
+                  (t (buffer-substring blinkpos (1+ blinkpos))))))
+            (message "Matches %s"
+                     (substring-no-properties open-paren-line-string)))))))))
+
+(defvar blink-paren-function 'blink-matching-open
+  "Function called, if non-nil, whenever a close parenthesis is inserted.
+More precisely, a char with closeparen syntax is self-inserted.")
+
+(defun blink-paren-post-self-insert-function ()
+  (when (and (eq (char-before) last-command-event) ; Sanity check.
+             (memq (char-syntax last-command-event) '(?\) ?\$))
+             blink-paren-function
+             (not executing-kbd-macro)
+             (not noninteractive)
+            ;; Verify an even number of quoting characters precede the close.
+            (= 1 (logand 1 (- (point)
+                              (save-excursion
+                                (forward-char -1)
+                                (skip-syntax-backward "/\\")
+                                (point))))))
+    (funcall blink-paren-function)))
+
+(put 'blink-paren-post-self-insert-function 'priority 100)
+
+(add-hook 'post-self-insert-hook #'blink-paren-post-self-insert-function
+          ;; Most likely, this hook is nil, so this arg doesn't matter,
+          ;; but I use it as a reminder that this function usually
+          ;; likes to be run after others since it does
+          ;; `sit-for'. That's also the reason it get a `priority' prop
+          ;; of 100.
+          'append)
+
+;; This executes C-g typed while Emacs is waiting for a command.
+;; Quitting out of a program does not go through here;
+;; that happens in the QUIT macro at the C code level.
+(defun keyboard-quit ()
+  "Signal a `quit' condition.
+During execution of Lisp code, this character causes a quit directly.
+At top-level, as an editor command, this simply beeps."
+  (interactive)
+  ;; Avoid adding the region to the window selection.
+  (setq saved-region-selection nil)
+  (let (select-active-regions)
+    (deactivate-mark))
+  (if (fboundp 'kmacro-keyboard-quit)
+      (kmacro-keyboard-quit))
+  ;; Force the next redisplay cycle to remove the "Def" indicator from
+  ;; all the mode lines.
+  (if defining-kbd-macro
+      (force-mode-line-update t))
+  (setq defining-kbd-macro nil)
+  (let ((debug-on-quit nil))
+    (signal 'quit nil)))
+
+(defvar buffer-quit-function nil
+  "Function to call to \"quit\" the current buffer, or nil if none.
+\\[keyboard-escape-quit] calls this function when its more local actions
+\(such as canceling a prefix argument, minibuffer or region) do not apply.")
+
+(defun keyboard-escape-quit ()
+  "Exit the current \"mode\" (in a generalized sense of the word).
+This command can exit an interactive command such as `query-replace',
+can clear out a prefix argument or a region,
+can get out of the minibuffer or other recursive edit,
+cancel the use of the current buffer (for special-purpose buffers),
+or go back to just one window (by deleting all but the selected window)."
+  (interactive)
+  (cond ((eq last-command 'mode-exited) nil)
+       ((region-active-p)
+        (deactivate-mark))
+       ((> (minibuffer-depth) 0)
+        (abort-recursive-edit))
+       (current-prefix-arg
+        nil)
+       ((> (recursion-depth) 0)
+        (exit-recursive-edit))
+       (buffer-quit-function
+        (funcall buffer-quit-function))
+       ((not (one-window-p t))
+        (delete-other-windows))
+       ((string-match "^ \\*" (buffer-name (current-buffer)))
+        (bury-buffer))))
+
+(defun play-sound-file (file &optional volume device)
+  "Play sound stored in FILE.
+VOLUME and DEVICE correspond to the keywords of the sound
+specification for `play-sound'."
+  (interactive "fPlay sound file: ")
+  (let ((sound (list :file file)))
+    (if volume
+       (plist-put sound :volume volume))
+    (if device
+       (plist-put sound :device device))
+    (push 'sound sound)
+    (play-sound sound)))
+
+
+(defcustom read-mail-command 'rmail
+  "Your preference for a mail reading package.
+This is used by some keybindings which support reading mail.
+See also `mail-user-agent' concerning sending mail."
+  :type '(radio (function-item :tag "Rmail" :format "%t\n" rmail)
+                (function-item :tag "Gnus" :format "%t\n" gnus)
+                (function-item :tag "Emacs interface to MH"
+                               :format "%t\n" mh-rmail)
+                (function :tag "Other"))
+  :version "21.1"
+  :group 'mail)
+
+(defcustom mail-user-agent 'message-user-agent
+  "Your preference for a mail composition package.
+Various Emacs Lisp packages (e.g. Reporter) require you to compose an
+outgoing email message.  This variable lets you specify which
+mail-sending package you prefer.
+
+Valid values include:
+
+  `message-user-agent'  -- use the Message package.
+                           See Info node `(message)'.
+  `sendmail-user-agent' -- use the Mail package.
+                           See Info node `(emacs)Sending Mail'.
+  `mh-e-user-agent'     -- use the Emacs interface to the MH mail system.
+                           See Info node `(mh-e)'.
+  `gnus-user-agent'     -- like `message-user-agent', but with Gnus
+                           paraphernalia if Gnus is running, particularly
+                           the Gcc: header for archiving.
+
+Additional valid symbols may be available; check with the author of
+your package for details.  The function should return non-nil if it
+succeeds.
+
+See also `read-mail-command' concerning reading mail."
+  :type '(radio (function-item :tag "Message package"
+                              :format "%t\n"
+                              message-user-agent)
+               (function-item :tag "Mail package"
+                              :format "%t\n"
+                              sendmail-user-agent)
+               (function-item :tag "Emacs interface to MH"
+                              :format "%t\n"
+                              mh-e-user-agent)
+               (function-item :tag "Message with full Gnus features"
+                              :format "%t\n"
+                              gnus-user-agent)
+               (function :tag "Other"))
+  :version "23.2"                       ; sendmail->message
+  :group 'mail)
+
+(defcustom compose-mail-user-agent-warnings t
+  "If non-nil, `compose-mail' warns about changes in `mail-user-agent'.
+If the value of `mail-user-agent' is the default, and the user
+appears to have customizations applying to the old default,
+`compose-mail' issues a warning."
+  :type 'boolean
+  :version "23.2"
+  :group 'mail)
+
+(defun rfc822-goto-eoh ()
+  "If the buffer starts with a mail header, move point to the header's end.
+Otherwise, moves to `point-min'.
+The end of the header is the start of the next line, if there is one,
+else the end of the last line.  This function obeys RFC822."
+  (goto-char (point-min))
+  (when (re-search-forward
+        "^\\([:\n]\\|[^: \t\n]+[ \t\n]\\)" nil 'move)
+    (goto-char (match-beginning 0))))
+
+;; Used by Rmail (e.g., rmail-forward).
+(defvar mail-encode-mml nil
+  "If non-nil, mail-user-agent's `sendfunc' command should mml-encode
+the outgoing message before sending it.")
+
+(defun compose-mail (&optional to subject other-headers continue
+                    switch-function yank-action send-actions
+                    return-action)
+  "Start composing a mail message to send.
+This uses the user's chosen mail composition package
+as selected with the variable `mail-user-agent'.
+The optional arguments TO and SUBJECT specify recipients
+and the initial Subject field, respectively.
+
+OTHER-HEADERS is an alist specifying additional
+header fields.  Elements look like (HEADER . VALUE) where both
+HEADER and VALUE are strings.
+
+CONTINUE, if non-nil, says to continue editing a message already
+being composed.  Interactively, CONTINUE is the prefix argument.
+
+SWITCH-FUNCTION, if non-nil, is a function to use to
+switch to and display the buffer used for mail composition.
+
+YANK-ACTION, if non-nil, is an action to perform, if and when necessary,
+to insert the raw text of the message being replied to.
+It has the form (FUNCTION . ARGS).  The user agent will apply
+FUNCTION to ARGS, to insert the raw text of the original message.
+\(The user agent will also run `mail-citation-hook', *after* the
+original text has been inserted in this way.)
+
+SEND-ACTIONS is a list of actions to call when the message is sent.
+Each action has the form (FUNCTION . ARGS).
+
+RETURN-ACTION, if non-nil, is an action for returning to the
+caller.  It has the form (FUNCTION . ARGS).  The function is
+called after the mail has been sent or put aside, and the mail
+buffer buried."
+  (interactive
+   (list nil nil nil current-prefix-arg))
+
+  ;; In Emacs 23.2, the default value of `mail-user-agent' changed
+  ;; from sendmail-user-agent to message-user-agent.  Some users may
+  ;; encounter incompatibilities.  This hack tries to detect problems
+  ;; and warn about them.
+  (and compose-mail-user-agent-warnings
+       (eq mail-user-agent 'message-user-agent)
+       (let (warn-vars)
+        (dolist (var '(mail-mode-hook mail-send-hook mail-setup-hook
+                       mail-yank-hooks mail-archive-file-name
+                       mail-default-reply-to mail-mailing-lists
+                       mail-self-blind))
+          (and (boundp var)
+               (symbol-value var)
+               (push var warn-vars)))
+        (when warn-vars
+          (display-warning 'mail
+                           (format "\
+The default mail mode is now Message mode.
+You have the following Mail mode variable%s customized:
+\n  %s\n\nTo use Mail mode, set `mail-user-agent' to sendmail-user-agent.
+To disable this warning, set `compose-mail-user-agent-warnings' to nil."
+                                   (if (> (length warn-vars) 1) "s" "")
+                                   (mapconcat 'symbol-name
+                                              warn-vars " "))))))
+
+  (let ((function (get mail-user-agent 'composefunc)))
+    (funcall function to subject other-headers continue switch-function
+            yank-action send-actions return-action)))
+
+(defun compose-mail-other-window (&optional to subject other-headers continue
+                                           yank-action send-actions
+                                           return-action)
+  "Like \\[compose-mail], but edit the outgoing message in another window."
+  (interactive (list nil nil nil current-prefix-arg))
+  (compose-mail to subject other-headers continue
+               'switch-to-buffer-other-window yank-action send-actions
+               return-action))
+
+(defun compose-mail-other-frame (&optional to subject other-headers continue
+                                           yank-action send-actions
+                                           return-action)
+  "Like \\[compose-mail], but edit the outgoing message in another frame."
+  (interactive (list nil nil nil current-prefix-arg))
+  (compose-mail to subject other-headers continue
+               'switch-to-buffer-other-frame yank-action send-actions
+               return-action))
+
+
+(defvar set-variable-value-history nil
+  "History of values entered with `set-variable'.
+
+Maximum length of the history list is determined by the value
+of `history-length', which see.")
+
+(defun set-variable (variable value &optional make-local)
+  "Set VARIABLE to VALUE.  VALUE is a Lisp object.
+VARIABLE should be a user option variable name, a Lisp variable
+meant to be customized by users.  You should enter VALUE in Lisp syntax,
+so if you want VALUE to be a string, you must surround it with doublequotes.
+VALUE is used literally, not evaluated.
+
+If VARIABLE has a `variable-interactive' property, that is used as if
+it were the arg to `interactive' (which see) to interactively read VALUE.
+
+If VARIABLE has been defined with `defcustom', then the type information
+in the definition is used to check that VALUE is valid.
+
+With a prefix argument, set VARIABLE to VALUE buffer-locally."
+  (interactive
+   (let* ((default-var (variable-at-point))
+          (var (if (custom-variable-p default-var)
+                  (read-variable (format "Set variable (default %s): " 
default-var)
+                                 default-var)
+                (read-variable "Set variable: ")))
+         (minibuffer-help-form '(describe-variable var))
+         (prop (get var 'variable-interactive))
+          (obsolete (car (get var 'byte-obsolete-variable)))
+         (prompt (format "Set %s %s to value: " var
+                         (cond ((local-variable-p var)
+                                "(buffer-local)")
+                               ((or current-prefix-arg
+                                    (local-variable-if-set-p var))
+                                "buffer-locally")
+                               (t "globally"))))
+         (val (progn
+                 (when obsolete
+                   (message (concat "`%S' is obsolete; "
+                                    (if (symbolp obsolete) "use `%S' instead" 
"%s"))
+                            var obsolete)
+                   (sit-for 3))
+                 (if prop
+                     ;; Use VAR's `variable-interactive' property
+                     ;; as an interactive spec for prompting.
+                     (call-interactively `(lambda (arg)
+                                            (interactive ,prop)
+                                            arg))
+                   (read-from-minibuffer prompt nil
+                                         read-expression-map t
+                                         'set-variable-value-history
+                                         (format "%S" (symbol-value var)))))))
+     (list var val current-prefix-arg)))
+
+  (and (custom-variable-p variable)
+       (not (get variable 'custom-type))
+       (custom-load-symbol variable))
+  (let ((type (get variable 'custom-type)))
+    (when type
+      ;; Match with custom type.
+      (require 'cus-edit)
+      (setq type (widget-convert type))
+      (unless (widget-apply type :match value)
+       (error "Value `%S' does not match type %S of %S"
+              value (car type) variable))))
+
+  (if make-local
+      (make-local-variable variable))
+
+  (set variable value)
+
+  ;; Force a thorough redisplay for the case that the variable
+  ;; has an effect on the display, like `tab-width' has.
+  (force-mode-line-update))
+
+;; Define the major mode for lists of completions.
+
+(defvar completion-list-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map [mouse-2] 'choose-completion)
+    (define-key map [follow-link] 'mouse-face)
+    (define-key map [down-mouse-2] nil)
+    (define-key map "\C-m" 'choose-completion)
+    (define-key map "\e\e\e" 'delete-completion-window)
+    (define-key map [left] 'previous-completion)
+    (define-key map [right] 'next-completion)
+    (define-key map "q" 'quit-window)
+    (define-key map "z" 'kill-this-buffer)
+    map)
+  "Local map for completion list buffers.")
+
+;; Completion mode is suitable only for specially formatted data.
+(put 'completion-list-mode 'mode-class 'special)
+
+(defvar completion-reference-buffer nil
+  "Record the buffer that was current when the completion list was requested.
+This is a local variable in the completion list buffer.
+Initial value is nil to avoid some compiler warnings.")
+
+(defvar completion-no-auto-exit nil
+  "Non-nil means `choose-completion-string' should never exit the minibuffer.
+This also applies to other functions such as `choose-completion'.")
+
+(defvar completion-base-position nil
+  "Position of the base of the text corresponding to the shown completions.
+This variable is used in the *Completions* buffers.
+Its value is a list of the form (START END) where START is the place
+where the completion should be inserted and END (if non-nil) is the end
+of the text to replace.  If END is nil, point is used instead.")
+
+(defvar completion-list-insert-choice-function #'completion--replace
+  "Function to use to insert the text chosen in *Completions*.
+Called with three arguments (BEG END TEXT), it should replace the text
+between BEG and END with TEXT.  Expected to be set buffer-locally
+in the *Completions* buffer.")
+
+(defvar completion-base-size nil
+  "Number of chars before point not involved in completion.
+This is a local variable in the completion list buffer.
+It refers to the chars in the minibuffer if completing in the
+minibuffer, or in `completion-reference-buffer' otherwise.
+Only characters in the field at point are included.
+
+If nil, Emacs determines which part of the tail end of the
+buffer's text is involved in completion by comparing the text
+directly.")
+(make-obsolete-variable 'completion-base-size 'completion-base-position "23.2")
+
+(defun delete-completion-window ()
+  "Delete the completion list window.
+Go to the window from which completion was requested."
+  (interactive)
+  (let ((buf completion-reference-buffer))
+    (if (one-window-p t)
+       (if (window-dedicated-p) (delete-frame))
+      (delete-window (selected-window))
+      (if (get-buffer-window buf)
+         (select-window (get-buffer-window buf))))))
+
+(defun previous-completion (n)
+  "Move to the previous item in the completion list."
+  (interactive "p")
+  (next-completion (- n)))
+
+(defun next-completion (n)
+  "Move to the next item in the completion list.
+With prefix argument N, move N items (negative N means move backward)."
+  (interactive "p")
+  (let ((beg (point-min)) (end (point-max)))
+    (while (and (> n 0) (not (eobp)))
+      ;; If in a completion, move to the end of it.
+      (when (get-text-property (point) 'mouse-face)
+       (goto-char (next-single-property-change (point) 'mouse-face nil end)))
+      ;; Move to start of next one.
+      (unless (get-text-property (point) 'mouse-face)
+       (goto-char (next-single-property-change (point) 'mouse-face nil end)))
+      (setq n (1- n)))
+    (while (and (< n 0) (not (bobp)))
+      (let ((prop (get-text-property (1- (point)) 'mouse-face)))
+       ;; If in a completion, move to the start of it.
+       (when (and prop (eq prop (get-text-property (point) 'mouse-face)))
+         (goto-char (previous-single-property-change
+                     (point) 'mouse-face nil beg)))
+       ;; Move to end of the previous completion.
+       (unless (or (bobp) (get-text-property (1- (point)) 'mouse-face))
+         (goto-char (previous-single-property-change
+                     (point) 'mouse-face nil beg)))
+       ;; Move to the start of that one.
+       (goto-char (previous-single-property-change
+                   (point) 'mouse-face nil beg))
+       (setq n (1+ n))))))
+
+(defun choose-completion (&optional event)
+  "Choose the completion at point.
+If EVENT, use EVENT's position to determine the starting position."
+  (interactive (list last-nonmenu-event))
+  ;; In case this is run via the mouse, give temporary modes such as
+  ;; isearch a chance to turn off.
+  (run-hooks 'mouse-leave-buffer-hook)
+  (with-current-buffer (window-buffer (posn-window (event-start event)))
+    (let ((buffer completion-reference-buffer)
+          (base-size completion-base-size)
+          (base-position completion-base-position)
+          (insert-function completion-list-insert-choice-function)
+          (choice
+           (save-excursion
+             (goto-char (posn-point (event-start event)))
+             (let (beg end)
+               (cond
+                ((and (not (eobp)) (get-text-property (point) 'mouse-face))
+                 (setq end (point) beg (1+ (point))))
+                ((and (not (bobp))
+                      (get-text-property (1- (point)) 'mouse-face))
+                 (setq end (1- (point)) beg (point)))
+                (t (error "No completion here")))
+               (setq beg (previous-single-property-change beg 'mouse-face))
+               (setq end (or (next-single-property-change end 'mouse-face)
+                             (point-max)))
+               (buffer-substring-no-properties beg end)))))
+
+      (unless (buffer-live-p buffer)
+        (error "Destination buffer is dead"))
+      (quit-window nil (posn-window (event-start event)))
+
+      (with-current-buffer buffer
+        (choose-completion-string
+         choice buffer
+         (or base-position
+             (when base-size
+               ;; Someone's using old completion code that doesn't know
+               ;; about base-position yet.
+               (list (+ base-size (field-beginning))))
+             ;; If all else fails, just guess.
+             (list (choose-completion-guess-base-position choice)))
+         insert-function)))))
+
+;; Delete the longest partial match for STRING
+;; that can be found before POINT.
+(defun choose-completion-guess-base-position (string)
+  (save-excursion
+    (let ((opoint (point))
+          len)
+      ;; Try moving back by the length of the string.
+      (goto-char (max (- (point) (length string))
+                      (minibuffer-prompt-end)))
+      ;; See how far back we were actually able to move.  That is the
+      ;; upper bound on how much we can match and delete.
+      (setq len (- opoint (point)))
+      (if completion-ignore-case
+          (setq string (downcase string)))
+      (while (and (> len 0)
+                  (let ((tail (buffer-substring (point) opoint)))
+                    (if completion-ignore-case
+                        (setq tail (downcase tail)))
+                    (not (string= tail (substring string 0 len)))))
+        (setq len (1- len))
+        (forward-char 1))
+      (point))))
+
+(defun choose-completion-delete-max-match (string)
+  (declare (obsolete choose-completion-guess-base-position "23.2"))
+  (delete-region (choose-completion-guess-base-position string) (point)))
+
+(defvar choose-completion-string-functions nil
+  "Functions that may override the normal insertion of a completion choice.
+These functions are called in order with three arguments:
+CHOICE - the string to insert in the buffer,
+BUFFER - the buffer in which the choice should be inserted,
+BASE-POSITION - where to insert the completion.
+
+If a function in the list returns non-nil, that function is supposed
+to have inserted the CHOICE in the BUFFER, and possibly exited
+the minibuffer; no further functions will be called.
+
+If all functions in the list return nil, that means to use
+the default method of inserting the completion in BUFFER.")
+
+(defun choose-completion-string (choice &optional
+                                        buffer base-position insert-function)
+  "Switch to BUFFER and insert the completion choice CHOICE.
+BASE-POSITION says where to insert the completion.
+INSERT-FUNCTION says how to insert the completion and falls
+back on `completion-list-insert-choice-function' when nil."
+
+  ;; If BUFFER is the minibuffer, exit the minibuffer
+  ;; unless it is reading a file name and CHOICE is a directory,
+  ;; or completion-no-auto-exit is non-nil.
+
+  ;; Some older code may call us passing `base-size' instead of
+  ;; `base-position'.  It's difficult to make any use of `base-size',
+  ;; so we just ignore it.
+  (unless (consp base-position)
+    (message "Obsolete `base-size' passed to choose-completion-string")
+    (setq base-position nil))
+
+  (let* ((buffer (or buffer completion-reference-buffer))
+        (mini-p (minibufferp buffer)))
+    ;; If BUFFER is a minibuffer, barf unless it's the currently
+    ;; active minibuffer.
+    (if (and mini-p
+             (not (and (active-minibuffer-window)
+                       (equal buffer
+                            (window-buffer (active-minibuffer-window))))))
+       (error "Minibuffer is not active for completion")
+      ;; Set buffer so buffer-local choose-completion-string-functions works.
+      (set-buffer buffer)
+      (unless (run-hook-with-args-until-success
+              'choose-completion-string-functions
+               ;; The fourth arg used to be `mini-p' but was useless
+               ;; (since minibufferp can be used on the `buffer' arg)
+               ;; and indeed unused.  The last used to be `base-size', so we
+               ;; keep it to try and avoid breaking old code.
+              choice buffer base-position nil)
+        ;; This remove-text-properties should be unnecessary since `choice'
+        ;; comes from buffer-substring-no-properties.
+        ;;(remove-text-properties 0 (length choice) '(mouse-face nil) choice)
+       ;; Insert the completion into the buffer where it was requested.
+        (funcall (or insert-function completion-list-insert-choice-function)
+                 (or (car base-position) (point))
+                 (or (cadr base-position) (point))
+                 choice)
+        ;; Update point in the window that BUFFER is showing in.
+       (let ((window (get-buffer-window buffer t)))
+         (set-window-point window (point)))
+       ;; If completing for the minibuffer, exit it with this choice.
+       (and (not completion-no-auto-exit)
+             (minibufferp buffer)
+            minibuffer-completion-table
+            ;; If this is reading a file name, and the file name chosen
+            ;; is a directory, don't exit the minibuffer.
+             (let* ((result (buffer-substring (field-beginning) (point)))
+                    (bounds
+                     (completion-boundaries result minibuffer-completion-table
+                                            minibuffer-completion-predicate
+                                            "")))
+               (if (eq (car bounds) (length result))
+                   ;; The completion chosen leads to a new set of completions
+                   ;; (e.g. it's a directory): don't exit the minibuffer yet.
+                   (let ((mini (active-minibuffer-window)))
+                     (select-window mini)
+                     (when minibuffer-auto-raise
+                       (raise-frame (window-frame mini))))
+                 (exit-minibuffer))))))))
+
+(define-derived-mode completion-list-mode nil "Completion List"
+  "Major mode for buffers showing lists of possible completions.
+Type \\<completion-list-mode-map>\\[choose-completion] in the completion list\
+ to select the completion near point.
+Or click to select one with the mouse.
+
+\\{completion-list-mode-map}"
+  (set (make-local-variable 'completion-base-size) nil))
+
+(defun completion-list-mode-finish ()
+  "Finish setup of the completions buffer.
+Called from `temp-buffer-show-hook'."
+  (when (eq major-mode 'completion-list-mode)
+    (setq buffer-read-only t)))
+
+(add-hook 'temp-buffer-show-hook 'completion-list-mode-finish)
+
+
+;; Variables and faces used in `completion-setup-function'.
+
+(defcustom completion-show-help t
+  "Non-nil means show help message in *Completions* buffer."
+  :type 'boolean
+  :version "22.1"
+  :group 'completion)
+
+;; This function goes in completion-setup-hook, so that it is called
+;; after the text of the completion list buffer is written.
+(defun completion-setup-function ()
+  (let* ((mainbuf (current-buffer))
+         (base-dir
+          ;; FIXME: This is a bad hack.  We try to set the default-directory
+          ;; in the *Completions* buffer so that the relative file names
+          ;; displayed there can be treated as valid file names, independently
+          ;; from the completion context.  But this suffers from many problems:
+          ;; - It's not clear when the completions are file names.  With some
+          ;;   completion tables (e.g. bzr revision specs), the listed
+          ;;   completions can mix file names and other things.
+          ;; - It doesn't pay attention to possible quoting.
+          ;; - With fancy completion styles, the code below will not always
+          ;;   find the right base directory.
+          (if minibuffer-completing-file-name
+              (file-name-as-directory
+               (expand-file-name
+                (buffer-substring (minibuffer-prompt-end)
+                                  (- (point) (or completion-base-size 0))))))))
+    (with-current-buffer standard-output
+      (let ((base-size completion-base-size) ;Read before killing localvars.
+            (base-position completion-base-position)
+            (insert-fun completion-list-insert-choice-function))
+        (completion-list-mode)
+        (set (make-local-variable 'completion-base-size) base-size)
+        (set (make-local-variable 'completion-base-position) base-position)
+        (set (make-local-variable 'completion-list-insert-choice-function)
+            insert-fun))
+      (set (make-local-variable 'completion-reference-buffer) mainbuf)
+      (if base-dir (setq default-directory base-dir))
+      ;; Maybe insert help string.
+      (when completion-show-help
+       (goto-char (point-min))
+       (if (display-mouse-p)
+           (insert (substitute-command-keys
+                    "Click on a completion to select it.\n")))
+       (insert (substitute-command-keys
+                "In this buffer, type \\[choose-completion] to \
+select the completion near point.\n\n"))))))
+
+(add-hook 'completion-setup-hook 'completion-setup-function)
+
+(define-key minibuffer-local-completion-map [prior] 'switch-to-completions)
+(define-key minibuffer-local-completion-map "\M-v"  'switch-to-completions)
+
+(defun switch-to-completions ()
+  "Select the completion list window."
+  (interactive)
+  (let ((window (or (get-buffer-window "*Completions*" 0)
+                   ;; Make sure we have a completions window.
+                    (progn (minibuffer-completion-help)
+                           (get-buffer-window "*Completions*" 0)))))
+    (when window
+      (select-window window)
+      ;; In the new buffer, go to the first completion.
+      ;; FIXME: Perhaps this should be done in `minibuffer-completion-help'.
+      (when (bobp)
+       (next-completion 1)))))
+
+;;; Support keyboard commands to turn on various modifiers.
+
+;; These functions -- which are not commands -- each add one modifier
+;; to the following event.
+
+(defun event-apply-alt-modifier (_ignore-prompt)
+  "\\<function-key-map>Add the Alt modifier to the following event.
+For example, type \\[event-apply-alt-modifier] & to enter Alt-&."
+  (vector (event-apply-modifier (read-event) 'alt 22 "A-")))
+(defun event-apply-super-modifier (_ignore-prompt)
+  "\\<function-key-map>Add the Super modifier to the following event.
+For example, type \\[event-apply-super-modifier] & to enter Super-&."
+  (vector (event-apply-modifier (read-event) 'super 23 "s-")))
+(defun event-apply-hyper-modifier (_ignore-prompt)
+  "\\<function-key-map>Add the Hyper modifier to the following event.
+For example, type \\[event-apply-hyper-modifier] & to enter Hyper-&."
+  (vector (event-apply-modifier (read-event) 'hyper 24 "H-")))
+(defun event-apply-shift-modifier (_ignore-prompt)
+  "\\<function-key-map>Add the Shift modifier to the following event.
+For example, type \\[event-apply-shift-modifier] & to enter Shift-&."
+  (vector (event-apply-modifier (read-event) 'shift 25 "S-")))
+(defun event-apply-control-modifier (_ignore-prompt)
+  "\\<function-key-map>Add the Ctrl modifier to the following event.
+For example, type \\[event-apply-control-modifier] & to enter Ctrl-&."
+  (vector (event-apply-modifier (read-event) 'control 26 "C-")))
+(defun event-apply-meta-modifier (_ignore-prompt)
+  "\\<function-key-map>Add the Meta modifier to the following event.
+For example, type \\[event-apply-meta-modifier] & to enter Meta-&."
+  (vector (event-apply-modifier (read-event) 'meta 27 "M-")))
+
+(defun event-apply-modifier (event symbol lshiftby prefix)
+  "Apply a modifier flag to event EVENT.
+SYMBOL is the name of this modifier, as a symbol.
+LSHIFTBY is the numeric value of this modifier, in keyboard events.
+PREFIX is the string that represents this modifier in an event type symbol."
+  (if (numberp event)
+      (cond ((eq symbol 'control)
+            (if (and (<= (downcase event) ?z)
+                     (>= (downcase event) ?a))
+                (- (downcase event) ?a -1)
+              (if (and (<= (downcase event) ?Z)
+                       (>= (downcase event) ?A))
+                  (- (downcase event) ?A -1)
+                (logior (lsh 1 lshiftby) event))))
+           ((eq symbol 'shift)
+            (if (and (<= (downcase event) ?z)
+                     (>= (downcase event) ?a))
+                (upcase event)
+              (logior (lsh 1 lshiftby) event)))
+           (t
+            (logior (lsh 1 lshiftby) event)))
+    (if (memq symbol (event-modifiers event))
+       event
+      (let ((event-type (if (symbolp event) event (car event))))
+       (setq event-type (intern (concat prefix (symbol-name event-type))))
+       (if (symbolp event)
+           event-type
+         (cons event-type (cdr event)))))))
+
+(define-key function-key-map [?\C-x ?@ ?h] 'event-apply-hyper-modifier)
+(define-key function-key-map [?\C-x ?@ ?s] 'event-apply-super-modifier)
+(define-key function-key-map [?\C-x ?@ ?m] 'event-apply-meta-modifier)
+(define-key function-key-map [?\C-x ?@ ?a] 'event-apply-alt-modifier)
+(define-key function-key-map [?\C-x ?@ ?S] 'event-apply-shift-modifier)
+(define-key function-key-map [?\C-x ?@ ?c] 'event-apply-control-modifier)
+
+;;;; Keypad support.
+
+;; Make the keypad keys act like ordinary typing keys.  If people add
+;; bindings for the function key symbols, then those bindings will
+;; override these, so this shouldn't interfere with any existing
+;; bindings.
+
+;; Also tell read-char how to handle these keys.
+(mapc
+ (lambda (keypad-normal)
+   (let ((keypad (nth 0 keypad-normal))
+        (normal (nth 1 keypad-normal)))
+     (put keypad 'ascii-character normal)
+     (define-key function-key-map (vector keypad) (vector normal))))
+ ;; See also kp-keys bound in bindings.el.
+ '((kp-space ?\s)
+   (kp-tab ?\t)
+   (kp-enter ?\r)
+   (kp-separator ?,)
+   (kp-equal ?=)
+   ;; Do the same for various keys that are represented as symbols under
+   ;; GUIs but naturally correspond to characters.
+   (backspace 127)
+   (delete 127)
+   (tab ?\t)
+   (linefeed ?\n)
+   (clear ?\C-l)
+   (return ?\C-m)
+   (escape ?\e)
+   ))
+
+;;;;
+;;;; forking a twin copy of a buffer.
+;;;;
+
+(defvar clone-buffer-hook nil
+  "Normal hook to run in the new buffer at the end of `clone-buffer'.")
+
+(defvar clone-indirect-buffer-hook nil
+  "Normal hook to run in the new buffer at the end of 
`clone-indirect-buffer'.")
+
+(defun clone-process (process &optional newname)
+  "Create a twin copy of PROCESS.
+If NEWNAME is nil, it defaults to PROCESS' name;
+NEWNAME is modified by adding or incrementing <N> at the end as necessary.
+If PROCESS is associated with a buffer, the new process will be associated
+  with the current buffer instead.
+Returns nil if PROCESS has already terminated."
+  (setq newname (or newname (process-name process)))
+  (if (string-match "<[0-9]+>\\'" newname)
+      (setq newname (substring newname 0 (match-beginning 0))))
+  (when (memq (process-status process) '(run stop open))
+    (let* ((process-connection-type (process-tty-name process))
+          (new-process
+           (if (memq (process-status process) '(open))
+               (let ((args (process-contact process t)))
+                 (setq args (plist-put args :name newname))
+                 (setq args (plist-put args :buffer
+                                       (if (process-buffer process)
+                                           (current-buffer))))
+                 (apply 'make-network-process args))
+             (apply 'start-process newname
+                    (if (process-buffer process) (current-buffer))
+                    (process-command process)))))
+      (set-process-query-on-exit-flag
+       new-process (process-query-on-exit-flag process))
+      (set-process-inherit-coding-system-flag
+       new-process (process-inherit-coding-system-flag process))
+      (set-process-filter new-process (process-filter process))
+      (set-process-sentinel new-process (process-sentinel process))
+      (set-process-plist new-process (copy-sequence (process-plist process)))
+      new-process)))
+
+;; things to maybe add (currently partly covered by `funcall mode'):
+;; - syntax-table
+;; - overlays
+(defun clone-buffer (&optional newname display-flag)
+  "Create and return a twin copy of the current buffer.
+Unlike an indirect buffer, the new buffer can be edited
+independently of the old one (if it is not read-only).
+NEWNAME is the name of the new buffer.  It may be modified by
+adding or incrementing <N> at the end as necessary to create a
+unique buffer name.  If nil, it defaults to the name of the
+current buffer, with the proper suffix.  If DISPLAY-FLAG is
+non-nil, the new buffer is shown with `pop-to-buffer'.  Trying to
+clone a file-visiting buffer, or a buffer whose major mode symbol
+has a non-nil `no-clone' property, results in an error.
+
+Interactively, DISPLAY-FLAG is t and NEWNAME is the name of the
+current buffer with appropriate suffix.  However, if a prefix
+argument is given, then the command prompts for NEWNAME in the
+minibuffer.
+
+This runs the normal hook `clone-buffer-hook' in the new buffer
+after it has been set up properly in other respects."
+  (interactive
+   (progn
+     (if buffer-file-name
+        (error "Cannot clone a file-visiting buffer"))
+     (if (get major-mode 'no-clone)
+        (error "Cannot clone a buffer in %s mode" mode-name))
+     (list (if current-prefix-arg
+              (read-buffer "Name of new cloned buffer: " (current-buffer)))
+          t)))
+  (if buffer-file-name
+      (error "Cannot clone a file-visiting buffer"))
+  (if (get major-mode 'no-clone)
+      (error "Cannot clone a buffer in %s mode" mode-name))
+  (setq newname (or newname (buffer-name)))
+  (if (string-match "<[0-9]+>\\'" newname)
+      (setq newname (substring newname 0 (match-beginning 0))))
+  (let ((buf (current-buffer))
+       (ptmin (point-min))
+       (ptmax (point-max))
+       (pt (point))
+       (mk (if mark-active (mark t)))
+       (modified (buffer-modified-p))
+       (mode major-mode)
+       (lvars (buffer-local-variables))
+       (process (get-buffer-process (current-buffer)))
+       (new (generate-new-buffer (or newname (buffer-name)))))
+    (save-restriction
+      (widen)
+      (with-current-buffer new
+       (insert-buffer-substring buf)))
+    (with-current-buffer new
+      (narrow-to-region ptmin ptmax)
+      (goto-char pt)
+      (if mk (set-mark mk))
+      (set-buffer-modified-p modified)
+
+      ;; Clone the old buffer's process, if any.
+      (when process (clone-process process))
+
+      ;; Now set up the major mode.
+      (funcall mode)
+
+      ;; Set up other local variables.
+      (mapc (lambda (v)
+             (condition-case ()        ;in case var is read-only
+                 (if (symbolp v)
+                     (makunbound v)
+                   (set (make-local-variable (car v)) (cdr v)))
+               (error nil)))
+           lvars)
+
+      ;; Run any hooks (typically set up by the major mode
+      ;; for cloning to work properly).
+      (run-hooks 'clone-buffer-hook))
+    (if display-flag
+        ;; Presumably the current buffer is shown in the selected frame, so
+        ;; we want to display the clone elsewhere.
+        (let ((same-window-regexps nil)
+              (same-window-buffer-names))
+          (pop-to-buffer new)))
+    new))
+
+
+(defun clone-indirect-buffer (newname display-flag &optional norecord)
+  "Create an indirect buffer that is a twin copy of the current buffer.
+
+Give the indirect buffer name NEWNAME.  Interactively, read NEWNAME
+from the minibuffer when invoked with a prefix arg.  If NEWNAME is nil
+or if not called with a prefix arg, NEWNAME defaults to the current
+buffer's name.  The name is modified by adding a `<N>' suffix to it
+or by incrementing the N in an existing suffix.  Trying to clone a
+buffer whose major mode symbol has a non-nil `no-clone-indirect'
+property results in an error.
+
+DISPLAY-FLAG non-nil means show the new buffer with `pop-to-buffer'.
+This is always done when called interactively.
+
+Optional third arg NORECORD non-nil means do not put this buffer at the
+front of the list of recently selected ones."
+  (interactive
+   (progn
+     (if (get major-mode 'no-clone-indirect)
+        (error "Cannot indirectly clone a buffer in %s mode" mode-name))
+     (list (if current-prefix-arg
+              (read-buffer "Name of indirect buffer: " (current-buffer)))
+          t)))
+  (if (get major-mode 'no-clone-indirect)
+      (error "Cannot indirectly clone a buffer in %s mode" mode-name))
+  (setq newname (or newname (buffer-name)))
+  (if (string-match "<[0-9]+>\\'" newname)
+      (setq newname (substring newname 0 (match-beginning 0))))
+  (let* ((name (generate-new-buffer-name newname))
+        (buffer (make-indirect-buffer (current-buffer) name t)))
+    (with-current-buffer buffer
+      (run-hooks 'clone-indirect-buffer-hook))
+    (when display-flag
+      (pop-to-buffer buffer norecord))
+    buffer))
+
+
+(defun clone-indirect-buffer-other-window (newname display-flag &optional 
norecord)
+  "Like `clone-indirect-buffer' but display in another window."
+  (interactive
+   (progn
+     (if (get major-mode 'no-clone-indirect)
+        (error "Cannot indirectly clone a buffer in %s mode" mode-name))
+     (list (if current-prefix-arg
+              (read-buffer "Name of indirect buffer: " (current-buffer)))
+          t)))
+  (let ((pop-up-windows t))
+    (clone-indirect-buffer newname display-flag norecord)))
+
+
+;;; Handling of Backspace and Delete keys.
+
+(defcustom normal-erase-is-backspace 'maybe
+  "Set the default behavior of the Delete and Backspace keys.
+
+If set to t, Delete key deletes forward and Backspace key deletes
+backward.
+
+If set to nil, both Delete and Backspace keys delete backward.
+
+If set to 'maybe (which is the default), Emacs automatically
+selects a behavior.  On window systems, the behavior depends on
+the keyboard used.  If the keyboard has both a Backspace key and
+a Delete key, and both are mapped to their usual meanings, the
+option's default value is set to t, so that Backspace can be used
+to delete backward, and Delete can be used to delete forward.
+
+If not running under a window system, customizing this option
+accomplishes a similar effect by mapping C-h, which is usually
+generated by the Backspace key, to DEL, and by mapping DEL to C-d
+via `keyboard-translate'.  The former functionality of C-h is
+available on the F1 key.  You should probably not use this
+setting if you don't have both Backspace, Delete and F1 keys.
+
+Setting this variable with setq doesn't take effect.  Programmatically,
+call `normal-erase-is-backspace-mode' (which see) instead."
+  :type '(choice (const :tag "Off" nil)
+                (const :tag "Maybe" maybe)
+                (other :tag "On" t))
+  :group 'editing-basics
+  :version "21.1"
+  :set (lambda (symbol value)
+        ;; The fboundp is because of a problem with :set when
+        ;; dumping Emacs.  It doesn't really matter.
+        (if (fboundp 'normal-erase-is-backspace-mode)
+            (normal-erase-is-backspace-mode (or value 0))
+          (set-default symbol value))))
+
+(defun normal-erase-is-backspace-setup-frame (&optional frame)
+  "Set up `normal-erase-is-backspace-mode' on FRAME, if necessary."
+  (unless frame (setq frame (selected-frame)))
+  (with-selected-frame frame
+    (unless (terminal-parameter nil 'normal-erase-is-backspace)
+      (normal-erase-is-backspace-mode
+       (if (if (eq normal-erase-is-backspace 'maybe)
+               (and (not noninteractive)
+                    (or (memq system-type '(ms-dos windows-nt))
+                       (memq window-system '(w32 ns))
+                        (and (memq window-system '(x))
+                             (fboundp 'x-backspace-delete-keys-p)
+                             (x-backspace-delete-keys-p))
+                        ;; If the terminal Emacs is running on has erase char
+                        ;; set to ^H, use the Backspace key for deleting
+                        ;; backward, and the Delete key for deleting forward.
+                        (and (null window-system)
+                             (eq tty-erase-char ?\^H))))
+             normal-erase-is-backspace)
+           1 0)))))
+
+(define-minor-mode normal-erase-is-backspace-mode
+  "Toggle the Erase and Delete mode of the Backspace and Delete keys.
+With a prefix argument ARG, enable this feature if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+On window systems, when this mode is on, Delete is mapped to C-d
+and Backspace is mapped to DEL; when this mode is off, both
+Delete and Backspace are mapped to DEL.  (The remapping goes via
+`local-function-key-map', so binding Delete or Backspace in the
+global or local keymap will override that.)
+
+In addition, on window systems, the bindings of C-Delete, M-Delete,
+C-M-Delete, C-Backspace, M-Backspace, and C-M-Backspace are changed in
+the global keymap in accordance with the functionality of Delete and
+Backspace.  For example, if Delete is remapped to C-d, which deletes
+forward, C-Delete is bound to `kill-word', but if Delete is remapped
+to DEL, which deletes backward, C-Delete is bound to
+`backward-kill-word'.
+
+If not running on a window system, a similar effect is accomplished by
+remapping C-h (normally produced by the Backspace key) and DEL via
+`keyboard-translate': if this mode is on, C-h is mapped to DEL and DEL
+to C-d; if it's off, the keys are not remapped.
+
+When not running on a window system, and this mode is turned on, the
+former functionality of C-h is available on the F1 key.  You should
+probably not turn on this mode on a text-only terminal if you don't
+have both Backspace, Delete and F1 keys.
+
+See also `normal-erase-is-backspace'."
+  :variable ((eq (terminal-parameter nil 'normal-erase-is-backspace) 1)
+             . (lambda (v)
+                 (setf (terminal-parameter nil 'normal-erase-is-backspace)
+                       (if v 1 0))))
+  (let ((enabled (eq 1 (terminal-parameter
+                        nil 'normal-erase-is-backspace))))
+
+    (cond ((or (memq window-system '(x w32 ns pc))
+              (memq system-type '(ms-dos windows-nt)))
+          (let ((bindings
+                 `(([M-delete] [M-backspace])
+                   ([C-M-delete] [C-M-backspace])
+                   ([?\e C-delete] [?\e C-backspace]))))
+
+            (if enabled
+                (progn
+                  (define-key local-function-key-map [delete] [deletechar])
+                  (define-key local-function-key-map [kp-delete] [deletechar])
+                  (define-key local-function-key-map [backspace] [?\C-?])
+                   (dolist (b bindings)
+                     ;; Not sure if input-decode-map is really right, but
+                     ;; keyboard-translate-table (used below) only works
+                     ;; for integer events, and key-translation-table is
+                     ;; global (like the global-map, used earlier).
+                     (define-key input-decode-map (car b) nil)
+                     (define-key input-decode-map (cadr b) nil)))
+              (define-key local-function-key-map [delete] [?\C-?])
+              (define-key local-function-key-map [kp-delete] [?\C-?])
+              (define-key local-function-key-map [backspace] [?\C-?])
+               (dolist (b bindings)
+                 (define-key input-decode-map (car b) (cadr b))
+                 (define-key input-decode-map (cadr b) (car b))))))
+         (t
+          (if enabled
+              (progn
+                (keyboard-translate ?\C-h ?\C-?)
+                (keyboard-translate ?\C-? ?\C-d))
+            (keyboard-translate ?\C-h ?\C-h)
+            (keyboard-translate ?\C-? ?\C-?))))
+
+    (if (called-interactively-p 'interactive)
+       (message "Delete key deletes %s"
+                (if (eq 1 (terminal-parameter nil 'normal-erase-is-backspace))
+                    "forward" "backward")))))
+
+(defvar vis-mode-saved-buffer-invisibility-spec nil
+  "Saved value of `buffer-invisibility-spec' when Visible mode is on.")
+
+(define-minor-mode read-only-mode
+  "Change whether the current buffer is read-only.
+With prefix argument ARG, make the buffer read-only if ARG is
+positive, otherwise make it writable.  If buffer is read-only
+and `view-read-only' is non-nil, enter view mode.
+
+Do not call this from a Lisp program unless you really intend to
+do the same thing as the \\[read-only-mode] command, including
+possibly enabling or disabling View mode.  Also, note that this
+command works by setting the variable `buffer-read-only', which
+does not affect read-only regions caused by text properties.  To
+ignore read-only status in a Lisp program (whether due to text
+properties or buffer state), bind `inhibit-read-only' temporarily
+to a non-nil value."
+  :variable buffer-read-only
+  (cond
+   ((and (not buffer-read-only) view-mode)
+    (View-exit-and-edit)
+    (make-local-variable 'view-read-only)
+    (setq view-read-only t))           ; Must leave view mode.
+   ((and buffer-read-only view-read-only
+         ;; If view-mode is already active, `view-mode-enter' is a nop.
+         (not view-mode)
+         (not (eq (get major-mode 'mode-class) 'special)))
+    (view-mode-enter))))
+
+(define-minor-mode visible-mode
+  "Toggle making all invisible text temporarily visible (Visible mode).
+With a prefix argument ARG, enable Visible mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+This mode works by saving the value of `buffer-invisibility-spec'
+and setting it to nil."
+  :lighter " Vis"
+  :group 'editing-basics
+  (when (local-variable-p 'vis-mode-saved-buffer-invisibility-spec)
+    (setq buffer-invisibility-spec vis-mode-saved-buffer-invisibility-spec)
+    (kill-local-variable 'vis-mode-saved-buffer-invisibility-spec))
+  (when visible-mode
+    (set (make-local-variable 'vis-mode-saved-buffer-invisibility-spec)
+        buffer-invisibility-spec)
+    (setq buffer-invisibility-spec nil)))
+
+(defvar messages-buffer-mode-map
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map special-mode-map)
+    (define-key map "g" nil)            ; nothing to revert
+    map))
+
+(define-derived-mode messages-buffer-mode special-mode "Messages"
+  "Major mode used in the \"*Messages*\" buffer.")
+
+(defun messages-buffer ()
+  "Return the \"*Messages*\" buffer.
+If it does not exist, create and it switch it to `messages-buffer-mode'."
+  (or (get-buffer "*Messages*")
+      (with-current-buffer (get-buffer-create "*Messages*")
+        (messages-buffer-mode)
+        (current-buffer))))
+
+
+;; Minibuffer prompt stuff.
+
+;;(defun minibuffer-prompt-modification (start end)
+;;  (error "You cannot modify the prompt"))
+;;
+;;
+;;(defun minibuffer-prompt-insertion (start end)
+;;  (let ((inhibit-modification-hooks t))
+;;    (delete-region start end)
+;;    ;; Discard undo information for the text insertion itself
+;;    ;; and for the text deletion.above.
+;;    (when (consp buffer-undo-list)
+;;      (setq buffer-undo-list (cddr buffer-undo-list)))
+;;    (message "You cannot modify the prompt")))
+;;
+;;
+;;(setq minibuffer-prompt-properties
+;;  (list 'modification-hooks '(minibuffer-prompt-modification)
+;;     'insert-in-front-hooks '(minibuffer-prompt-insertion)))
+
+
+;;;; Problematic external packages.
+
+;; rms says this should be done by specifying symbols that define
+;; versions together with bad values.  This is therefore not as
+;; flexible as it could be.  See the thread:
+;; http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00300.html
+(defconst bad-packages-alist
+  ;; Not sure exactly which semantic versions have problems.
+  ;; Definitely 2.0pre3, probably all 2.0pre's before this.
+  '((semantic semantic-version "\\`2\\.0pre[1-3]\\'"
+              "The version of `semantic' loaded does not work in Emacs 22.
+It can cause constant high CPU load.
+Upgrade to at least Semantic 2.0pre4 (distributed with CEDET 1.0pre4).")
+    ;; CUA-mode does not work with GNU Emacs version 22.1 and newer.
+    ;; Except for version 1.2, all of the 1.x and 2.x version of cua-mode
+    ;; provided the `CUA-mode' feature.  Since this is no longer true,
+    ;; we can warn the user if the `CUA-mode' feature is ever provided.
+    (CUA-mode t nil
+"CUA-mode is now part of the standard GNU Emacs distribution,
+so you can now enable CUA via the Options menu or by customizing `cua-mode'.
+
+You have loaded an older version of CUA-mode which does not work
+correctly with this version of Emacs.  You should remove the old
+version and use the one distributed with Emacs."))
+  "Alist of packages known to cause problems in this version of Emacs.
+Each element has the form (PACKAGE SYMBOL REGEXP STRING).
+PACKAGE is either a regular expression to match file names, or a
+symbol (a feature name), like for `with-eval-after-load'.
+SYMBOL is either the name of a string variable, or `t'.  Upon
+loading PACKAGE, if SYMBOL is t or matches REGEXP, display a
+warning using STRING as the message.")
+
+(defun bad-package-check (package)
+  "Run a check using the element from `bad-packages-alist' matching PACKAGE."
+  (condition-case nil
+      (let* ((list (assoc package bad-packages-alist))
+             (symbol (nth 1 list)))
+        (and list
+             (boundp symbol)
+             (or (eq symbol t)
+                 (and (stringp (setq symbol (eval symbol)))
+                      (string-match-p (nth 2 list) symbol)))
+             (display-warning package (nth 3 list) :warning)))
+    (error nil)))
+
+(dolist (elem bad-packages-alist)
+  (let ((pkg (car elem)))
+    (with-eval-after-load pkg
+      (bad-package-check pkg))))
+
+
+;;; Generic dispatcher commands
+
+;; Macro `define-alternatives' is used to create generic commands.
+;; Generic commands are these (like web, mail, news, encrypt, irc, etc.)
+;; that can have different alternative implementations where choosing
+;; among them is exclusively a matter of user preference.
+
+;; (define-alternatives COMMAND) creates a new interactive command
+;; M-x COMMAND and a customizable variable COMMAND-alternatives.
+;; Typically, the user will not need to customize this variable; packages
+;; wanting to add alternative implementations should use
+;;
+;; ;;;###autoload (push '("My impl name" . my-impl-symbol) COMMAND-alternatives
+
+(defmacro define-alternatives (command &rest customizations)
+  "Define the new command `COMMAND'.
+
+The argument `COMMAND' should be a symbol.
+
+Running `M-x COMMAND RET' for the first time prompts for which
+alternative to use and records the selected command as a custom
+variable.
+
+Running `C-u M-x COMMAND RET' prompts again for an alternative
+and overwrites the previous choice.
+
+The variable `COMMAND-alternatives' contains an alist with
+alternative implementations of COMMAND.  `define-alternatives'
+does not have any effect until this variable is set.
+
+CUSTOMIZATIONS, if non-nil, should be composed of alternating
+`defcustom' keywords and values to add to the declaration of
+`COMMAND-alternatives' (typically :group and :version)."
+  (let* ((command-name (symbol-name command))
+         (varalt-name (concat command-name "-alternatives"))
+         (varalt-sym (intern varalt-name))
+         (varimp-sym (intern (concat command-name "--implementation"))))
+    `(progn
+
+       (defcustom ,varalt-sym nil
+         ,(format "Alist of alternative implementations for the `%s' command.
+
+Each entry must be a pair (ALTNAME . ALTFUN), where:
+ALTNAME - The name shown at user to describe the alternative implementation.
+ALTFUN  - The function called to implement this alternative."
+                  command-name)
+         :type '(alist :key-type string :value-type function)
+         ,@customizations)
+
+       (put ',varalt-sym 'definition-name ',command)
+       (defvar ,varimp-sym nil "Internal use only.")
+
+       (defun ,command (&optional arg)
+         ,(format "Run generic command `%s'.
+If used for the first time, or with interactive ARG, ask the user which
+implementation to use for `%s'.  The variable `%s'
+contains the list of implementations currently supported for this command."
+                  command-name command-name varalt-name)
+         (interactive "P")
+         (when (or arg (null ,varimp-sym))
+           (let ((val (completing-read
+                      ,(format "Select implementation for command `%s': "
+                               command-name)
+                      ,varalt-sym nil t)))
+             (unless (string-equal val "")
+              (when (null ,varimp-sym)
+                (message
+                 "Use `C-u M-x %s RET' to select another implementation"
+                 ,command-name)
+                (sit-for 3))
+              (customize-save-variable ',varimp-sym
+                                       (cdr (assoc-string val ,varalt-sym))))))
+         (if ,varimp-sym
+             (call-interactively ,varimp-sym)
+           (message ,(format "No implementation selected for command `%s'"
+                             command-name)))))))
+
+
+;; This is here because files in obsolete/ are not scanned for autoloads.
+
+(defvar iswitchb-mode nil "\
+Non-nil if Iswitchb mode is enabled.
+See the command `iswitchb-mode' for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `iswitchb-mode'.")
+
+(custom-autoload 'iswitchb-mode "iswitchb" nil)
+
+(autoload 'iswitchb-mode "iswitchb" "\
+Toggle Iswitchb mode.
+With a prefix argument ARG, enable Iswitchb mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+Iswitchb mode is a global minor mode that enables switching
+between buffers using substrings.  See `iswitchb' for details.
+
+\(fn &optional ARG)" t nil)
+
+(make-obsolete 'iswitchb-mode
+               "use `icomplete-mode' or `ido-mode' instead." "24.4")
+
+
+(provide 'simple)
+
+;;; simple.el ends here
diff --git a/packages/context-coloring/benchmark/fixtures/subr.el 
b/packages/context-coloring/benchmark/fixtures/subr.el
new file mode 100644
index 0000000..a48038f
--- /dev/null
+++ b/packages/context-coloring/benchmark/fixtures/subr.el
@@ -0,0 +1,4801 @@
+;;; subr.el --- basic lisp subroutines for Emacs  -*- coding: utf-8; 
lexical-binding:t -*-
+
+;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2015 Free Software
+;; Foundation, Inc.
+
+;; Maintainer: address@hidden
+;; Keywords: internal
+;; Package: emacs
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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.
+
+;; GNU Emacs 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 GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+;; Beware: while this file has tag `utf-8', before it's compiled, it gets
+;; loaded as "raw-text", so non-ASCII chars won't work right during bootstrap.
+
+(defmacro declare-function (_fn _file &optional _arglist _fileonly)
+  "Tell the byte-compiler that function FN is defined, in FILE.
+Optional ARGLIST is the argument list used by the function.
+The FILE argument is not used by the byte-compiler, but by the
+`check-declare' package, which checks that FILE contains a
+definition for FN.  ARGLIST is used by both the byte-compiler
+and `check-declare' to check for consistency.
+
+FILE can be either a Lisp file (in which case the \".el\"
+extension is optional), or a C file.  C files are expanded
+relative to the Emacs \"src/\" directory.  Lisp files are
+searched for using `locate-library', and if that fails they are
+expanded relative to the location of the file containing the
+declaration.  A FILE with an \"ext:\" prefix is an external file.
+`check-declare' will check such files if they are found, and skip
+them without error if they are not.
+
+FILEONLY non-nil means that `check-declare' will only check that
+FILE exists, not that it defines FN.  This is intended for
+function-definitions that `check-declare' does not recognize, e.g.
+`defstruct'.
+
+To specify a value for FILEONLY without passing an argument list,
+set ARGLIST to t.  This is necessary because nil means an
+empty argument list, rather than an unspecified one.
+
+Note that for the purposes of `check-declare', this statement
+must be the first non-whitespace on a line.
+
+For more information, see Info node `(elisp)Declaring Functions'."
+  ;; Does nothing - byte-compile-declare-function does the work.
+  nil)
+
+
+;;;; Basic Lisp macros.
+
+(defalias 'not 'null)
+
+(defmacro noreturn (form)
+  "Evaluate FORM, expecting it not to return.
+If FORM does return, signal an error."
+  (declare (debug t))
+  `(prog1 ,form
+     (error "Form marked with `noreturn' did return")))
+
+(defmacro 1value (form)
+  "Evaluate FORM, expecting a constant return value.
+This is the global do-nothing version.  There is also `testcover-1value'
+that complains if FORM ever does return differing values."
+  (declare (debug t))
+  form)
+
+(defmacro def-edebug-spec (symbol spec)
+  "Set the `edebug-form-spec' property of SYMBOL according to SPEC.
+Both SYMBOL and SPEC are unevaluated.  The SPEC can be:
+0 (instrument no arguments); t (instrument all arguments);
+a symbol (naming a function with an Edebug specification); or a list.
+The elements of the list describe the argument types; see
+Info node `(elisp)Specification List' for details."
+  `(put (quote ,symbol) 'edebug-form-spec (quote ,spec)))
+
+(defmacro lambda (&rest cdr)
+  "Return a lambda expression.
+A call of the form (lambda ARGS DOCSTRING INTERACTIVE BODY) is
+self-quoting; the result of evaluating the lambda expression is the
+expression itself.  The lambda expression may then be treated as a
+function, i.e., stored as the function value of a symbol, passed to
+`funcall' or `mapcar', etc.
+
+ARGS should take the same form as an argument list for a `defun'.
+DOCSTRING is an optional documentation string.
+ If present, it should describe how to call the function.
+ But documentation strings are usually not useful in nameless functions.
+INTERACTIVE should be a call to the function `interactive', which see.
+It may also be omitted.
+BODY should be a list of Lisp expressions.
+
+\(fn ARGS [DOCSTRING] [INTERACTIVE] BODY)"
+  (declare (doc-string 2) (indent defun)
+           (debug (&define lambda-list
+                           [&optional stringp]
+                           [&optional ("interactive" interactive)]
+                           def-body)))
+  ;; Note that this definition should not use backquotes; subr.el should not
+  ;; depend on backquote.el.
+  (list 'function (cons 'lambda cdr)))
+
+(defmacro setq-local (var val)
+  "Set variable VAR to value VAL in current buffer."
+  ;; Can't use backquote here, it's too early in the bootstrap.
+  (list 'set (list 'make-local-variable (list 'quote var)) val))
+
+(defmacro defvar-local (var val &optional docstring)
+  "Define VAR as a buffer-local variable with default value VAL.
+Like `defvar' but additionally marks the variable as being automatically
+buffer-local wherever it is set."
+  (declare (debug defvar) (doc-string 3))
+  ;; Can't use backquote here, it's too early in the bootstrap.
+  (list 'progn (list 'defvar var val docstring)
+        (list 'make-variable-buffer-local (list 'quote var))))
+
+(defun apply-partially (fun &rest args)
+  "Return a function that is a partial application of FUN to ARGS.
+ARGS is a list of the first N arguments to pass to FUN.
+The result is a new function which does the same as FUN, except that
+the first N arguments are fixed at the values with which this function
+was called."
+  `(closure (t) (&rest args)
+            (apply ',fun ,@(mapcar (lambda (arg) `',arg) args) args)))
+
+(defmacro push (newelt place)
+  "Add NEWELT to the list stored in the generalized variable PLACE.
+This is morally equivalent to (setf PLACE (cons NEWELT PLACE)),
+except that PLACE is only evaluated once (after NEWELT)."
+  (declare (debug (form gv-place)))
+  (if (symbolp place)
+      ;; Important special case, to avoid triggering GV too early in
+      ;; the bootstrap.
+      (list 'setq place
+            (list 'cons newelt place))
+    (require 'macroexp)
+    (macroexp-let2 macroexp-copyable-p v newelt
+      (gv-letplace (getter setter) place
+        (funcall setter `(cons ,v ,getter))))))
+
+(defmacro pop (place)
+  "Return the first element of PLACE's value, and remove it from the list.
+PLACE must be a generalized variable whose value is a list.
+If the value is nil, `pop' returns nil but does not actually
+change the list."
+  (declare (debug (gv-place)))
+  ;; We use `car-safe' here instead of `car' because the behavior is the same
+  ;; (if it's not a cons cell, the `cdr' would have signaled an error already),
+  ;; but `car-safe' is total, so the byte-compiler can safely remove it if the
+  ;; result is not used.
+  `(car-safe
+    ,(if (symbolp place)
+         ;; So we can use `pop' in the bootstrap before `gv' can be used.
+         (list 'prog1 place (list 'setq place (list 'cdr place)))
+       (gv-letplace (getter setter) place
+         `(prog1 ,getter ,(funcall setter `(cdr ,getter)))))))
+
+(defmacro when (cond &rest body)
+  "If COND yields non-nil, do BODY, else return nil.
+When COND yields non-nil, eval BODY forms sequentially and return
+value of last one, or nil if there are none.
+
+\(fn COND BODY...)"
+  (declare (indent 1) (debug t))
+  (list 'if cond (cons 'progn body)))
+
+(defmacro unless (cond &rest body)
+  "If COND yields nil, do BODY, else return nil.
+When COND yields nil, eval BODY forms sequentially and return
+value of last one, or nil if there are none.
+
+\(fn COND BODY...)"
+  (declare (indent 1) (debug t))
+  (cons 'if (cons cond (cons nil body))))
+
+(defmacro dolist (spec &rest body)
+  "Loop over a list.
+Evaluate BODY with VAR bound to each car from LIST, in turn.
+Then evaluate RESULT to get return value, default nil.
+
+\(fn (VAR LIST [RESULT]) BODY...)"
+  (declare (indent 1) (debug ((symbolp form &optional form) body)))
+  ;; It would be cleaner to create an uninterned symbol,
+  ;; but that uses a lot more space when many functions in many files
+  ;; use dolist.
+  ;; FIXME: This cost disappears in byte-compiled lexical-binding files.
+  (let ((temp '--dolist-tail--))
+    ;; This is not a reliable test, but it does not matter because both
+    ;; semantics are acceptable, tho one is slightly faster with dynamic
+    ;; scoping and the other is slightly faster (and has cleaner semantics)
+    ;; with lexical scoping.
+    (if lexical-binding
+        `(let ((,temp ,(nth 1 spec)))
+           (while ,temp
+             (let ((,(car spec) (car ,temp)))
+               ,@body
+               (setq ,temp (cdr ,temp))))
+           ,@(cdr (cdr spec)))
+      `(let ((,temp ,(nth 1 spec))
+             ,(car spec))
+         (while ,temp
+           (setq ,(car spec) (car ,temp))
+           ,@body
+           (setq ,temp (cdr ,temp)))
+         ,@(if (cdr (cdr spec))
+               `((setq ,(car spec) nil) ,@(cdr (cdr spec))))))))
+
+(defmacro dotimes (spec &rest body)
+  "Loop a certain number of times.
+Evaluate BODY with VAR bound to successive integers running from 0,
+inclusive, to COUNT, exclusive.  Then evaluate RESULT to get
+the return value (nil if RESULT is omitted).
+
+\(fn (VAR COUNT [RESULT]) BODY...)"
+  (declare (indent 1) (debug dolist))
+  ;; It would be cleaner to create an uninterned symbol,
+  ;; but that uses a lot more space when many functions in many files
+  ;; use dotimes.
+  ;; FIXME: This cost disappears in byte-compiled lexical-binding files.
+  (let ((temp '--dotimes-limit--)
+       (start 0)
+       (end (nth 1 spec)))
+    ;; This is not a reliable test, but it does not matter because both
+    ;; semantics are acceptable, tho one is slightly faster with dynamic
+    ;; scoping and the other has cleaner semantics.
+    (if lexical-binding
+        (let ((counter '--dotimes-counter--))
+          `(let ((,temp ,end)
+                 (,counter ,start))
+             (while (< ,counter ,temp)
+               (let ((,(car spec) ,counter))
+                 ,@body)
+               (setq ,counter (1+ ,counter)))
+             ,@(if (cddr spec)
+                   ;; FIXME: This let often leads to "unused var" warnings.
+                   `((let ((,(car spec) ,counter)) ,@(cddr spec))))))
+      `(let ((,temp ,end)
+             (,(car spec) ,start))
+         (while (< ,(car spec) ,temp)
+           ,@body
+           (setq ,(car spec) (1+ ,(car spec))))
+         ,@(cdr (cdr spec))))))
+
+(defmacro declare (&rest _specs)
+  "Do not evaluate any arguments, and return nil.
+If a `declare' form appears as the first form in the body of a
+`defun' or `defmacro' form, SPECS specifies various additional
+information about the function or macro; these go into effect
+during the evaluation of the `defun' or `defmacro' form.
+
+The possible values of SPECS are specified by
+`defun-declarations-alist' and `macro-declarations-alist'."
+  ;; FIXME: edebug spec should pay attention to defun-declarations-alist.
+  nil)
+
+(defmacro ignore-errors (&rest body)
+  "Execute BODY; if an error occurs, return nil.
+Otherwise, return result of last form in BODY.
+See also `with-demoted-errors' that does something similar
+without silencing all errors."
+  (declare (debug t) (indent 0))
+  `(condition-case nil (progn ,@body) (error nil)))
+
+;;;; Basic Lisp functions.
+
+(defun ignore (&rest _ignore)
+  "Do nothing and return nil.
+This function accepts any number of arguments, but ignores them."
+  (interactive)
+  nil)
+
+;; Signal a compile-error if the first arg is missing.
+(defun error (&rest args)
+  "Signal an error, making error message by passing all args to `format'.
+In Emacs, the convention is that error messages start with a capital
+letter but *do not* end with a period.  Please follow this convention
+for the sake of consistency."
+  (declare (advertised-calling-convention (string &rest args) "23.1"))
+  (signal 'error (list (apply 'format args))))
+
+(defun user-error (format &rest args)
+  "Signal a pilot error, making error message by passing all args to `format'.
+In Emacs, the convention is that error messages start with a capital
+letter but *do not* end with a period.  Please follow this convention
+for the sake of consistency.
+This is just like `error' except that `user-error's are expected to be the
+result of an incorrect manipulation on the part of the user, rather than the
+result of an actual problem."
+  (signal 'user-error (list (apply #'format format args))))
+
+(defun define-error (name message &optional parent)
+  "Define NAME as a new error signal.
+MESSAGE is a string that will be output to the echo area if such an error
+is signaled without being caught by a `condition-case'.
+PARENT is either a signal or a list of signals from which it inherits.
+Defaults to `error'."
+  (unless parent (setq parent 'error))
+  (let ((conditions
+         (if (consp parent)
+             (apply #'nconc
+                    (mapcar (lambda (parent)
+                              (cons parent
+                                    (or (get parent 'error-conditions)
+                                        (error "Unknown signal `%s'" parent))))
+                            parent))
+           (cons parent (get parent 'error-conditions)))))
+    (put name 'error-conditions
+         (delete-dups (copy-sequence (cons name conditions))))
+    (when message (put name 'error-message message))))
+
+;; We put this here instead of in frame.el so that it's defined even on
+;; systems where frame.el isn't loaded.
+(defun frame-configuration-p (object)
+  "Return non-nil if OBJECT seems to be a frame configuration.
+Any list whose car is `frame-configuration' is assumed to be a frame
+configuration."
+  (and (consp object)
+       (eq (car object) 'frame-configuration)))
+
+;;;; List functions.
+
+(defsubst caar (x)
+  "Return the car of the car of X."
+  (car (car x)))
+
+(defsubst cadr (x)
+  "Return the car of the cdr of X."
+  (car (cdr x)))
+
+(defsubst cdar (x)
+  "Return the cdr of the car of X."
+  (cdr (car x)))
+
+(defsubst cddr (x)
+  "Return the cdr of the cdr of X."
+  (cdr (cdr x)))
+
+(defun last (list &optional n)
+  "Return the last link of LIST.  Its car is the last element.
+If LIST is nil, return nil.
+If N is non-nil, return the Nth-to-last link of LIST.
+If N is bigger than the length of LIST, return LIST."
+  (if n
+      (and (>= n 0)
+           (let ((m (safe-length list)))
+             (if (< n m) (nthcdr (- m n) list) list)))
+    (and list
+         (nthcdr (1- (safe-length list)) list))))
+
+(defun butlast (list &optional n)
+  "Return a copy of LIST with the last N elements removed.
+If N is omitted or nil, the last element is removed from the
+copy."
+  (if (and n (<= n 0)) list
+    (nbutlast (copy-sequence list) n)))
+
+(defun nbutlast (list &optional n)
+  "Modifies LIST to remove the last N elements.
+If N is omitted or nil, remove the last element."
+  (let ((m (length list)))
+    (or n (setq n 1))
+    (and (< n m)
+        (progn
+          (if (> n 0) (setcdr (nthcdr (- (1- m) n) list) nil))
+          list))))
+
+(defun delete-dups (list)
+  "Destructively remove `equal' duplicates from LIST.
+Store the result in LIST and return it.  LIST must be a proper list.
+Of several `equal' occurrences of an element in LIST, the first
+one is kept."
+  (let ((tail list))
+    (while tail
+      (setcdr tail (delete (car tail) (cdr tail)))
+      (setq tail (cdr tail))))
+  list)
+
+;; See http://lists.gnu.org/archive/html/emacs-devel/2013-05/msg00204.html
+(defun delete-consecutive-dups (list &optional circular)
+  "Destructively remove `equal' consecutive duplicates from LIST.
+First and last elements are considered consecutive if CIRCULAR is
+non-nil."
+  (let ((tail list) last)
+    (while (consp tail)
+      (if (equal (car tail) (cadr tail))
+         (setcdr tail (cddr tail))
+       (setq last (car tail)
+             tail (cdr tail))))
+    (if (and circular
+            (cdr list)
+            (equal last (car list)))
+       (nbutlast list)
+      list)))
+
+(defun number-sequence (from &optional to inc)
+  "Return a sequence of numbers from FROM to TO (both inclusive) as a list.
+INC is the increment used between numbers in the sequence and defaults to 1.
+So, the Nth element of the list is (+ FROM (* N INC)) where N counts from
+zero.  TO is only included if there is an N for which TO = FROM + N * INC.
+If TO is nil or numerically equal to FROM, return (FROM).
+If INC is positive and TO is less than FROM, or INC is negative
+and TO is larger than FROM, return nil.
+If INC is zero and TO is neither nil nor numerically equal to
+FROM, signal an error.
+
+This function is primarily designed for integer arguments.
+Nevertheless, FROM, TO and INC can be integer or float.  However,
+floating point arithmetic is inexact.  For instance, depending on
+the machine, it may quite well happen that
+\(number-sequence 0.4 0.6 0.2) returns the one element list (0.4),
+whereas (number-sequence 0.4 0.8 0.2) returns a list with three
+elements.  Thus, if some of the arguments are floats and one wants
+to make sure that TO is included, one may have to explicitly write
+TO as (+ FROM (* N INC)) or use a variable whose value was
+computed with this exact expression.  Alternatively, you can,
+of course, also replace TO with a slightly larger value
+\(or a slightly more negative value if INC is negative)."
+  (if (or (not to) (= from to))
+      (list from)
+    (or inc (setq inc 1))
+    (when (zerop inc) (error "The increment can not be zero"))
+    (let (seq (n 0) (next from))
+      (if (> inc 0)
+          (while (<= next to)
+            (setq seq (cons next seq)
+                  n (1+ n)
+                  next (+ from (* n inc))))
+        (while (>= next to)
+          (setq seq (cons next seq)
+                n (1+ n)
+                next (+ from (* n inc)))))
+      (nreverse seq))))
+
+(defun copy-tree (tree &optional vecp)
+  "Make a copy of TREE.
+If TREE is a cons cell, this recursively copies both its car and its cdr.
+Contrast to `copy-sequence', which copies only along the cdrs.  With second
+argument VECP, this copies vectors as well as conses."
+  (if (consp tree)
+      (let (result)
+       (while (consp tree)
+         (let ((newcar (car tree)))
+           (if (or (consp (car tree)) (and vecp (vectorp (car tree))))
+               (setq newcar (copy-tree (car tree) vecp)))
+           (push newcar result))
+         (setq tree (cdr tree)))
+       (nconc (nreverse result) tree))
+    (if (and vecp (vectorp tree))
+       (let ((i (length (setq tree (copy-sequence tree)))))
+         (while (>= (setq i (1- i)) 0)
+           (aset tree i (copy-tree (aref tree i) vecp)))
+         tree)
+      tree)))
+
+;;;; Various list-search functions.
+
+(defun assoc-default (key alist &optional test default)
+  "Find object KEY in a pseudo-alist ALIST.
+ALIST is a list of conses or objects.  Each element
+ (or the element's car, if it is a cons) is compared with KEY by
+ calling TEST, with two arguments: (i) the element or its car,
+ and (ii) KEY.
+If that is non-nil, the element matches; then `assoc-default'
+ returns the element's cdr, if it is a cons, or DEFAULT if the
+ element is not a cons.
+
+If no element matches, the value is nil.
+If TEST is omitted or nil, `equal' is used."
+  (let (found (tail alist) value)
+    (while (and tail (not found))
+      (let ((elt (car tail)))
+       (when (funcall (or test 'equal) (if (consp elt) (car elt) elt) key)
+         (setq found t value (if (consp elt) (cdr elt) default))))
+      (setq tail (cdr tail)))
+    value))
+
+(defun assoc-ignore-case (key alist)
+  "Like `assoc', but ignores differences in case and text representation.
+KEY must be a string.  Upper-case and lower-case letters are treated as equal.
+Unibyte strings are converted to multibyte for comparison."
+  (declare (obsolete assoc-string "22.1"))
+  (assoc-string key alist t))
+
+(defun assoc-ignore-representation (key alist)
+  "Like `assoc', but ignores differences in text representation.
+KEY must be a string.
+Unibyte strings are converted to multibyte for comparison."
+  (declare (obsolete assoc-string "22.1"))
+  (assoc-string key alist nil))
+
+(defun member-ignore-case (elt list)
+  "Like `member', but ignore differences in case and text representation.
+ELT must be a string.  Upper-case and lower-case letters are treated as equal.
+Unibyte strings are converted to multibyte for comparison.
+Non-strings in LIST are ignored."
+  (while (and list
+             (not (and (stringp (car list))
+                       (eq t (compare-strings elt 0 nil (car list) 0 nil t)))))
+    (setq list (cdr list)))
+  list)
+
+(defun assq-delete-all (key alist)
+  "Delete from ALIST all elements whose car is `eq' to KEY.
+Return the modified alist.
+Elements of ALIST that are not conses are ignored."
+  (while (and (consp (car alist))
+             (eq (car (car alist)) key))
+    (setq alist (cdr alist)))
+  (let ((tail alist) tail-cdr)
+    (while (setq tail-cdr (cdr tail))
+      (if (and (consp (car tail-cdr))
+              (eq (car (car tail-cdr)) key))
+         (setcdr tail (cdr tail-cdr))
+       (setq tail tail-cdr))))
+  alist)
+
+(defun rassq-delete-all (value alist)
+  "Delete from ALIST all elements whose cdr is `eq' to VALUE.
+Return the modified alist.
+Elements of ALIST that are not conses are ignored."
+  (while (and (consp (car alist))
+             (eq (cdr (car alist)) value))
+    (setq alist (cdr alist)))
+  (let ((tail alist) tail-cdr)
+    (while (setq tail-cdr (cdr tail))
+      (if (and (consp (car tail-cdr))
+              (eq (cdr (car tail-cdr)) value))
+         (setcdr tail (cdr tail-cdr))
+       (setq tail tail-cdr))))
+  alist)
+
+(defun remove (elt seq)
+  "Return a copy of SEQ with all occurrences of ELT removed.
+SEQ must be a list, vector, or string.  The comparison is done with `equal'."
+  (if (nlistp seq)
+      ;; If SEQ isn't a list, there's no need to copy SEQ because
+      ;; `delete' will return a new object.
+      (delete elt seq)
+    (delete elt (copy-sequence seq))))
+
+(defun remq (elt list)
+  "Return LIST with all occurrences of ELT removed.
+The comparison is done with `eq'.  Contrary to `delq', this does not use
+side-effects, and the argument LIST is not modified."
+  (while (and (eq elt (car list)) (setq list (cdr list))))
+  (if (memq elt list)
+      (delq elt (copy-sequence list))
+    list))
+
+;;;; Keymap support.
+
+(defun kbd (keys)
+  "Convert KEYS to the internal Emacs key representation.
+KEYS should be a string constant in the format used for
+saving keyboard macros (see `edmacro-mode')."
+  ;; Don't use a defalias, since the `pure' property is only true for
+  ;; the calling convention of `kbd'.
+  (read-kbd-macro keys))
+(put 'kbd 'pure t)
+
+(defun undefined ()
+  "Beep to tell the user this binding is undefined."
+  (interactive)
+  (ding)
+  (message "%s is undefined" (key-description (this-single-command-keys)))
+  (setq defining-kbd-macro nil)
+  (force-mode-line-update)
+  ;; If this is a down-mouse event, don't reset prefix-arg;
+  ;; pass it to the command run by the up event.
+  (setq prefix-arg
+        (when (memq 'down (event-modifiers last-command-event))
+          current-prefix-arg)))
+
+;; Prevent the \{...} documentation construct
+;; from mentioning keys that run this command.
+(put 'undefined 'suppress-keymap t)
+
+(defun suppress-keymap (map &optional nodigits)
+  "Make MAP override all normally self-inserting keys to be undefined.
+Normally, as an exception, digits and minus-sign are set to make prefix args,
+but optional second arg NODIGITS non-nil treats them like other chars."
+  (define-key map [remap self-insert-command] 'undefined)
+  (or nodigits
+      (let (loop)
+       (define-key map "-" 'negative-argument)
+       ;; Make plain numbers do numeric args.
+       (setq loop ?0)
+       (while (<= loop ?9)
+         (define-key map (char-to-string loop) 'digit-argument)
+         (setq loop (1+ loop))))))
+
+(defun make-composed-keymap (maps &optional parent)
+  "Construct a new keymap composed of MAPS and inheriting from PARENT.
+When looking up a key in the returned map, the key is looked in each
+keymap of MAPS in turn until a binding is found.
+If no binding is found in MAPS, the lookup continues in PARENT, if non-nil.
+As always with keymap inheritance, a nil binding in MAPS overrides
+any corresponding binding in PARENT, but it does not override corresponding
+bindings in other keymaps of MAPS.
+MAPS can be a list of keymaps or a single keymap.
+PARENT if non-nil should be a keymap."
+  `(keymap
+    ,@(if (keymapp maps) (list maps) maps)
+    ,@parent))
+
+(defun define-key-after (keymap key definition &optional after)
+  "Add binding in KEYMAP for KEY => DEFINITION, right after AFTER's binding.
+This is like `define-key' except that the binding for KEY is placed
+just after the binding for the event AFTER, instead of at the beginning
+of the map.  Note that AFTER must be an event type (like KEY), NOT a command
+\(like DEFINITION).
+
+If AFTER is t or omitted, the new binding goes at the end of the keymap.
+AFTER should be a single event type--a symbol or a character, not a sequence.
+
+Bindings are always added before any inherited map.
+
+The order of bindings in a keymap only matters when it is used as
+a menu, so this function is not useful for non-menu keymaps."
+  (unless after (setq after t))
+  (or (keymapp keymap)
+      (signal 'wrong-type-argument (list 'keymapp keymap)))
+  (setq key
+       (if (<= (length key) 1) (aref key 0)
+         (setq keymap (lookup-key keymap
+                                  (apply 'vector
+                                         (butlast (mapcar 'identity key)))))
+         (aref key (1- (length key)))))
+  (let ((tail keymap) done inserted)
+    (while (and (not done) tail)
+      ;; Delete any earlier bindings for the same key.
+      (if (eq (car-safe (car (cdr tail))) key)
+         (setcdr tail (cdr (cdr tail))))
+      ;; If we hit an included map, go down that one.
+      (if (keymapp (car tail)) (setq tail (car tail)))
+      ;; When we reach AFTER's binding, insert the new binding after.
+      ;; If we reach an inherited keymap, insert just before that.
+      ;; If we reach the end of this keymap, insert at the end.
+      (if (or (and (eq (car-safe (car tail)) after)
+                  (not (eq after t)))
+             (eq (car (cdr tail)) 'keymap)
+             (null (cdr tail)))
+         (progn
+           ;; Stop the scan only if we find a parent keymap.
+           ;; Keep going past the inserted element
+           ;; so we can delete any duplications that come later.
+           (if (eq (car (cdr tail)) 'keymap)
+               (setq done t))
+           ;; Don't insert more than once.
+           (or inserted
+               (setcdr tail (cons (cons key definition) (cdr tail))))
+           (setq inserted t)))
+      (setq tail (cdr tail)))))
+
+(defun map-keymap-sorted (function keymap)
+  "Implement `map-keymap' with sorting.
+Don't call this function; it is for internal use only."
+  (let (list)
+    (map-keymap (lambda (a b) (push (cons a b) list))
+                keymap)
+    (setq list (sort list
+                     (lambda (a b)
+                       (setq a (car a) b (car b))
+                       (if (integerp a)
+                           (if (integerp b) (< a b)
+                             t)
+                         (if (integerp b) t
+                           ;; string< also accepts symbols.
+                           (string< a b))))))
+    (dolist (p list)
+      (funcall function (car p) (cdr p)))))
+
+(defun keymap--menu-item-binding (val)
+  "Return the binding part of a menu-item."
+  (cond
+   ((not (consp val)) val)              ;Not a menu-item.
+   ((eq 'menu-item (car val))
+    (let* ((binding (nth 2 val))
+           (plist (nthcdr 3 val))
+           (filter (plist-get plist :filter)))
+      (if filter (funcall filter binding)
+        binding)))
+   ((and (consp (cdr val)) (stringp (cadr val)))
+    (cddr val))
+   ((stringp (car val))
+    (cdr val))
+   (t val)))                            ;Not a menu-item either.
+
+(defun keymap--menu-item-with-binding (item binding)
+  "Build a menu-item like ITEM but with its binding changed to BINDING."
+  (cond
+   ((not (consp item)) binding)                ;Not a menu-item.
+   ((eq 'menu-item (car item))
+    (setq item (copy-sequence item))
+    (let ((tail (nthcdr 2 item)))
+      (setcar tail binding)
+      ;; Remove any potential filter.
+      (if (plist-get (cdr tail) :filter)
+          (setcdr tail (plist-put (cdr tail) :filter nil))))
+    item)
+   ((and (consp (cdr item)) (stringp (cadr item)))
+    (cons (car item) (cons (cadr item) binding)))
+   (t (cons (car item) binding))))
+
+(defun keymap--merge-bindings (val1 val2)
+  "Merge bindings VAL1 and VAL2."
+  (let ((map1 (keymap--menu-item-binding val1))
+        (map2 (keymap--menu-item-binding val2)))
+    (if (not (and (keymapp map1) (keymapp map2)))
+        ;; There's nothing to merge: val1 takes precedence.
+        val1
+      (let ((map (list 'keymap map1 map2))
+            (item (if (keymapp val1) (if (keymapp val2) nil val2) val1)))
+        (keymap--menu-item-with-binding item map)))))
+
+(defun keymap-canonicalize (map)
+  "Return a simpler equivalent keymap.
+This resolves inheritance and redefinitions.  The returned keymap
+should behave identically to a copy of KEYMAP w.r.t `lookup-key'
+and use in active keymaps and menus.
+Subkeymaps may be modified but are not canonicalized."
+  ;; FIXME: Problem with the difference between a nil binding
+  ;; that hides a binding in an inherited map and a nil binding that's ignored
+  ;; to let some further binding visible.  Currently a nil binding hides all.
+  ;; FIXME: we may want to carefully (re)order elements in case they're
+  ;; menu-entries.
+  (let ((bindings ())
+        (ranges ())
+       (prompt (keymap-prompt map)))
+    (while (keymapp map)
+      (setq map (map-keymap ;; -internal
+                 (lambda (key item)
+                   (if (consp key)
+                       ;; Treat char-ranges specially.
+                       (push (cons key item) ranges)
+                     (push (cons key item) bindings)))
+                 map)))
+    ;; Create the new map.
+    (setq map (funcall (if ranges 'make-keymap 'make-sparse-keymap) prompt))
+    (dolist (binding ranges)
+      ;; Treat char-ranges specially.  FIXME: need to merge as well.
+      (define-key map (vector (car binding)) (cdr binding)))
+    ;; Process the bindings starting from the end.
+    (dolist (binding (prog1 bindings (setq bindings ())))
+      (let* ((key (car binding))
+             (oldbind (assq key bindings)))
+        (push (if (not oldbind)
+                  ;; The normal case: no duplicate bindings.
+                  binding
+                ;; This is the second binding for this key.
+                (setq bindings (delq oldbind bindings))
+                (cons key (keymap--merge-bindings (cdr binding)
+                                                  (cdr oldbind))))
+              bindings)))
+    (nconc map bindings)))
+
+(put 'keyboard-translate-table 'char-table-extra-slots 0)
+
+(defun keyboard-translate (from to)
+  "Translate character FROM to TO on the current terminal.
+This function creates a `keyboard-translate-table' if necessary
+and then modifies one entry in it."
+  (or (char-table-p keyboard-translate-table)
+      (setq keyboard-translate-table
+           (make-char-table 'keyboard-translate-table nil)))
+  (aset keyboard-translate-table from to))
+
+;;;; Key binding commands.
+
+(defun global-set-key (key command)
+  "Give KEY a global binding as COMMAND.
+COMMAND is the command definition to use; usually it is
+a symbol naming an interactively-callable function.
+KEY is a key sequence; noninteractively, it is a string or vector
+of characters or event types, and non-ASCII characters with codes
+above 127 (such as ISO Latin-1) can be included if you use a vector.
+
+Note that if KEY has a local binding in the current buffer,
+that local binding will continue to shadow any global binding
+that you make with this function."
+  (interactive "KSet key globally: \nCSet key %s to command: ")
+  (or (vectorp key) (stringp key)
+      (signal 'wrong-type-argument (list 'arrayp key)))
+  (define-key (current-global-map) key command))
+
+(defun local-set-key (key command)
+  "Give KEY a local binding as COMMAND.
+COMMAND is the command definition to use; usually it is
+a symbol naming an interactively-callable function.
+KEY is a key sequence; noninteractively, it is a string or vector
+of characters or event types, and non-ASCII characters with codes
+above 127 (such as ISO Latin-1) can be included if you use a vector.
+
+The binding goes in the current buffer's local map, which in most
+cases is shared with all other buffers in the same major mode."
+  (interactive "KSet key locally: \nCSet key %s locally to command: ")
+  (let ((map (current-local-map)))
+    (or map
+       (use-local-map (setq map (make-sparse-keymap))))
+    (or (vectorp key) (stringp key)
+       (signal 'wrong-type-argument (list 'arrayp key)))
+    (define-key map key command)))
+
+(defun global-unset-key (key)
+  "Remove global binding of KEY.
+KEY is a string or vector representing a sequence of keystrokes."
+  (interactive "kUnset key globally: ")
+  (global-set-key key nil))
+
+(defun local-unset-key (key)
+  "Remove local binding of KEY.
+KEY is a string or vector representing a sequence of keystrokes."
+  (interactive "kUnset key locally: ")
+  (if (current-local-map)
+      (local-set-key key nil))
+  nil)
+
+;;;; substitute-key-definition and its subroutines.
+
+(defvar key-substitution-in-progress nil
+  "Used internally by `substitute-key-definition'.")
+
+(defun substitute-key-definition (olddef newdef keymap &optional oldmap prefix)
+  "Replace OLDDEF with NEWDEF for any keys in KEYMAP now defined as OLDDEF.
+In other words, OLDDEF is replaced with NEWDEF where ever it appears.
+Alternatively, if optional fourth argument OLDMAP is specified, we redefine
+in KEYMAP as NEWDEF those keys which are defined as OLDDEF in OLDMAP.
+
+If you don't specify OLDMAP, you can usually get the same results
+in a cleaner way with command remapping, like this:
+  (define-key KEYMAP [remap OLDDEF] NEWDEF)
+\n(fn OLDDEF NEWDEF KEYMAP &optional OLDMAP)"
+  ;; Don't document PREFIX in the doc string because we don't want to
+  ;; advertise it.  It's meant for recursive calls only.  Here's its
+  ;; meaning
+
+  ;; If optional argument PREFIX is specified, it should be a key
+  ;; prefix, a string.  Redefined bindings will then be bound to the
+  ;; original key, with PREFIX added at the front.
+  (or prefix (setq prefix ""))
+  (let* ((scan (or oldmap keymap))
+        (prefix1 (vconcat prefix [nil]))
+        (key-substitution-in-progress
+         (cons scan key-substitution-in-progress)))
+    ;; Scan OLDMAP, finding each char or event-symbol that
+    ;; has any definition, and act on it with hack-key.
+    (map-keymap
+     (lambda (char defn)
+       (aset prefix1 (length prefix) char)
+       (substitute-key-definition-key defn olddef newdef prefix1 keymap))
+     scan)))
+
+(defun substitute-key-definition-key (defn olddef newdef prefix keymap)
+  (let (inner-def skipped menu-item)
+    ;; Find the actual command name within the binding.
+    (if (eq (car-safe defn) 'menu-item)
+       (setq menu-item defn defn (nth 2 defn))
+      ;; Skip past menu-prompt.
+      (while (stringp (car-safe defn))
+       (push (pop defn) skipped))
+      ;; Skip past cached key-equivalence data for menu items.
+      (if (consp (car-safe defn))
+         (setq defn (cdr defn))))
+    (if (or (eq defn olddef)
+           ;; Compare with equal if definition is a key sequence.
+           ;; That is useful for operating on function-key-map.
+           (and (or (stringp defn) (vectorp defn))
+                (equal defn olddef)))
+       (define-key keymap prefix
+         (if menu-item
+             (let ((copy (copy-sequence menu-item)))
+               (setcar (nthcdr 2 copy) newdef)
+               copy)
+           (nconc (nreverse skipped) newdef)))
+      ;; Look past a symbol that names a keymap.
+      (setq inner-def
+           (or (indirect-function defn t) defn))
+      ;; For nested keymaps, we use `inner-def' rather than `defn' so as to
+      ;; avoid autoloading a keymap.  This is mostly done to preserve the
+      ;; original non-autoloading behavior of pre-map-keymap times.
+      (if (and (keymapp inner-def)
+              ;; Avoid recursively scanning
+              ;; where KEYMAP does not have a submap.
+              (let ((elt (lookup-key keymap prefix)))
+                (or (null elt) (natnump elt) (keymapp elt)))
+              ;; Avoid recursively rescanning keymap being scanned.
+              (not (memq inner-def key-substitution-in-progress)))
+         ;; If this one isn't being scanned already, scan it now.
+         (substitute-key-definition olddef newdef keymap inner-def prefix)))))
+
+
+;;;; The global keymap tree.
+
+;; global-map, esc-map, and ctl-x-map have their values set up in
+;; keymap.c; we just give them docstrings here.
+
+(defvar global-map nil
+  "Default global keymap mapping Emacs keyboard input into commands.
+The value is a keymap which is usually (but not necessarily) Emacs's
+global map.")
+
+(defvar esc-map nil
+  "Default keymap for ESC (meta) commands.
+The normal global definition of the character ESC indirects to this keymap.")
+
+(defvar ctl-x-map nil
+  "Default keymap for C-x commands.
+The normal global definition of the character C-x indirects to this keymap.")
+
+(defvar ctl-x-4-map (make-sparse-keymap)
+  "Keymap for subcommands of C-x 4.")
+(defalias 'ctl-x-4-prefix ctl-x-4-map)
+(define-key ctl-x-map "4" 'ctl-x-4-prefix)
+
+(defvar ctl-x-5-map (make-sparse-keymap)
+  "Keymap for frame commands.")
+(defalias 'ctl-x-5-prefix ctl-x-5-map)
+(define-key ctl-x-map "5" 'ctl-x-5-prefix)
+
+
+;;;; Event manipulation functions.
+
+(defconst listify-key-sequence-1 (logior 128 ?\M-\C-@))
+
+(defun listify-key-sequence (key)
+  "Convert a key sequence to a list of events."
+  (if (vectorp key)
+      (append key nil)
+    (mapcar (function (lambda (c)
+                       (if (> c 127)
+                           (logxor c listify-key-sequence-1)
+                         c)))
+           key)))
+
+(defun eventp (obj)
+  "True if the argument is an event object."
+  (when obj
+    (or (integerp obj)
+        (and (symbolp obj) obj (not (keywordp obj)))
+        (and (consp obj) (symbolp (car obj))))))
+
+(defun event-modifiers (event)
+  "Return a list of symbols representing the modifier keys in event EVENT.
+The elements of the list may include `meta', `control',
+`shift', `hyper', `super', `alt', `click', `double', `triple', `drag',
+and `down'.
+EVENT may be an event or an event type.  If EVENT is a symbol
+that has never been used in an event that has been read as input
+in the current Emacs session, then this function may fail to include
+the `click' modifier."
+  (let ((type event))
+    (if (listp type)
+       (setq type (car type)))
+    (if (symbolp type)
+        ;; Don't read event-symbol-elements directly since we're not
+        ;; sure the symbol has already been parsed.
+       (cdr (internal-event-symbol-parse-modifiers type))
+      (let ((list nil)
+           (char (logand type (lognot (logior ?\M-\^@ ?\C-\^@ ?\S-\^@
+                                              ?\H-\^@ ?\s-\^@ ?\A-\^@)))))
+       (if (not (zerop (logand type ?\M-\^@)))
+           (push 'meta list))
+       (if (or (not (zerop (logand type ?\C-\^@)))
+               (< char 32))
+           (push 'control list))
+       (if (or (not (zerop (logand type ?\S-\^@)))
+               (/= char (downcase char)))
+           (push 'shift list))
+       (or (zerop (logand type ?\H-\^@))
+           (push 'hyper list))
+       (or (zerop (logand type ?\s-\^@))
+           (push 'super list))
+       (or (zerop (logand type ?\A-\^@))
+           (push 'alt list))
+       list))))
+
+(defun event-basic-type (event)
+  "Return the basic type of the given event (all modifiers removed).
+The value is a printing character (not upper case) or a symbol.
+EVENT may be an event or an event type.  If EVENT is a symbol
+that has never been used in an event that has been read as input
+in the current Emacs session, then this function may return nil."
+  (if (consp event)
+      (setq event (car event)))
+  (if (symbolp event)
+      (car (get event 'event-symbol-elements))
+    (let* ((base (logand event (1- ?\A-\^@)))
+          (uncontrolled (if (< base 32) (logior base 64) base)))
+      ;; There are some numbers that are invalid characters and
+      ;; cause `downcase' to get an error.
+      (condition-case ()
+         (downcase uncontrolled)
+       (error uncontrolled)))))
+
+(defsubst mouse-movement-p (object)
+  "Return non-nil if OBJECT is a mouse movement event."
+  (eq (car-safe object) 'mouse-movement))
+
+(defun mouse-event-p (object)
+  "Return non-nil if OBJECT is a mouse click event."
+  ;; is this really correct? maybe remove mouse-movement?
+  (memq (event-basic-type object) '(mouse-1 mouse-2 mouse-3 mouse-movement)))
+
+(defun event-start (event)
+  "Return the starting position of EVENT.
+EVENT should be a mouse click, drag, or key press event.  If
+EVENT is nil, the value of `posn-at-point' is used instead.
+
+The following accessor functions are used to access the elements
+of the position:
+
+`posn-window': The window the event is in.
+`posn-area': A symbol identifying the area the event occurred in,
+or nil if the event occurred in the text area.
+`posn-point': The buffer position of the event.
+`posn-x-y': The pixel-based coordinates of the event.
+`posn-col-row': The estimated column and row corresponding to the
+position of the event.
+`posn-actual-col-row': The actual column and row corresponding to the
+position of the event.
+`posn-string': The string object of the event, which is either
+nil or (STRING . POSITION)'.
+`posn-image': The image object of the event, if any.
+`posn-object': The image or string object of the event, if any.
+`posn-timestamp': The time the event occurred, in milliseconds.
+
+For more information, see Info node `(elisp)Click Events'."
+  (if (consp event) (nth 1 event)
+    (or (posn-at-point)
+        (list (selected-window) (point) '(0 . 0) 0))))
+
+(defun event-end (event)
+  "Return the ending position of EVENT.
+EVENT should be a click, drag, or key press event.
+
+See `event-start' for a description of the value returned."
+  (if (consp event) (nth (if (consp (nth 2 event)) 2 1) event)
+    (or (posn-at-point)
+        (list (selected-window) (point) '(0 . 0) 0))))
+
+(defsubst event-click-count (event)
+  "Return the multi-click count of EVENT, a click or drag event.
+The return value is a positive integer."
+  (if (and (consp event) (integerp (nth 2 event))) (nth 2 event) 1))
+
+;;;; Extracting fields of the positions in an event.
+
+(defun posnp (obj)
+  "Return non-nil if OBJ appears to be a valid `posn' object specifying a 
window.
+If OBJ is a valid `posn' object, but specifies a frame rather
+than a window, return nil."
+  ;; FIXME: Correct the behavior of this function so that all valid
+  ;; `posn' objects are recognized, after updating other code that
+  ;; depends on its present behavior.
+  (and (windowp (car-safe obj))
+       (atom (car-safe (setq obj (cdr obj))))                ;AREA-OR-POS.
+       (integerp (car-safe (car-safe (setq obj (cdr obj))))) ;XOFFSET.
+       (integerp (car-safe (cdr obj)))))                     ;TIMESTAMP.
+
+(defsubst posn-window (position)
+  "Return the window in POSITION.
+POSITION should be a list of the form returned by the `event-start'
+and `event-end' functions."
+  (nth 0 position))
+
+(defsubst posn-area (position)
+  "Return the window area recorded in POSITION, or nil for the text area.
+POSITION should be a list of the form returned by the `event-start'
+and `event-end' functions."
+  (let ((area (if (consp (nth 1 position))
+                 (car (nth 1 position))
+               (nth 1 position))))
+    (and (symbolp area) area)))
+
+(defun posn-point (position)
+  "Return the buffer location in POSITION.
+POSITION should be a list of the form returned by the `event-start'
+and `event-end' functions.
+Returns nil if POSITION does not correspond to any buffer location (e.g.
+a click on a scroll bar)."
+  (or (nth 5 position)
+      (let ((pt (nth 1 position)))
+        (or (car-safe pt)
+            ;; Apparently this can also be `vertical-scroll-bar' (bug#13979).
+            (if (integerp pt) pt)))))
+
+(defun posn-set-point (position)
+  "Move point to POSITION.
+Select the corresponding window as well."
+  (if (not (windowp (posn-window position)))
+      (error "Position not in text area of window"))
+  (select-window (posn-window position))
+  (if (numberp (posn-point position))
+      (goto-char (posn-point position))))
+
+(defsubst posn-x-y (position)
+  "Return the x and y coordinates in POSITION.
+The return value has the form (X . Y), where X and Y are given in
+pixels.  POSITION should be a list of the form returned by
+`event-start' and `event-end'."
+  (nth 2 position))
+
+(declare-function scroll-bar-scale "scroll-bar" (num-denom whole))
+
+(defun posn-col-row (position)
+  "Return the nominal column and row in POSITION, measured in characters.
+The column and row values are approximations calculated from the x
+and y coordinates in POSITION and the frame's default character width
+and default line height, including spacing.
+For a scroll-bar event, the result column is 0, and the row
+corresponds to the vertical position of the click in the scroll bar.
+POSITION should be a list of the form returned by the `event-start'
+and `event-end' functions."
+  (let* ((pair            (posn-x-y position))
+         (frame-or-window (posn-window position))
+         (frame           (if (framep frame-or-window)
+                              frame-or-window
+                            (window-frame frame-or-window)))
+         (window          (when (windowp frame-or-window) frame-or-window))
+         (area            (posn-area position)))
+    (cond
+     ((null frame-or-window)
+      '(0 . 0))
+     ((eq area 'vertical-scroll-bar)
+      (cons 0 (scroll-bar-scale pair (1- (window-height window)))))
+     ((eq area 'horizontal-scroll-bar)
+      (cons (scroll-bar-scale pair (window-width window)) 0))
+     (t
+      ;; FIXME: This should take line-spacing properties on
+      ;; newlines into account.
+      (let* ((spacing (when (display-graphic-p frame)
+                        (or (with-current-buffer
+                                (window-buffer (frame-selected-window frame))
+                              line-spacing)
+                            (frame-parameter frame 'line-spacing)))))
+       (cond ((floatp spacing)
+              (setq spacing (truncate (* spacing
+                                         (frame-char-height frame)))))
+             ((null spacing)
+              (setq spacing 0)))
+       (cons (/ (car pair) (frame-char-width frame))
+             (/ (cdr pair) (+ (frame-char-height frame) spacing))))))))
+
+(defun posn-actual-col-row (position)
+  "Return the window row number in POSITION and character number in that row.
+
+Return nil if POSITION does not contain the actual position; in that case
+\`posn-col-row' can be used to get approximate values.
+POSITION should be a list of the form returned by the `event-start'
+and `event-end' functions.
+
+This function does not account for the width on display, like the
+number of visual columns taken by a TAB or image.  If you need
+the coordinates of POSITION in character units, you should use
+\`posn-col-row', not this function."
+  (nth 6 position))
+
+(defsubst posn-timestamp (position)
+  "Return the timestamp of POSITION.
+POSITION should be a list of the form returned by the `event-start'
+and `event-end' functions."
+  (nth 3 position))
+
+(defun posn-string (position)
+  "Return the string object of POSITION.
+Value is a cons (STRING . STRING-POS), or nil if not a string.
+POSITION should be a list of the form returned by the `event-start'
+and `event-end' functions."
+  (let ((x (nth 4 position)))
+    ;; Apparently this can also be `handle' or `below-handle' (bug#13979).
+    (when (consp x) x)))
+
+(defsubst posn-image (position)
+  "Return the image object of POSITION.
+Value is a list (image ...), or nil if not an image.
+POSITION should be a list of the form returned by the `event-start'
+and `event-end' functions."
+  (nth 7 position))
+
+(defsubst posn-object (position)
+  "Return the object (image or string) of POSITION.
+Value is a list (image ...) for an image object, a cons cell
+\(STRING . STRING-POS) for a string object, and nil for a buffer position.
+POSITION should be a list of the form returned by the `event-start'
+and `event-end' functions."
+  (or (posn-image position) (posn-string position)))
+
+(defsubst posn-object-x-y (position)
+  "Return the x and y coordinates relative to the object of POSITION.
+The return value has the form (DX . DY), where DX and DY are
+given in pixels.  POSITION should be a list of the form returned
+by `event-start' and `event-end'."
+  (nth 8 position))
+
+(defsubst posn-object-width-height (position)
+  "Return the pixel width and height of the object of POSITION.
+The return value has the form (WIDTH . HEIGHT).  POSITION should
+be a list of the form returned by `event-start' and `event-end'."
+  (nth 9 position))
+
+
+;;;; Obsolescent names for functions.
+
+(define-obsolete-function-alias 'window-dot 'window-point "22.1")
+(define-obsolete-function-alias 'set-window-dot 'set-window-point "22.1")
+(define-obsolete-function-alias 'read-input 'read-string "22.1")
+(define-obsolete-function-alias 'show-buffer 'set-window-buffer "22.1")
+(define-obsolete-function-alias 'eval-current-buffer 'eval-buffer "22.1")
+(define-obsolete-function-alias 'string-to-int 'string-to-number "22.1")
+
+(make-obsolete 'forward-point "use (+ (point) N) instead." "23.1")
+(make-obsolete 'buffer-has-markers-at nil "24.3")
+
+(defun insert-string (&rest args)
+  "Mocklisp-compatibility insert function.
+Like the function `insert' except that any argument that is a number
+is converted into a string by expressing it in decimal."
+  (declare (obsolete insert "22.1"))
+  (dolist (el args)
+    (insert (if (integerp el) (number-to-string el) el))))
+
+(defun makehash (&optional test)
+  (declare (obsolete make-hash-table "22.1"))
+  (make-hash-table :test (or test 'eql)))
+
+(defun log10 (x)
+  "Return (log X 10), the log base 10 of X."
+  (declare (obsolete log "24.4"))
+  (log x 10))
+
+;; These are used by VM and some old programs
+(defalias 'focus-frame 'ignore "")
+(make-obsolete 'focus-frame "it does nothing." "22.1")
+(defalias 'unfocus-frame 'ignore "")
+(make-obsolete 'unfocus-frame "it does nothing." "22.1")
+(make-obsolete 'make-variable-frame-local
+              "explicitly check for a frame-parameter instead." "22.2")
+(set-advertised-calling-convention
+ 'all-completions '(string collection &optional predicate) "23.1")
+(set-advertised-calling-convention 'unintern '(name obarray) "23.3")
+(set-advertised-calling-convention 'redirect-frame-focus '(frame focus-frame) 
"24.3")
+(set-advertised-calling-convention 'decode-char '(ch charset) "21.4")
+(set-advertised-calling-convention 'encode-char '(ch charset) "21.4")
+
+;;;; Obsolescence declarations for variables, and aliases.
+
+;; Special "default-FOO" variables which contain the default value of
+;; the "FOO" variable are nasty.  Their implementation is brittle, and
+;; slows down several unrelated variable operations; furthermore, they
+;; can lead to really odd behavior if you decide to make them
+;; buffer-local.
+
+;; Not used at all in Emacs, last time I checked:
+(make-obsolete-variable 'default-mode-line-format 'mode-line-format "23.2")
+(make-obsolete-variable 'default-header-line-format 'header-line-format "23.2")
+(make-obsolete-variable 'default-line-spacing 'line-spacing "23.2")
+(make-obsolete-variable 'default-abbrev-mode 'abbrev-mode "23.2")
+(make-obsolete-variable 'default-ctl-arrow 'ctl-arrow "23.2")
+(make-obsolete-variable 'default-truncate-lines 'truncate-lines "23.2")
+(make-obsolete-variable 'default-left-margin 'left-margin "23.2")
+(make-obsolete-variable 'default-tab-width 'tab-width "23.2")
+(make-obsolete-variable 'default-case-fold-search 'case-fold-search "23.2")
+(make-obsolete-variable 'default-left-margin-width 'left-margin-width "23.2")
+(make-obsolete-variable 'default-right-margin-width 'right-margin-width "23.2")
+(make-obsolete-variable 'default-left-fringe-width 'left-fringe-width "23.2")
+(make-obsolete-variable 'default-right-fringe-width 'right-fringe-width "23.2")
+(make-obsolete-variable 'default-fringes-outside-margins 
'fringes-outside-margins "23.2")
+(make-obsolete-variable 'default-scroll-bar-width 'scroll-bar-width "23.2")
+(make-obsolete-variable 'default-vertical-scroll-bar 'vertical-scroll-bar 
"23.2")
+(make-obsolete-variable 'default-indicate-empty-lines 'indicate-empty-lines 
"23.2")
+(make-obsolete-variable 'default-indicate-buffer-boundaries 
'indicate-buffer-boundaries "23.2")
+(make-obsolete-variable 'default-fringe-indicator-alist 
'fringe-indicator-alist "23.2")
+(make-obsolete-variable 'default-fringe-cursor-alist 'fringe-cursor-alist 
"23.2")
+(make-obsolete-variable 'default-scroll-up-aggressively 
'scroll-up-aggressively "23.2")
+(make-obsolete-variable 'default-scroll-down-aggressively 
'scroll-down-aggressively "23.2")
+(make-obsolete-variable 'default-fill-column 'fill-column "23.2")
+(make-obsolete-variable 'default-cursor-type 'cursor-type "23.2")
+(make-obsolete-variable 'default-cursor-in-non-selected-windows 
'cursor-in-non-selected-windows "23.2")
+(make-obsolete-variable 'default-buffer-file-coding-system 
'buffer-file-coding-system "23.2")
+(make-obsolete-variable 'default-major-mode 'major-mode "23.2")
+(make-obsolete-variable 'default-enable-multibyte-characters
+      "use enable-multibyte-characters or set-buffer-multibyte instead" "23.2")
+
+(make-obsolete-variable 'define-key-rebound-commands nil "23.2")
+(make-obsolete-variable 'redisplay-end-trigger-functions 'jit-lock-register 
"23.1")
+(make-obsolete-variable 'deferred-action-list 'post-command-hook "24.1")
+(make-obsolete-variable 'deferred-action-function 'post-command-hook "24.1")
+(make-obsolete-variable 'redisplay-dont-pause nil "24.5")
+(make-obsolete 'window-redisplay-end-trigger nil "23.1")
+(make-obsolete 'set-window-redisplay-end-trigger nil "23.1")
+
+(make-obsolete 'process-filter-multibyte-p nil "23.1")
+(make-obsolete 'set-process-filter-multibyte nil "23.1")
+
+;; Lisp manual only updated in 22.1.
+(define-obsolete-variable-alias 'executing-macro 'executing-kbd-macro
+  "before 19.34")
+
+(define-obsolete-variable-alias 'x-lost-selection-hooks
+  'x-lost-selection-functions "22.1")
+(define-obsolete-variable-alias 'x-sent-selection-hooks
+  'x-sent-selection-functions "22.1")
+
+;; This was introduced in 21.4 for pre-unicode unification.  That
+;; usage was rendered obsolete in 23.1 which uses Unicode internally.
+;; Other uses are possible, so this variable is not _really_ obsolete,
+;; but Stefan insists to mark it so.
+(make-obsolete-variable 'translation-table-for-input nil "23.1")
+
+(defvaralias 'messages-buffer-max-lines 'message-log-max)
+
+;;;; Alternate names for functions - these are not being phased out.
+
+(defalias 'send-string 'process-send-string)
+(defalias 'send-region 'process-send-region)
+(defalias 'string= 'string-equal)
+(defalias 'string< 'string-lessp)
+(defalias 'move-marker 'set-marker)
+(defalias 'rplaca 'setcar)
+(defalias 'rplacd 'setcdr)
+(defalias 'beep 'ding) ;preserve lingual purity
+(defalias 'indent-to-column 'indent-to)
+(defalias 'backward-delete-char 'delete-backward-char)
+(defalias 'search-forward-regexp (symbol-function 're-search-forward))
+(defalias 'search-backward-regexp (symbol-function 're-search-backward))
+(defalias 'int-to-string 'number-to-string)
+(defalias 'store-match-data 'set-match-data)
+(defalias 'chmod 'set-file-modes)
+(defalias 'mkdir 'make-directory)
+;; These are the XEmacs names:
+(defalias 'point-at-eol 'line-end-position)
+(defalias 'point-at-bol 'line-beginning-position)
+
+(defalias 'user-original-login-name 'user-login-name)
+
+
+;;;; Hook manipulation functions.
+
+(defun add-hook (hook function &optional append local)
+  "Add to the value of HOOK the function FUNCTION.
+FUNCTION is not added if already present.
+FUNCTION is added (if necessary) at the beginning of the hook list
+unless the optional argument APPEND is non-nil, in which case
+FUNCTION is added at the end.
+
+The optional fourth argument, LOCAL, if non-nil, says to modify
+the hook's buffer-local value rather than its global value.
+This makes the hook buffer-local, and it makes t a member of the
+buffer-local value.  That acts as a flag to run the hook
+functions of the global value as well as in the local value.
+
+HOOK should be a symbol, and FUNCTION may be any valid function.  If
+HOOK is void, it is first set to nil.  If HOOK's value is a single
+function, it is changed to a list of functions."
+  (or (boundp hook) (set hook nil))
+  (or (default-boundp hook) (set-default hook nil))
+  (if local (unless (local-variable-if-set-p hook)
+             (set (make-local-variable hook) (list t)))
+    ;; Detect the case where make-local-variable was used on a hook
+    ;; and do what we used to do.
+    (unless (and (consp (symbol-value hook)) (memq t (symbol-value hook)))
+      (setq local t)))
+  (let ((hook-value (if local (symbol-value hook) (default-value hook))))
+    ;; If the hook value is a single function, turn it into a list.
+    (when (or (not (listp hook-value)) (functionp hook-value))
+      (setq hook-value (list hook-value)))
+    ;; Do the actual addition if necessary
+    (unless (member function hook-value)
+      (when (stringp function)
+       (setq function (purecopy function)))
+      (setq hook-value
+           (if append
+               (append hook-value (list function))
+             (cons function hook-value))))
+    ;; Set the actual variable
+    (if local
+       (progn
+         ;; If HOOK isn't a permanent local,
+         ;; but FUNCTION wants to survive a change of modes,
+         ;; mark HOOK as partially permanent.
+         (and (symbolp function)
+              (get function 'permanent-local-hook)
+              (not (get hook 'permanent-local))
+              (put hook 'permanent-local 'permanent-local-hook))
+         (set hook hook-value))
+      (set-default hook hook-value))))
+
+(defun remove-hook (hook function &optional local)
+  "Remove from the value of HOOK the function FUNCTION.
+HOOK should be a symbol, and FUNCTION may be any valid function.  If
+FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the
+list of hooks to run in HOOK, then nothing is done.  See `add-hook'.
+
+The optional third argument, LOCAL, if non-nil, says to modify
+the hook's buffer-local value rather than its default value."
+  (or (boundp hook) (set hook nil))
+  (or (default-boundp hook) (set-default hook nil))
+  ;; Do nothing if LOCAL is t but this hook has no local binding.
+  (unless (and local (not (local-variable-p hook)))
+    ;; Detect the case where make-local-variable was used on a hook
+    ;; and do what we used to do.
+    (when (and (local-variable-p hook)
+              (not (and (consp (symbol-value hook))
+                        (memq t (symbol-value hook)))))
+      (setq local t))
+    (let ((hook-value (if local (symbol-value hook) (default-value hook))))
+      ;; Remove the function, for both the list and the non-list cases.
+      (if (or (not (listp hook-value)) (eq (car hook-value) 'lambda))
+         (if (equal hook-value function) (setq hook-value nil))
+       (setq hook-value (delete function (copy-sequence hook-value))))
+      ;; If the function is on the global hook, we need to shadow it locally
+      ;;(when (and local (member function (default-value hook))
+      ;;              (not (member (cons 'not function) hook-value)))
+      ;;  (push (cons 'not function) hook-value))
+      ;; Set the actual variable
+      (if (not local)
+         (set-default hook hook-value)
+       (if (equal hook-value '(t))
+           (kill-local-variable hook)
+         (set hook hook-value))))))
+
+(defmacro letrec (binders &rest body)
+  "Bind variables according to BINDERS then eval BODY.
+The value of the last form in BODY is returned.
+Each element of BINDERS is a list (SYMBOL VALUEFORM) which binds
+SYMBOL to the value of VALUEFORM.
+All symbols are bound before the VALUEFORMs are evalled."
+  ;; Only useful in lexical-binding mode.
+  ;; As a special-form, we could implement it more efficiently (and cleanly,
+  ;; making the vars actually unbound during evaluation of the binders).
+  (declare (debug let) (indent 1))
+  `(let ,(mapcar #'car binders)
+     ,@(mapcar (lambda (binder) `(setq ,@binder)) binders)
+     ,@body))
+
+(defmacro with-wrapper-hook (hook args &rest body)
+  "Run BODY, using wrapper functions from HOOK with additional ARGS.
+HOOK is an abnormal hook.  Each hook function in HOOK \"wraps\"
+around the preceding ones, like a set of nested `around' advices.
+
+Each hook function should accept an argument list consisting of a
+function FUN, followed by the additional arguments in ARGS.
+
+The first hook function in HOOK is passed a FUN that, if it is called
+with arguments ARGS, performs BODY (i.e., the default operation).
+The FUN passed to each successive hook function is defined based
+on the preceding hook functions; if called with arguments ARGS,
+it does what the `with-wrapper-hook' call would do if the
+preceding hook functions were the only ones present in HOOK.
+
+Each hook function may call its FUN argument as many times as it wishes,
+including never.  In that case, such a hook function acts to replace
+the default definition altogether, and any preceding hook functions.
+Of course, a subsequent hook function may do the same thing.
+
+Each hook function definition is used to construct the FUN passed
+to the next hook function, if any.  The last (or \"outermost\")
+FUN is then called once."
+  (declare (indent 2) (debug (form sexp body))
+           (obsolete "use a <foo>-function variable modified by 
`add-function'."
+                     "24.4"))
+  ;; We need those two gensyms because CL's lexical scoping is not available
+  ;; for function arguments :-(
+  (let ((funs (make-symbol "funs"))
+        (global (make-symbol "global"))
+        (argssym (make-symbol "args"))
+        (runrestofhook (make-symbol "runrestofhook")))
+    ;; Since the hook is a wrapper, the loop has to be done via
+    ;; recursion: a given hook function will call its parameter in order to
+    ;; continue looping.
+    `(letrec ((,runrestofhook
+               (lambda (,funs ,global ,argssym)
+                 ;; `funs' holds the functions left on the hook and `global'
+                 ;; holds the functions left on the global part of the hook
+                 ;; (in case the hook is local).
+                 (if (consp ,funs)
+                     (if (eq t (car ,funs))
+                         (funcall ,runrestofhook
+                                  (append ,global (cdr ,funs)) nil ,argssym)
+                       (apply (car ,funs)
+                              (apply-partially
+                               (lambda (,funs ,global &rest ,argssym)
+                                 (funcall ,runrestofhook ,funs ,global 
,argssym))
+                               (cdr ,funs) ,global)
+                              ,argssym))
+                   ;; Once there are no more functions on the hook, run
+                   ;; the original body.
+                   (apply (lambda ,args ,@body) ,argssym)))))
+       (funcall ,runrestofhook ,hook
+                ;; The global part of the hook, if any.
+                ,(if (symbolp hook)
+                     `(if (local-variable-p ',hook)
+                          (default-value ',hook)))
+                (list ,@args)))))
+
+(defun add-to-list (list-var element &optional append compare-fn)
+  "Add ELEMENT to the value of LIST-VAR if it isn't there yet.
+The test for presence of ELEMENT is done with `equal', or with
+COMPARE-FN if that's non-nil.
+If ELEMENT is added, it is added at the beginning of the list,
+unless the optional argument APPEND is non-nil, in which case
+ELEMENT is added at the end.
+
+The return value is the new value of LIST-VAR.
+
+This is handy to add some elements to configuration variables,
+but please do not abuse it in Elisp code, where you are usually
+better off using `push' or `cl-pushnew'.
+
+If you want to use `add-to-list' on a variable that is not
+defined until a certain package is loaded, you should put the
+call to `add-to-list' into a hook function that will be run only
+after loading the package.  `eval-after-load' provides one way to
+do this.  In some cases other hooks, such as major mode hooks,
+can do the job."
+  (declare
+   (compiler-macro
+    (lambda (exp)
+      ;; FIXME: Something like this could be used for `set' as well.
+      (if (or (not (eq 'quote (car-safe list-var)))
+              (special-variable-p (cadr list-var))
+              (not (macroexp-const-p append)))
+          exp
+        (let* ((sym (cadr list-var))
+               (append (eval append))
+               (msg (format "`add-to-list' can't use lexical var `%s'; use 
`push' or `cl-pushnew'"
+                            sym))
+               ;; Big ugly hack so we only output a warning during
+               ;; byte-compilation, and so we can use
+               ;; byte-compile-not-lexical-var-p to silence the warning
+               ;; when a defvar has been seen but not yet executed.
+               (warnfun (lambda ()
+                          ;; FIXME: We should also emit a warning for let-bound
+                          ;; variables with dynamic binding.
+                          (when (assq sym byte-compile--lexical-environment)
+                            (byte-compile-log-warning msg t :error))))
+               (code
+                (macroexp-let2 macroexp-copyable-p x element
+                  `(if ,(if compare-fn
+                            (progn
+                              (require 'cl-lib)
+                              `(cl-member ,x ,sym :test ,compare-fn))
+                          ;; For bootstrapping reasons, don't rely on
+                          ;; cl--compiler-macro-member for the base case.
+                          `(member ,x ,sym))
+                       ,sym
+                     ,(if append
+                          `(setq ,sym (append ,sym (list ,x)))
+                        `(push ,x ,sym))))))
+          (if (not (macroexp--compiling-p))
+              code
+            `(progn
+               (macroexp--funcall-if-compiled ',warnfun)
+               ,code)))))))
+  (if (cond
+       ((null compare-fn)
+       (member element (symbol-value list-var)))
+       ((eq compare-fn 'eq)
+       (memq element (symbol-value list-var)))
+       ((eq compare-fn 'eql)
+       (memql element (symbol-value list-var)))
+       (t
+       (let ((lst (symbol-value list-var)))
+         (while (and lst
+                     (not (funcall compare-fn element (car lst))))
+           (setq lst (cdr lst)))
+          lst)))
+      (symbol-value list-var)
+    (set list-var
+        (if append
+            (append (symbol-value list-var) (list element))
+          (cons element (symbol-value list-var))))))
+
+
+(defun add-to-ordered-list (list-var element &optional order)
+  "Add ELEMENT to the value of LIST-VAR if it isn't there yet.
+The test for presence of ELEMENT is done with `eq'.
+
+The resulting list is reordered so that the elements are in the
+order given by each element's numeric list order.  Elements
+without a numeric list order are placed at the end of the list.
+
+If the third optional argument ORDER is a number (integer or
+float), set the element's list order to the given value.  If
+ORDER is nil or omitted, do not change the numeric order of
+ELEMENT.  If ORDER has any other value, remove the numeric order
+of ELEMENT if it has one.
+
+The list order for each element is stored in LIST-VAR's
+`list-order' property.
+
+The return value is the new value of LIST-VAR."
+  (let ((ordering (get list-var 'list-order)))
+    (unless ordering
+      (put list-var 'list-order
+           (setq ordering (make-hash-table :weakness 'key :test 'eq))))
+    (when order
+      (puthash element (and (numberp order) order) ordering))
+    (unless (memq element (symbol-value list-var))
+      (set list-var (cons element (symbol-value list-var))))
+    (set list-var (sort (symbol-value list-var)
+                       (lambda (a b)
+                         (let ((oa (gethash a ordering))
+                               (ob (gethash b ordering)))
+                           (if (and oa ob)
+                               (< oa ob)
+                             oa)))))))
+
+(defun add-to-history (history-var newelt &optional maxelt keep-all)
+  "Add NEWELT to the history list stored in the variable HISTORY-VAR.
+Return the new history list.
+If MAXELT is non-nil, it specifies the maximum length of the history.
+Otherwise, the maximum history length is the value of the `history-length'
+property on symbol HISTORY-VAR, if set, or the value of the `history-length'
+variable.
+Remove duplicates of NEWELT if `history-delete-duplicates' is non-nil.
+If optional fourth arg KEEP-ALL is non-nil, add NEWELT to history even
+if it is empty or a duplicate."
+  (unless maxelt
+    (setq maxelt (or (get history-var 'history-length)
+                    history-length)))
+  (let ((history (symbol-value history-var))
+       tail)
+    (when (and (listp history)
+              (or keep-all
+                  (not (stringp newelt))
+                  (> (length newelt) 0))
+              (or keep-all
+                  (not (equal (car history) newelt))))
+      (if history-delete-duplicates
+         (setq history (delete newelt history)))
+      (setq history (cons newelt history))
+      (when (integerp maxelt)
+       (if (= 0 maxelt)
+           (setq history nil)
+         (setq tail (nthcdr (1- maxelt) history))
+         (when (consp tail)
+           (setcdr tail nil)))))
+    (set history-var history)))
+
+
+;;;; Mode hooks.
+
+(defvar delay-mode-hooks nil
+  "If non-nil, `run-mode-hooks' should delay running the hooks.")
+(defvar delayed-mode-hooks nil
+  "List of delayed mode hooks waiting to be run.")
+(make-variable-buffer-local 'delayed-mode-hooks)
+(put 'delay-mode-hooks 'permanent-local t)
+
+(defvar change-major-mode-after-body-hook nil
+  "Normal hook run in major mode functions, before the mode hooks.")
+
+(defvar after-change-major-mode-hook nil
+  "Normal hook run at the very end of major mode functions.")
+
+(defun run-mode-hooks (&rest hooks)
+  "Run mode hooks `delayed-mode-hooks' and HOOKS, or delay HOOKS.
+If the variable `delay-mode-hooks' is non-nil, does not run any hooks,
+just adds the HOOKS to the list `delayed-mode-hooks'.
+Otherwise, runs hooks in the sequence: `change-major-mode-after-body-hook',
+`delayed-mode-hooks' (in reverse order), HOOKS, and finally
+`after-change-major-mode-hook'.  Major mode functions should use
+this instead of `run-hooks' when running their FOO-mode-hook."
+  (if delay-mode-hooks
+      ;; Delaying case.
+      (dolist (hook hooks)
+       (push hook delayed-mode-hooks))
+    ;; Normal case, just run the hook as before plus any delayed hooks.
+    (setq hooks (nconc (nreverse delayed-mode-hooks) hooks))
+    (setq delayed-mode-hooks nil)
+    (apply 'run-hooks (cons 'change-major-mode-after-body-hook hooks))
+    (run-hooks 'after-change-major-mode-hook)))
+
+(defmacro delay-mode-hooks (&rest body)
+  "Execute BODY, but delay any `run-mode-hooks'.
+These hooks will be executed by the first following call to
+`run-mode-hooks' that occurs outside any `delayed-mode-hooks' form.
+Only affects hooks run in the current buffer."
+  (declare (debug t) (indent 0))
+  `(progn
+     (make-local-variable 'delay-mode-hooks)
+     (let ((delay-mode-hooks t))
+       ,@body)))
+
+;; PUBLIC: find if the current mode derives from another.
+
+(defun derived-mode-p (&rest modes)
+  "Non-nil if the current major mode is derived from one of MODES.
+Uses the `derived-mode-parent' property of the symbol to trace backwards."
+  (let ((parent major-mode))
+    (while (and (not (memq parent modes))
+               (setq parent (get parent 'derived-mode-parent))))
+    parent))
+
+;;;; Minor modes.
+
+;; If a minor mode is not defined with define-minor-mode,
+;; add it here explicitly.
+;; isearch-mode is deliberately excluded, since you should
+;; not call it yourself.
+(defvar minor-mode-list '(auto-save-mode auto-fill-mode abbrev-mode
+                                        overwrite-mode view-mode
+                                         hs-minor-mode)
+  "List of all minor mode functions.")
+
+(defun add-minor-mode (toggle name &optional keymap after toggle-fun)
+  "Register a new minor mode.
+
+This is an XEmacs-compatibility function.  Use `define-minor-mode' instead.
+
+TOGGLE is a symbol which is the name of a buffer-local variable that
+is toggled on or off to say whether the minor mode is active or not.
+
+NAME specifies what will appear in the mode line when the minor mode
+is active.  NAME should be either a string starting with a space, or a
+symbol whose value is such a string.
+
+Optional KEYMAP is the keymap for the minor mode that will be added
+to `minor-mode-map-alist'.
+
+Optional AFTER specifies that TOGGLE should be added after AFTER
+in `minor-mode-alist'.
+
+Optional TOGGLE-FUN is an interactive function to toggle the mode.
+It defaults to (and should by convention be) TOGGLE.
+
+If TOGGLE has a non-nil `:included' property, an entry for the mode is
+included in the mode-line minor mode menu.
+If TOGGLE has a `:menu-tag', that is used for the menu item's label."
+  (unless (memq toggle minor-mode-list)
+    (push toggle minor-mode-list))
+
+  (unless toggle-fun (setq toggle-fun toggle))
+  (unless (eq toggle-fun toggle)
+    (put toggle :minor-mode-function toggle-fun))
+  ;; Add the name to the minor-mode-alist.
+  (when name
+    (let ((existing (assq toggle minor-mode-alist)))
+      (if existing
+         (setcdr existing (list name))
+       (let ((tail minor-mode-alist) found)
+         (while (and tail (not found))
+           (if (eq after (caar tail))
+               (setq found tail)
+             (setq tail (cdr tail))))
+         (if found
+             (let ((rest (cdr found)))
+               (setcdr found nil)
+               (nconc found (list (list toggle name)) rest))
+           (push (list toggle name) minor-mode-alist))))))
+  ;; Add the toggle to the minor-modes menu if requested.
+  (when (get toggle :included)
+    (define-key mode-line-mode-menu
+      (vector toggle)
+      (list 'menu-item
+           (concat
+            (or (get toggle :menu-tag)
+                (if (stringp name) name (symbol-name toggle)))
+            (let ((mode-name (if (symbolp name) (symbol-value name))))
+              (if (and (stringp mode-name) (string-match "[^ ]+" mode-name))
+                  (concat " (" (match-string 0 mode-name) ")"))))
+           toggle-fun
+           :button (cons :toggle toggle))))
+
+  ;; Add the map to the minor-mode-map-alist.
+  (when keymap
+    (let ((existing (assq toggle minor-mode-map-alist)))
+      (if existing
+         (setcdr existing keymap)
+       (let ((tail minor-mode-map-alist) found)
+         (while (and tail (not found))
+           (if (eq after (caar tail))
+               (setq found tail)
+             (setq tail (cdr tail))))
+         (if found
+             (let ((rest (cdr found)))
+               (setcdr found nil)
+               (nconc found (list (cons toggle keymap)) rest))
+           (push (cons toggle keymap) minor-mode-map-alist)))))))
+
+;;;; Load history
+
+(defsubst autoloadp (object)
+  "Non-nil if OBJECT is an autoload."
+  (eq 'autoload (car-safe object)))
+
+;; (defun autoload-type (object)
+;;   "Returns the type of OBJECT or `function' or `command' if the type is nil.
+;; OBJECT should be an autoload object."
+;;   (when (autoloadp object)
+;;     (let ((type (nth 3 object)))
+;;       (cond ((null type) (if (nth 2 object) 'command 'function))
+;;             ((eq 'keymap t) 'macro)
+;;             (type)))))
+
+;; (defalias 'autoload-file #'cadr
+;;   "Return the name of the file from which AUTOLOAD will be loaded.
+;; \n\(fn AUTOLOAD)")
+
+(defun symbol-file (symbol &optional type)
+  "Return the name of the file that defined SYMBOL.
+The value is normally an absolute file name.  It can also be nil,
+if the definition is not associated with any file.  If SYMBOL
+specifies an autoloaded function, the value can be a relative
+file name without extension.
+
+If TYPE is nil, then any kind of definition is acceptable.  If
+TYPE is `defun', `defvar', or `defface', that specifies function
+definition, variable definition, or face definition only."
+  (if (and (or (null type) (eq type 'defun))
+          (symbolp symbol)
+          (autoloadp (symbol-function symbol)))
+      (nth 1 (symbol-function symbol))
+    (let ((files load-history)
+         file)
+      (while files
+       (if (if type
+               (if (eq type 'defvar)
+                   ;; Variables are present just as their names.
+                   (member symbol (cdr (car files)))
+                 ;; Other types are represented as (TYPE . NAME).
+                 (member (cons type symbol) (cdr (car files))))
+             ;; We accept all types, so look for variable def
+             ;; and then for any other kind.
+             (or (member symbol (cdr (car files)))
+                 (rassq symbol (cdr (car files)))))
+           (setq file (car (car files)) files nil))
+       (setq files (cdr files)))
+      file)))
+
+(defun locate-library (library &optional nosuffix path interactive-call)
+  "Show the precise file name of Emacs library LIBRARY.
+LIBRARY should be a relative file name of the library, a string.
+It can omit the suffix (a.k.a. file-name extension) if NOSUFFIX is
+nil (which is the default, see below).
+This command searches the directories in `load-path' like `\\[load-library]'
+to find the file that `\\[load-library] RET LIBRARY RET' would load.
+Optional second arg NOSUFFIX non-nil means don't add suffixes `load-suffixes'
+to the specified name LIBRARY.
+
+If the optional third arg PATH is specified, that list of directories
+is used instead of `load-path'.
+
+When called from a program, the file name is normally returned as a
+string.  When run interactively, the argument INTERACTIVE-CALL is t,
+and the file name is displayed in the echo area."
+  (interactive (list (completing-read "Locate library: "
+                                     (apply-partially
+                                       'locate-file-completion-table
+                                       load-path (get-load-suffixes)))
+                    nil nil
+                    t))
+  (let ((file (locate-file library
+                          (or path load-path)
+                          (append (unless nosuffix (get-load-suffixes))
+                                  load-file-rep-suffixes))))
+    (if interactive-call
+       (if file
+           (message "Library is file %s" (abbreviate-file-name file))
+         (message "No library %s in search path" library)))
+    file))
+
+
+;;;; Process stuff.
+
+(defun process-lines (program &rest args)
+  "Execute PROGRAM with ARGS, returning its output as a list of lines.
+Signal an error if the program returns with a non-zero exit status."
+  (with-temp-buffer
+    (let ((status (apply 'call-process program nil (current-buffer) nil args)))
+      (unless (eq status 0)
+       (error "%s exited with status %s" program status))
+      (goto-char (point-min))
+      (let (lines)
+       (while (not (eobp))
+         (setq lines (cons (buffer-substring-no-properties
+                            (line-beginning-position)
+                            (line-end-position))
+                           lines))
+         (forward-line 1))
+       (nreverse lines)))))
+
+(defun process-live-p (process)
+  "Returns non-nil if PROCESS is alive.
+A process is considered alive if its status is `run', `open',
+`listen', `connect' or `stop'.  Value is nil if PROCESS is not a
+process."
+  (and (processp process)
+       (memq (process-status process)
+            '(run open listen connect stop))))
+
+;; compatibility
+
+(make-obsolete
+ 'process-kill-without-query
+ "use `process-query-on-exit-flag' or `set-process-query-on-exit-flag'."
+ "22.1")
+(defun process-kill-without-query (process &optional _flag)
+  "Say no query needed if PROCESS is running when Emacs is exited.
+Optional second argument if non-nil says to require a query.
+Value is t if a query was formerly required."
+  (let ((old (process-query-on-exit-flag process)))
+    (set-process-query-on-exit-flag process nil)
+    old))
+
+(defun process-kill-buffer-query-function ()
+  "Ask before killing a buffer that has a running process."
+  (let ((process (get-buffer-process (current-buffer))))
+    (or (not process)
+        (not (memq (process-status process) '(run stop open listen)))
+        (not (process-query-on-exit-flag process))
+        (yes-or-no-p
+        (format "Buffer %S has a running process; kill it? "
+                (buffer-name (current-buffer)))))))
+
+(add-hook 'kill-buffer-query-functions 'process-kill-buffer-query-function)
+
+;; process plist management
+
+(defun process-get (process propname)
+  "Return the value of PROCESS' PROPNAME property.
+This is the last value stored with `(process-put PROCESS PROPNAME VALUE)'."
+  (plist-get (process-plist process) propname))
+
+(defun process-put (process propname value)
+  "Change PROCESS' PROPNAME property to VALUE.
+It can be retrieved with `(process-get PROCESS PROPNAME)'."
+  (set-process-plist process
+                    (plist-put (process-plist process) propname value)))
+
+
+;;;; Input and display facilities.
+
+(defconst read-key-empty-map (make-sparse-keymap))
+
+(defvar read-key-delay 0.01) ;Fast enough for 100Hz repeat rate, hopefully.
+
+(defun read-key (&optional prompt)
+  "Read a key from the keyboard.
+Contrary to `read-event' this will not return a raw event but instead will
+obey the input decoding and translations usually done by `read-key-sequence'.
+So escape sequences and keyboard encoding are taken into account.
+When there's an ambiguity because the key looks like the prefix of
+some sort of escape sequence, the ambiguity is resolved via `read-key-delay'."
+  ;; This overriding-terminal-local-map binding also happens to
+  ;; disable quail's input methods, so although read-key-sequence
+  ;; always inherits the input method, in practice read-key does not
+  ;; inherit the input method (at least not if it's based on quail).
+  (let ((overriding-terminal-local-map nil)
+       (overriding-local-map read-key-empty-map)
+        (echo-keystrokes 0)
+       (old-global-map (current-global-map))
+        (timer (run-with-idle-timer
+                ;; Wait long enough that Emacs has the time to receive and
+                ;; process all the raw events associated with the single-key.
+                ;; But don't wait too long, or the user may find the delay
+                ;; annoying (or keep hitting more keys which may then get
+                ;; lost or misinterpreted).
+                ;; This is only relevant for keys which Emacs perceives as
+                ;; "prefixes", such as C-x (because of the C-x 8 map in
+                ;; key-translate-table and the C-x @ map in function-key-map)
+                ;; or ESC (because of terminal escape sequences in
+                ;; input-decode-map).
+                read-key-delay t
+                (lambda ()
+                  (let ((keys (this-command-keys-vector)))
+                    (unless (zerop (length keys))
+                      ;; `keys' is non-empty, so the user has hit at least
+                      ;; one key; there's no point waiting any longer, even
+                      ;; though read-key-sequence thinks we should wait
+                      ;; for more input to decide how to interpret the
+                      ;; current input.
+                      (throw 'read-key keys)))))))
+    (unwind-protect
+        (progn
+         (use-global-map
+           (let ((map (make-sparse-keymap)))
+             ;; Don't hide the menu-bar and tool-bar entries.
+             (define-key map [menu-bar] (lookup-key global-map [menu-bar]))
+             (define-key map [tool-bar]
+              ;; This hack avoids evaluating the :filter (Bug#9922).
+              (or (cdr (assq 'tool-bar global-map))
+                  (lookup-key global-map [tool-bar])))
+             map))
+         (aref (catch 'read-key (read-key-sequence-vector prompt nil t)) 0))
+      (cancel-timer timer)
+      (use-global-map old-global-map))))
+
+(defvar read-passwd-map
+  ;; BEWARE: `defconst' would purecopy it, breaking the sharing with
+  ;; minibuffer-local-map along the way!
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map minibuffer-local-map)
+    (define-key map "\C-u" #'delete-minibuffer-contents) ;bug#12570
+    map)
+  "Keymap used while reading passwords.")
+
+(defun read-passwd (prompt &optional confirm default)
+  "Read a password, prompting with PROMPT, and return it.
+If optional CONFIRM is non-nil, read the password twice to make sure.
+Optional DEFAULT is a default password to use instead of empty input.
+
+This function echoes `.' for each character that the user types.
+Note that in batch mode, the input is not hidden!
+
+Once the caller uses the password, it can erase the password
+by doing (clear-string STRING)."
+  (if confirm
+      (let (success)
+        (while (not success)
+          (let ((first (read-passwd prompt nil default))
+                (second (read-passwd "Confirm password: " nil default)))
+            (if (equal first second)
+                (progn
+                  (and (arrayp second) (clear-string second))
+                  (setq success first))
+              (and (arrayp first) (clear-string first))
+              (and (arrayp second) (clear-string second))
+              (message "Password not repeated accurately; please start over")
+              (sit-for 1))))
+        success)
+    (let ((hide-chars-fun
+           (lambda (beg end _len)
+             (clear-this-command-keys)
+             (setq beg (min end (max (minibuffer-prompt-end)
+                                     beg)))
+             (dotimes (i (- end beg))
+               (put-text-property (+ i beg) (+ 1 i beg)
+                                  'display (string ?.)))))
+          minibuf)
+      (minibuffer-with-setup-hook
+          (lambda ()
+            (setq minibuf (current-buffer))
+            ;; Turn off electricity.
+            (setq-local post-self-insert-hook nil)
+            (setq-local buffer-undo-list t)
+            (setq-local select-active-regions nil)
+            (use-local-map read-passwd-map)
+            (setq-local inhibit-modification-hooks nil) ;bug#15501.
+           (setq-local show-paren-mode nil)            ;bug#16091.
+            (add-hook 'after-change-functions hide-chars-fun nil 'local))
+        (unwind-protect
+            (let ((enable-recursive-minibuffers t))
+              (read-string
+               (if noninteractive
+                   (format "%s[INPUT WILL NOT BE HIDDEN!] " prompt) ; bug#17839
+                 prompt)
+               nil t default)) ; t = "no history"
+          (when (buffer-live-p minibuf)
+            (with-current-buffer minibuf
+              ;; Not sure why but it seems that there might be cases where the
+              ;; minibuffer is not always properly reset later on, so undo
+              ;; whatever we've done here (bug#11392).
+              (remove-hook 'after-change-functions hide-chars-fun 'local)
+              (kill-local-variable 'post-self-insert-hook)
+              ;; And of course, don't keep the sensitive data around.
+              (erase-buffer))))))))
+
+(defun read-number (prompt &optional default)
+  "Read a numeric value in the minibuffer, prompting with PROMPT.
+DEFAULT specifies a default value to return if the user just types RET.
+The value of DEFAULT is inserted into PROMPT.
+This function is used by the `interactive' code letter `n'."
+  (let ((n nil)
+       (default1 (if (consp default) (car default) default)))
+    (when default1
+      (setq prompt
+           (if (string-match "\\(\\):[ \t]*\\'" prompt)
+               (replace-match (format " (default %s)" default1) t t prompt 1)
+             (replace-regexp-in-string "[ \t]*\\'"
+                                       (format " (default %s) " default1)
+                                       prompt t t))))
+    (while
+       (progn
+         (let ((str (read-from-minibuffer
+                     prompt nil nil nil nil
+                     (when default
+                       (if (consp default)
+                           (mapcar 'number-to-string (delq nil default))
+                         (number-to-string default))))))
+           (condition-case nil
+               (setq n (cond
+                        ((zerop (length str)) default1)
+                        ((stringp str) (read str))))
+             (error nil)))
+         (unless (numberp n)
+           (message "Please enter a number.")
+           (sit-for 1)
+           t)))
+    n))
+
+(defun read-char-choice (prompt chars &optional inhibit-keyboard-quit)
+  "Read and return one of CHARS, prompting for PROMPT.
+Any input that is not one of CHARS is ignored.
+
+If optional argument INHIBIT-KEYBOARD-QUIT is non-nil, ignore
+keyboard-quit events while waiting for a valid input."
+  (unless (consp chars)
+    (error "Called `read-char-choice' without valid char choices"))
+  (let (char done show-help (helpbuf " *Char Help*"))
+    (let ((cursor-in-echo-area t)
+          (executing-kbd-macro executing-kbd-macro)
+         (esc-flag nil))
+      (save-window-excursion         ; in case we call help-form-show
+       (while (not done)
+         (unless (get-text-property 0 'face prompt)
+           (setq prompt (propertize prompt 'face 'minibuffer-prompt)))
+         (setq char (let ((inhibit-quit inhibit-keyboard-quit))
+                      (read-key prompt)))
+         (and show-help (buffer-live-p (get-buffer helpbuf))
+              (kill-buffer helpbuf))
+         (cond
+          ((not (numberp char)))
+          ;; If caller has set help-form, that's enough.
+          ;; They don't explicitly have to add help-char to chars.
+          ((and help-form
+                (eq char help-char)
+                (setq show-help t)
+                (help-form-show)))
+          ((memq char chars)
+           (setq done t))
+          ((and executing-kbd-macro (= char -1))
+           ;; read-event returns -1 if we are in a kbd macro and
+           ;; there are no more events in the macro.  Attempt to
+           ;; get an event interactively.
+           (setq executing-kbd-macro nil))
+          ((not inhibit-keyboard-quit)
+           (cond
+            ((and (null esc-flag) (eq char ?\e))
+             (setq esc-flag t))
+            ((memq char '(?\C-g ?\e))
+             (keyboard-quit))))))))
+    ;; Display the question with the answer.  But without cursor-in-echo-area.
+    (message "%s%s" prompt (char-to-string char))
+    char))
+
+(defun sit-for (seconds &optional nodisp obsolete)
+  "Redisplay, then wait for SECONDS seconds.  Stop when input is available.
+SECONDS may be a floating-point value.
+\(On operating systems that do not support waiting for fractions of a
+second, floating-point values are rounded down to the nearest integer.)
+
+If optional arg NODISP is t, don't redisplay, just wait for input.
+Redisplay does not happen if input is available before it starts.
+
+Value is t if waited the full time with no input arriving, and nil otherwise.
+
+An obsolete, but still supported form is
+\(sit-for SECONDS &optional MILLISECONDS NODISP)
+where the optional arg MILLISECONDS specifies an additional wait period,
+in milliseconds; this was useful when Emacs was built without
+floating point support."
+  (declare (advertised-calling-convention (seconds &optional nodisp) "22.1"))
+  ;; This used to be implemented in C until the following discussion:
+  ;; http://lists.gnu.org/archive/html/emacs-devel/2006-07/msg00401.html
+  ;; Then it was moved here using an implementation based on an idle timer,
+  ;; which was then replaced by the use of read-event.
+  (if (numberp nodisp)
+      (setq seconds (+ seconds (* 1e-3 nodisp))
+            nodisp obsolete)
+    (if obsolete (setq nodisp obsolete)))
+  (cond
+   (noninteractive
+    (sleep-for seconds)
+    t)
+   ((input-pending-p t)
+    nil)
+   ((<= seconds 0)
+    (or nodisp (redisplay)))
+   (t
+    (or nodisp (redisplay))
+    ;; FIXME: we should not read-event here at all, because it's much too
+    ;; difficult to reliably "undo" a read-event by pushing it onto
+    ;; unread-command-events.
+    ;; For bug#14782, we need read-event to do the keyboard-coding-system
+    ;; decoding (hence non-nil as second arg under POSIX ttys).
+    ;; For bug#15614, we need read-event not to inherit-input-method.
+    ;; So we temporarily suspend input-method-function.
+    (let ((read (let ((input-method-function nil))
+                  (read-event nil t seconds))))
+      (or (null read)
+         (progn
+           ;; If last command was a prefix arg, e.g. C-u, push this event onto
+           ;; unread-command-events as (t . EVENT) so it will be added to
+           ;; this-command-keys by read-key-sequence.
+           (if (eq overriding-terminal-local-map universal-argument-map)
+               (setq read (cons t read)))
+           (push read unread-command-events)
+           nil))))))
+
+;; Behind display-popup-menus-p test.
+(declare-function x-popup-dialog "menu.c" (position contents &optional header))
+
+(defun y-or-n-p (prompt)
+  "Ask user a \"y or n\" question.  Return t if answer is \"y\".
+PROMPT is the string to display to ask the question.  It should
+end in a space; `y-or-n-p' adds \"(y or n) \" to it.
+
+No confirmation of the answer is requested; a single character is
+enough.  SPC also means yes, and DEL means no.
+
+To be precise, this function translates user input into responses
+by consulting the bindings in `query-replace-map'; see the
+documentation of that variable for more information.  In this
+case, the useful bindings are `act', `skip', `recenter',
+`scroll-up', `scroll-down', and `quit'.
+An `act' response means yes, and a `skip' response means no.
+A `quit' response means to invoke `keyboard-quit'.
+If the user enters `recenter', `scroll-up', or `scroll-down'
+responses, perform the requested window recentering or scrolling
+and ask again.
+
+Under a windowing system a dialog box will be used if `last-nonmenu-event'
+is nil and `use-dialog-box' is non-nil."
+  ;; ¡Beware! when I tried to edebug this code, Emacs got into a weird state
+  ;; where all the keys were unbound (i.e. it somehow got triggered
+  ;; within read-key, apparently).  I had to kill it.
+  (let ((answer 'recenter)
+       (padded (lambda (prompt &optional dialog)
+                 (let ((l (length prompt)))
+                   (concat prompt
+                           (if (or (zerop l) (eq ?\s (aref prompt (1- l))))
+                               "" " ")
+                           (if dialog "" "(y or n) "))))))
+    (cond
+     (noninteractive
+      (setq prompt (funcall padded prompt))
+      (let ((temp-prompt prompt))
+       (while (not (memq answer '(act skip)))
+         (let ((str (read-string temp-prompt)))
+           (cond ((member str '("y" "Y")) (setq answer 'act))
+                 ((member str '("n" "N")) (setq answer 'skip))
+                 (t (setq temp-prompt (concat "Please answer y or n.  "
+                                              prompt))))))))
+     ((and (display-popup-menus-p)
+          (listp last-nonmenu-event)
+          use-dialog-box)
+      (setq prompt (funcall padded prompt t)
+           answer (x-popup-dialog t `(,prompt ("Yes" . act) ("No" . skip)))))
+     (t
+      (setq prompt (funcall padded prompt))
+      (while
+          (let* ((scroll-actions '(recenter scroll-up scroll-down
+                                  scroll-other-window 
scroll-other-window-down))
+                (key
+                  (let ((cursor-in-echo-area t))
+                    (when minibuffer-auto-raise
+                      (raise-frame (window-frame (minibuffer-window))))
+                    (read-key (propertize (if (memq answer scroll-actions)
+                                              prompt
+                                            (concat "Please answer y or n.  "
+                                                    prompt))
+                                          'face 'minibuffer-prompt)))))
+            (setq answer (lookup-key query-replace-map (vector key) t))
+            (cond
+            ((memq answer '(skip act)) nil)
+            ((eq answer 'recenter)
+             (recenter) t)
+            ((eq answer 'scroll-up)
+             (ignore-errors (scroll-up-command)) t)
+            ((eq answer 'scroll-down)
+             (ignore-errors (scroll-down-command)) t)
+            ((eq answer 'scroll-other-window)
+             (ignore-errors (scroll-other-window)) t)
+            ((eq answer 'scroll-other-window-down)
+             (ignore-errors (scroll-other-window-down)) t)
+            ((or (memq answer '(exit-prefix quit)) (eq key ?\e))
+             (signal 'quit nil) t)
+            (t t)))
+        (ding)
+        (discard-input))))
+    (let ((ret (eq answer 'act)))
+      (unless noninteractive
+        (message "%s%c" prompt (if ret ?y ?n)))
+      ret)))
+
+
+;;; Atomic change groups.
+
+(defmacro atomic-change-group (&rest body)
+  "Perform BODY as an atomic change group.
+This means that if BODY exits abnormally,
+all of its changes to the current buffer are undone.
+This works regardless of whether undo is enabled in the buffer.
+
+This mechanism is transparent to ordinary use of undo;
+if undo is enabled in the buffer and BODY succeeds, the
+user can undo the change normally."
+  (declare (indent 0) (debug t))
+  (let ((handle (make-symbol "--change-group-handle--"))
+       (success (make-symbol "--change-group-success--")))
+    `(let ((,handle (prepare-change-group))
+          ;; Don't truncate any undo data in the middle of this.
+          (undo-outer-limit nil)
+          (undo-limit most-positive-fixnum)
+          (undo-strong-limit most-positive-fixnum)
+          (,success nil))
+       (unwind-protect
+          (progn
+            ;; This is inside the unwind-protect because
+            ;; it enables undo if that was disabled; we need
+            ;; to make sure that it gets disabled again.
+            (activate-change-group ,handle)
+            ,@body
+            (setq ,success t))
+        ;; Either of these functions will disable undo
+        ;; if it was disabled before.
+        (if ,success
+            (accept-change-group ,handle)
+          (cancel-change-group ,handle))))))
+
+(defun prepare-change-group (&optional buffer)
+  "Return a handle for the current buffer's state, for a change group.
+If you specify BUFFER, make a handle for BUFFER's state instead.
+
+Pass the handle to `activate-change-group' afterward to initiate
+the actual changes of the change group.
+
+To finish the change group, call either `accept-change-group' or
+`cancel-change-group' passing the same handle as argument.  Call
+`accept-change-group' to accept the changes in the group as final;
+call `cancel-change-group' to undo them all.  You should use
+`unwind-protect' to make sure the group is always finished.  The call
+to `activate-change-group' should be inside the `unwind-protect'.
+Once you finish the group, don't use the handle again--don't try to
+finish the same group twice.  For a simple example of correct use, see
+the source code of `atomic-change-group'.
+
+The handle records only the specified buffer.  To make a multibuffer
+change group, call this function once for each buffer you want to
+cover, then use `nconc' to combine the returned values, like this:
+
+  (nconc (prepare-change-group buffer-1)
+         (prepare-change-group buffer-2))
+
+You can then activate that multibuffer change group with a single
+call to `activate-change-group' and finish it with a single call
+to `accept-change-group' or `cancel-change-group'."
+
+  (if buffer
+      (list (cons buffer (with-current-buffer buffer buffer-undo-list)))
+    (list (cons (current-buffer) buffer-undo-list))))
+
+(defun activate-change-group (handle)
+  "Activate a change group made with `prepare-change-group' (which see)."
+  (dolist (elt handle)
+    (with-current-buffer (car elt)
+      (if (eq buffer-undo-list t)
+         (setq buffer-undo-list nil)))))
+
+(defun accept-change-group (handle)
+  "Finish a change group made with `prepare-change-group' (which see).
+This finishes the change group by accepting its changes as final."
+  (dolist (elt handle)
+    (with-current-buffer (car elt)
+      (if (eq (cdr elt) t)
+         (setq buffer-undo-list t)))))
+
+(defun cancel-change-group (handle)
+  "Finish a change group made with `prepare-change-group' (which see).
+This finishes the change group by reverting all of its changes."
+  (dolist (elt handle)
+    (with-current-buffer (car elt)
+      (setq elt (cdr elt))
+      (save-restriction
+       ;; Widen buffer temporarily so if the buffer was narrowed within
+       ;; the body of `atomic-change-group' all changes can be undone.
+       (widen)
+       (let ((old-car
+              (if (consp elt) (car elt)))
+             (old-cdr
+              (if (consp elt) (cdr elt))))
+         ;; Temporarily truncate the undo log at ELT.
+         (when (consp elt)
+           (setcar elt nil) (setcdr elt nil))
+         (unless (eq last-command 'undo) (undo-start))
+         ;; Make sure there's no confusion.
+         (when (and (consp elt) (not (eq elt (last pending-undo-list))))
+           (error "Undoing to some unrelated state"))
+         ;; Undo it all.
+         (save-excursion
+           (while (listp pending-undo-list) (undo-more 1)))
+         ;; Reset the modified cons cell ELT to its original content.
+         (when (consp elt)
+           (setcar elt old-car)
+           (setcdr elt old-cdr))
+         ;; Revert the undo info to what it was when we grabbed the state.
+         (setq buffer-undo-list elt))))))
+
+;;;; Display-related functions.
+
+;; For compatibility.
+(define-obsolete-function-alias 'redraw-modeline
+  'force-mode-line-update "24.3")
+
+(defun momentary-string-display (string pos &optional exit-char message)
+  "Momentarily display STRING in the buffer at POS.
+Display remains until next event is input.
+If POS is a marker, only its position is used; its buffer is ignored.
+Optional third arg EXIT-CHAR can be a character, event or event
+description list.  EXIT-CHAR defaults to SPC.  If the input is
+EXIT-CHAR it is swallowed; otherwise it is then available as
+input (as a command if nothing else).
+Display MESSAGE (optional fourth arg) in the echo area.
+If MESSAGE is nil, instructions to type EXIT-CHAR are displayed there."
+  (or exit-char (setq exit-char ?\s))
+  (let ((ol (make-overlay pos pos))
+        (str (copy-sequence string)))
+    (unwind-protect
+        (progn
+          (save-excursion
+            (overlay-put ol 'after-string str)
+            (goto-char pos)
+            ;; To avoid trouble with out-of-bounds position
+            (setq pos (point))
+            ;; If the string end is off screen, recenter now.
+            (if (<= (window-end nil t) pos)
+                (recenter (/ (window-height) 2))))
+          (message (or message "Type %s to continue editing.")
+                   (single-key-description exit-char))
+         (let ((event (read-key)))
+           ;; `exit-char' can be an event, or an event description list.
+           (or (eq event exit-char)
+               (eq event (event-convert-list exit-char))
+               (setq unread-command-events
+                      (append (this-single-command-raw-keys))))))
+      (delete-overlay ol))))
+
+
+;;;; Overlay operations
+
+(defun copy-overlay (o)
+  "Return a copy of overlay O."
+  (let ((o1 (if (overlay-buffer o)
+                (make-overlay (overlay-start o) (overlay-end o)
+                              ;; FIXME: there's no easy way to find the
+                              ;; insertion-type of the two markers.
+                              (overlay-buffer o))
+              (let ((o1 (make-overlay (point-min) (point-min))))
+                (delete-overlay o1)
+                o1)))
+       (props (overlay-properties o)))
+    (while props
+      (overlay-put o1 (pop props) (pop props)))
+    o1))
+
+(defun remove-overlays (&optional beg end name val)
+  "Clear BEG and END of overlays whose property NAME has value VAL.
+Overlays might be moved and/or split.
+BEG and END default respectively to the beginning and end of buffer."
+  ;; This speeds up the loops over overlays.
+  (unless beg (setq beg (point-min)))
+  (unless end (setq end (point-max)))
+  (overlay-recenter end)
+  (if (< end beg)
+      (setq beg (prog1 end (setq end beg))))
+  (save-excursion
+    (dolist (o (overlays-in beg end))
+      (when (eq (overlay-get o name) val)
+       ;; Either push this overlay outside beg...end
+       ;; or split it to exclude beg...end
+       ;; or delete it entirely (if it is contained in beg...end).
+       (if (< (overlay-start o) beg)
+           (if (> (overlay-end o) end)
+               (progn
+                 (move-overlay (copy-overlay o)
+                               (overlay-start o) beg)
+                 (move-overlay o end (overlay-end o)))
+             (move-overlay o (overlay-start o) beg))
+         (if (> (overlay-end o) end)
+             (move-overlay o end (overlay-end o))
+           (delete-overlay o)))))))
+
+;;;; Miscellanea.
+
+(defvar suspend-hook nil
+  "Normal hook run by `suspend-emacs', before suspending.")
+
+(defvar suspend-resume-hook nil
+  "Normal hook run by `suspend-emacs', after Emacs is continued.")
+
+(defvar temp-buffer-show-hook nil
+  "Normal hook run by `with-output-to-temp-buffer' after displaying the buffer.
+When the hook runs, the temporary buffer is current, and the window it
+was displayed in is selected.")
+
+(defvar temp-buffer-setup-hook nil
+  "Normal hook run by `with-output-to-temp-buffer' at the start.
+When the hook runs, the temporary buffer is current.
+This hook is normally set up with a function to put the buffer in Help
+mode.")
+
+(defconst user-emacs-directory
+  (if (eq system-type 'ms-dos)
+      ;; MS-DOS cannot have initial dot.
+      "~/_emacs.d/"
+    "~/.emacs.d/")
+  "Directory beneath which additional per-user Emacs-specific files are placed.
+Various programs in Emacs store information in this directory.
+Note that this should end with a directory separator.
+See also `locate-user-emacs-file'.")
+
+;;;; Misc. useful functions.
+
+(defsubst buffer-narrowed-p ()
+  "Return non-nil if the current buffer is narrowed."
+  (/= (- (point-max) (point-min)) (buffer-size)))
+
+(defun find-tag-default-bounds ()
+  "Determine the boundaries of the default tag, based on text at point.
+Return a cons cell with the beginning and end of the found tag.
+If there is no plausible default, return nil."
+  (let (from to bound)
+    (when (or (progn
+               ;; Look at text around `point'.
+               (save-excursion
+                 (skip-syntax-backward "w_") (setq from (point)))
+               (save-excursion
+                 (skip-syntax-forward "w_") (setq to (point)))
+               (> to from))
+             ;; Look between `line-beginning-position' and `point'.
+             (save-excursion
+               (and (setq bound (line-beginning-position))
+                    (skip-syntax-backward "^w_" bound)
+                    (> (setq to (point)) bound)
+                    (skip-syntax-backward "w_")
+                    (setq from (point))))
+             ;; Look between `point' and `line-end-position'.
+             (save-excursion
+               (and (setq bound (line-end-position))
+                    (skip-syntax-forward "^w_" bound)
+                    (< (setq from (point)) bound)
+                    (skip-syntax-forward "w_")
+                    (setq to (point)))))
+      (cons from to))))
+
+(defun find-tag-default ()
+  "Determine default tag to search for, based on text at point.
+If there is no plausible default, return nil."
+  (let ((bounds (find-tag-default-bounds)))
+    (when bounds
+      (buffer-substring-no-properties (car bounds) (cdr bounds)))))
+
+(defun find-tag-default-as-regexp ()
+  "Return regexp that matches the default tag at point.
+If there is no tag at point, return nil.
+
+When in a major mode that does not provide its own
+`find-tag-default-function', return a regexp that matches the
+symbol at point exactly."
+  (let ((tag (funcall (or find-tag-default-function
+                         (get major-mode 'find-tag-default-function)
+                         'find-tag-default))))
+    (if tag (regexp-quote tag))))
+
+(defun find-tag-default-as-symbol-regexp ()
+  "Return regexp that matches the default tag at point as symbol.
+If there is no tag at point, return nil.
+
+When in a major mode that does not provide its own
+`find-tag-default-function', return a regexp that matches the
+symbol at point exactly."
+  (let ((tag-regexp (find-tag-default-as-regexp)))
+    (if (and tag-regexp
+            (eq (or find-tag-default-function
+                    (get major-mode 'find-tag-default-function)
+                    'find-tag-default)
+                'find-tag-default))
+       (format "\\_<%s\\_>" tag-regexp)
+      tag-regexp)))
+
+(defun play-sound (sound)
+  "SOUND is a list of the form `(sound KEYWORD VALUE...)'.
+The following keywords are recognized:
+
+  :file FILE - read sound data from FILE.  If FILE isn't an
+absolute file name, it is searched in `data-directory'.
+
+  :data DATA - read sound data from string DATA.
+
+Exactly one of :file or :data must be present.
+
+  :volume VOL - set volume to VOL.  VOL must an integer in the
+range 0..100 or a float in the range 0..1.0.  If not specified,
+don't change the volume setting of the sound device.
+
+  :device DEVICE - play sound on DEVICE.  If not specified,
+a system-dependent default device name is used.
+
+Note: :data and :device are currently not supported on Windows."
+  (if (fboundp 'play-sound-internal)
+      (play-sound-internal sound)
+    (error "This Emacs binary lacks sound support")))
+
+(declare-function w32-shell-dos-semantics "w32-fns" nil)
+
+(defun shell-quote-argument (argument)
+  "Quote ARGUMENT for passing as argument to an inferior shell."
+  (cond
+   ((eq system-type 'ms-dos)
+    ;; Quote using double quotes, but escape any existing quotes in
+    ;; the argument with backslashes.
+    (let ((result "")
+          (start 0)
+          end)
+      (if (or (null (string-match "[^\"]" argument))
+              (< (match-end 0) (length argument)))
+          (while (string-match "[\"]" argument start)
+            (setq end (match-beginning 0)
+                  result (concat result (substring argument start end)
+                                 "\\" (substring argument end (1+ end)))
+                  start (1+ end))))
+      (concat "\"" result (substring argument start) "\"")))
+
+   ((and (eq system-type 'windows-nt) (w32-shell-dos-semantics))
+
+    ;; First, quote argument so that CommandLineToArgvW will
+    ;; understand it.  See
+    ;; http://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx
+    ;; After we perform that level of quoting, escape shell
+    ;; metacharacters so that cmd won't mangle our argument.  If the
+    ;; argument contains no double quote characters, we can just
+    ;; surround it with double quotes.  Otherwise, we need to prefix
+    ;; each shell metacharacter with a caret.
+
+    (setq argument
+          ;; escape backslashes at end of string
+          (replace-regexp-in-string
+           "\\(\\\\*\\)$"
+           "\\1\\1"
+           ;; escape backslashes and quotes in string body
+           (replace-regexp-in-string
+            "\\(\\\\*\\)\""
+            "\\1\\1\\\\\""
+            argument)))
+
+    (if (string-match "[%!\"]" argument)
+        (concat
+         "^\""
+         (replace-regexp-in-string
+          "\\([%!()\"<>&|^]\\)"
+          "^\\1"
+          argument)
+         "^\"")
+      (concat "\"" argument "\"")))
+
+   (t
+    (if (equal argument "")
+        "''"
+      ;; Quote everything except POSIX filename characters.
+      ;; This should be safe enough even for really weird shells.
+      (replace-regexp-in-string
+       "\n" "'\n'"
+       (replace-regexp-in-string "[^-0-9a-zA-Z_./\n]" "\\\\\\&" argument))))
+   ))
+
+(defun string-or-null-p (object)
+  "Return t if OBJECT is a string or nil.
+Otherwise, return nil."
+  (or (stringp object) (null object)))
+
+(defun booleanp (object)
+  "Return t if OBJECT is one of the two canonical boolean values: t or nil.
+Otherwise, return nil."
+  (and (memq object '(nil t)) t))
+
+(defun special-form-p (object)
+  "Non-nil if and only if OBJECT is a special form."
+  (if (and (symbolp object) (fboundp object))
+      (setq object (indirect-function object t)))
+  (and (subrp object) (eq (cdr (subr-arity object)) 'unevalled)))
+
+(defun macrop (object)
+  "Non-nil if and only if OBJECT is a macro."
+  (let ((def (indirect-function object t)))
+    (when (consp def)
+      (or (eq 'macro (car def))
+          (and (autoloadp def) (memq (nth 4 def) '(macro t)))))))
+
+(defun field-at-pos (pos)
+  "Return the field at position POS, taking stickiness etc into account."
+  (let ((raw-field (get-char-property (field-beginning pos) 'field)))
+    (if (eq raw-field 'boundary)
+       (get-char-property (1- (field-end pos)) 'field)
+      raw-field)))
+
+(defun sha1 (object &optional start end binary)
+  "Return the SHA1 (Secure Hash Algorithm) of an OBJECT.
+OBJECT is either a string or a buffer.  Optional arguments START and
+END are character positions specifying which portion of OBJECT for
+computing the hash.  If BINARY is non-nil, return a string in binary
+form."
+  (secure-hash 'sha1 object start end binary))
+
+(defalias 'function-put #'put
+  ;; This is only really used in Emacs>24.4, but we add it to 24.4 already, so
+  ;; as to ease the pain when people use future autoload files that contain
+  ;; function-put.
+  "Set function F's property PROP to VALUE.
+The namespace for PROP is shared with symbols.
+So far, F can only be a symbol, not a lambda expression.")
+
+(defun function-get (f prop &optional autoload)
+  "Return the value of property PROP of function F.
+If AUTOLOAD is non-nil and F is autoloaded, try to autoload it
+in the hope that it will set PROP.  If AUTOLOAD is `macro', only do it
+if it's an autoloaded macro."
+  (let ((val nil))
+    (while (and (symbolp f)
+                (null (setq val (get f prop)))
+                (fboundp f))
+      (let ((fundef (symbol-function f)))
+        (if (and autoload (autoloadp fundef)
+                 (not (equal fundef
+                             (autoload-do-load fundef f
+                                               (if (eq autoload 'macro)
+                                                   'macro)))))
+            nil                         ;Re-try `get' on the same `f'.
+          (setq f fundef))))
+    val))
+
+;;;; Support for yanking and text properties.
+;; Why here in subr.el rather than in simple.el?  --Stef
+
+(defvar yank-handled-properties)
+(defvar yank-excluded-properties)
+
+(defun remove-yank-excluded-properties (start end)
+  "Process text properties between START and END, inserted for a `yank'.
+Perform the handling specified by `yank-handled-properties', then
+remove properties specified by `yank-excluded-properties'."
+  (let ((inhibit-read-only t))
+    (dolist (handler yank-handled-properties)
+      (let ((prop (car handler))
+           (fun  (cdr handler))
+           (run-start start))
+       (while (< run-start end)
+         (let ((value (get-text-property run-start prop))
+               (run-end (next-single-property-change
+                         run-start prop nil end)))
+           (funcall fun value run-start run-end)
+           (setq run-start run-end)))))
+    (if (eq yank-excluded-properties t)
+       (set-text-properties start end nil)
+      (remove-list-of-text-properties start end yank-excluded-properties))))
+
+(defvar yank-undo-function)
+
+(defun insert-for-yank (string)
+  "Call `insert-for-yank-1' repetitively for each `yank-handler' segment.
+
+See `insert-for-yank-1' for more details."
+  (let (to)
+    (while (setq to (next-single-property-change 0 'yank-handler string))
+      (insert-for-yank-1 (substring string 0 to))
+      (setq string (substring string to))))
+  (insert-for-yank-1 string))
+
+(defun insert-for-yank-1 (string)
+  "Insert STRING at point for the `yank' command.
+This function is like `insert', except it honors the variables
+`yank-handled-properties' and `yank-excluded-properties', and the
+`yank-handler' text property.
+
+Properties listed in `yank-handled-properties' are processed,
+then those listed in `yank-excluded-properties' are discarded.
+
+If STRING has a non-nil `yank-handler' property on its first
+character, the normal insert behavior is altered.  The value of
+the `yank-handler' property must be a list of one to four
+elements, of the form (FUNCTION PARAM NOEXCLUDE UNDO).
+FUNCTION, if non-nil, should be a function of one argument, an
+ object to insert; it is called instead of `insert'.
+PARAM, if present and non-nil, replaces STRING as the argument to
+ FUNCTION or `insert'; e.g. if FUNCTION is `yank-rectangle', PARAM
+ may be a list of strings to insert as a rectangle.
+If NOEXCLUDE is present and non-nil, the normal removal of
+ `yank-excluded-properties' is not performed; instead FUNCTION is
+ responsible for the removal.  This may be necessary if FUNCTION
+ adjusts point before or after inserting the object.
+UNDO, if present and non-nil, should be a function to be called
+ by `yank-pop' to undo the insertion of the current object.  It is
+ given two arguments, the start and end of the region.  FUNCTION
+ may set `yank-undo-function' to override UNDO."
+  (let* ((handler (and (stringp string)
+                      (get-text-property 0 'yank-handler string)))
+        (param (or (nth 1 handler) string))
+        (opoint (point))
+        (inhibit-read-only inhibit-read-only)
+        end)
+
+    (setq yank-undo-function t)
+    (if (nth 0 handler) ; FUNCTION
+       (funcall (car handler) param)
+      (insert param))
+    (setq end (point))
+
+    ;; Prevent read-only properties from interfering with the
+    ;; following text property changes.
+    (setq inhibit-read-only t)
+
+    (unless (nth 2 handler) ; NOEXCLUDE
+      (remove-yank-excluded-properties opoint end))
+
+    ;; If last inserted char has properties, mark them as rear-nonsticky.
+    (if (and (> end opoint)
+            (text-properties-at (1- end)))
+       (put-text-property (1- end) end 'rear-nonsticky t))
+
+    (if (eq yank-undo-function t)                 ; not set by FUNCTION
+       (setq yank-undo-function (nth 3 handler))) ; UNDO
+    (if (nth 4 handler)                                   ; COMMAND
+       (setq this-command (nth 4 handler)))))
+
+(defun insert-buffer-substring-no-properties (buffer &optional start end)
+  "Insert before point a substring of BUFFER, without text properties.
+BUFFER may be a buffer or a buffer name.
+Arguments START and END are character positions specifying the substring.
+They default to the values of (point-min) and (point-max) in BUFFER."
+  (let ((opoint (point)))
+    (insert-buffer-substring buffer start end)
+    (let ((inhibit-read-only t))
+      (set-text-properties opoint (point) nil))))
+
+(defun insert-buffer-substring-as-yank (buffer &optional start end)
+  "Insert before point a part of BUFFER, stripping some text properties.
+BUFFER may be a buffer or a buffer name.
+Arguments START and END are character positions specifying the substring.
+They default to the values of (point-min) and (point-max) in BUFFER.
+Before insertion, process text properties according to
+`yank-handled-properties' and `yank-excluded-properties'."
+  ;; Since the buffer text should not normally have yank-handler properties,
+  ;; there is no need to handle them here.
+  (let ((opoint (point)))
+    (insert-buffer-substring buffer start end)
+    (remove-yank-excluded-properties opoint (point))))
+
+(defun yank-handle-font-lock-face-property (face start end)
+  "If `font-lock-defaults' is nil, apply FACE as a `face' property.
+START and END denote the start and end of the text to act on.
+Do nothing if FACE is nil."
+  (and face
+       (null font-lock-defaults)
+       (put-text-property start end 'face face)))
+
+;; This removes `mouse-face' properties in *Help* buffer buttons:
+;; http://lists.gnu.org/archive/html/emacs-devel/2002-04/msg00648.html
+(defun yank-handle-category-property (category start end)
+  "Apply property category CATEGORY's properties between START and END."
+  (when category
+    (let ((start2 start))
+      (while (< start2 end)
+       (let ((end2     (next-property-change start2 nil end))
+             (original (text-properties-at start2)))
+         (set-text-properties start2 end2 (symbol-plist category))
+         (add-text-properties start2 end2 original)
+         (setq start2 end2))))))
+
+
+;;;; Synchronous shell commands.
+
+(defun start-process-shell-command (name buffer &rest args)
+  "Start a program in a subprocess.  Return the process object for it.
+NAME is name for process.  It is modified if necessary to make it unique.
+BUFFER is the buffer (or buffer name) to associate with the process.
+ Process output goes at end of that buffer, unless you specify
+ an output stream or filter function to handle the output.
+ BUFFER may be also nil, meaning that this process is not associated
+ with any buffer
+COMMAND is the shell command to run.
+
+An old calling convention accepted any number of arguments after COMMAND,
+which were just concatenated to COMMAND.  This is still supported but strongly
+discouraged."
+  (declare (advertised-calling-convention (name buffer command) "23.1"))
+  ;; We used to use `exec' to replace the shell with the command,
+  ;; but that failed to handle (...) and semicolon, etc.
+  (start-process name buffer shell-file-name shell-command-switch
+                (mapconcat 'identity args " ")))
+
+(defun start-file-process-shell-command (name buffer &rest args)
+  "Start a program in a subprocess.  Return the process object for it.
+Similar to `start-process-shell-command', but calls `start-file-process'."
+  (declare (advertised-calling-convention (name buffer command) "23.1"))
+  (start-file-process
+   name buffer
+   (if (file-remote-p default-directory) "/bin/sh" shell-file-name)
+   (if (file-remote-p default-directory) "-c" shell-command-switch)
+   (mapconcat 'identity args " ")))
+
+(defun call-process-shell-command (command &optional infile buffer display
+                                          &rest args)
+  "Execute the shell command COMMAND synchronously in separate process.
+The remaining arguments are optional.
+The program's input comes from file INFILE (nil means `/dev/null').
+Insert output in BUFFER before point; t means current buffer;
+ nil for BUFFER means discard it; 0 means discard and don't wait.
+BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
+REAL-BUFFER says what to do with standard output, as above,
+while STDERR-FILE says what to do with standard error in the child.
+STDERR-FILE may be nil (discard standard error output),
+t (mix it with ordinary output), or a file name string.
+
+Fourth arg DISPLAY non-nil means redisplay buffer as output is inserted.
+Wildcards and redirection are handled as usual in the shell.
+
+If BUFFER is 0, `call-process-shell-command' returns immediately with value 
nil.
+Otherwise it waits for COMMAND to terminate and returns a numeric exit
+status or a signal description string.
+If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.
+
+An old calling convention accepted any number of arguments after DISPLAY,
+which were just concatenated to COMMAND.  This is still supported but strongly
+discouraged."
+  (declare (advertised-calling-convention
+            (command &optional infile buffer display) "24.5"))
+  ;; We used to use `exec' to replace the shell with the command,
+  ;; but that failed to handle (...) and semicolon, etc.
+  (call-process shell-file-name
+               infile buffer display
+               shell-command-switch
+               (mapconcat 'identity (cons command args) " ")))
+
+(defun process-file-shell-command (command &optional infile buffer display
+                                          &rest args)
+  "Process files synchronously in a separate process.
+Similar to `call-process-shell-command', but calls `process-file'."
+  (declare (advertised-calling-convention
+            (command &optional infile buffer display) "24.5"))
+  (process-file
+   (if (file-remote-p default-directory) "/bin/sh" shell-file-name)
+   infile buffer display
+   (if (file-remote-p default-directory) "-c" shell-command-switch)
+   (mapconcat 'identity (cons command args) " ")))
+
+;;;; Lisp macros to do various things temporarily.
+
+(defmacro with-current-buffer (buffer-or-name &rest body)
+  "Execute the forms in BODY with BUFFER-OR-NAME temporarily current.
+BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
+The value returned is the value of the last form in BODY.  See
+also `with-temp-buffer'."
+  (declare (indent 1) (debug t))
+  `(save-current-buffer
+     (set-buffer ,buffer-or-name)
+     ,@body))
+
+(defun internal--before-with-selected-window (window)
+  (let ((other-frame (window-frame window)))
+    (list window (selected-window)
+          ;; Selecting a window on another frame also changes that
+          ;; frame's frame-selected-window.  We must save&restore it.
+          (unless (eq (selected-frame) other-frame)
+            (frame-selected-window other-frame))
+          ;; Also remember the top-frame if on ttys.
+          (unless (eq (selected-frame) other-frame)
+            (tty-top-frame other-frame)))))
+
+(defun internal--after-with-selected-window (state)
+  ;; First reset frame-selected-window.
+  (when (window-live-p (nth 2 state))
+    ;; We don't use set-frame-selected-window because it does not
+    ;; pass the `norecord' argument to Fselect_window.
+    (select-window (nth 2 state) 'norecord)
+    (and (frame-live-p (nth 3 state))
+         (not (eq (tty-top-frame) (nth 3 state)))
+         (select-frame (nth 3 state) 'norecord)))
+  ;; Then reset the actual selected-window.
+  (when (window-live-p (nth 1 state))
+    (select-window (nth 1 state) 'norecord)))
+
+(defmacro with-selected-window (window &rest body)
+  "Execute the forms in BODY with WINDOW as the selected window.
+The value returned is the value of the last form in BODY.
+
+This macro saves and restores the selected window, as well as the
+selected window of each frame.  It does not change the order of
+recently selected windows.  If the previously selected window of
+some frame is no longer live at the end of BODY, that frame's
+selected window is left alone.  If the selected window is no
+longer live, then whatever window is selected at the end of BODY
+remains selected.
+
+This macro uses `save-current-buffer' to save and restore the
+current buffer, since otherwise its normal operation could
+potentially make a different buffer current.  It does not alter
+the buffer list ordering."
+  (declare (indent 1) (debug t))
+  `(let ((save-selected-window--state
+          (internal--before-with-selected-window ,window)))
+     (save-current-buffer
+       (unwind-protect
+           (progn (select-window (car save-selected-window--state) 'norecord)
+                 ,@body)
+         (internal--after-with-selected-window save-selected-window--state)))))
+
+(defmacro with-selected-frame (frame &rest body)
+  "Execute the forms in BODY with FRAME as the selected frame.
+The value returned is the value of the last form in BODY.
+
+This macro saves and restores the selected frame, and changes the
+order of neither the recently selected windows nor the buffers in
+the buffer list."
+  (declare (indent 1) (debug t))
+  (let ((old-frame (make-symbol "old-frame"))
+       (old-buffer (make-symbol "old-buffer")))
+    `(let ((,old-frame (selected-frame))
+          (,old-buffer (current-buffer)))
+       (unwind-protect
+          (progn (select-frame ,frame 'norecord)
+                 ,@body)
+        (when (frame-live-p ,old-frame)
+          (select-frame ,old-frame 'norecord))
+        (when (buffer-live-p ,old-buffer)
+          (set-buffer ,old-buffer))))))
+
+(defmacro save-window-excursion (&rest body)
+  "Execute BODY, then restore previous window configuration.
+This macro saves the window configuration on the selected frame,
+executes BODY, then calls `set-window-configuration' to restore
+the saved window configuration.  The return value is the last
+form in BODY.  The window configuration is also restored if BODY
+exits nonlocally.
+
+BEWARE: Most uses of this macro introduce bugs.
+E.g. it should not be used to try and prevent some code from opening
+a new window, since that window may sometimes appear in another frame,
+in which case `save-window-excursion' cannot help."
+  (declare (indent 0) (debug t))
+  (let ((c (make-symbol "wconfig")))
+    `(let ((,c (current-window-configuration)))
+       (unwind-protect (progn ,@body)
+         (set-window-configuration ,c)))))
+
+(defun internal-temp-output-buffer-show (buffer)
+  "Internal function for `with-output-to-temp-buffer'."
+  (with-current-buffer buffer
+    (set-buffer-modified-p nil)
+    (goto-char (point-min)))
+
+  (if temp-buffer-show-function
+      (funcall temp-buffer-show-function buffer)
+    (with-current-buffer buffer
+      (let* ((window
+             (let ((window-combination-limit
+                  ;; When `window-combination-limit' equals
+                  ;; `temp-buffer' or `temp-buffer-resize' and
+                  ;; `temp-buffer-resize-mode' is enabled in this
+                  ;; buffer bind it to t so resizing steals space
+                  ;; preferably from the window that was split.
+                  (if (or (eq window-combination-limit 'temp-buffer)
+                          (and (eq window-combination-limit
+                                   'temp-buffer-resize)
+                               temp-buffer-resize-mode))
+                      t
+                    window-combination-limit)))
+               (display-buffer buffer)))
+            (frame (and window (window-frame window))))
+       (when window
+         (unless (eq frame (selected-frame))
+           (make-frame-visible frame))
+         (setq minibuffer-scroll-window window)
+         (set-window-hscroll window 0)
+         ;; Don't try this with NOFORCE non-nil!
+         (set-window-start window (point-min) t)
+         ;; This should not be necessary.
+         (set-window-point window (point-min))
+         ;; Run `temp-buffer-show-hook', with the chosen window selected.
+         (with-selected-window window
+           (run-hooks 'temp-buffer-show-hook))))))
+  ;; Return nil.
+  nil)
+
+;; Doc is very similar to with-temp-buffer-window.
+(defmacro with-output-to-temp-buffer (bufname &rest body)
+  "Bind `standard-output' to buffer BUFNAME, eval BODY, then show that buffer.
+
+This construct makes buffer BUFNAME empty before running BODY.
+It does not make the buffer current for BODY.
+Instead it binds `standard-output' to that buffer, so that output
+generated with `prin1' and similar functions in BODY goes into
+the buffer.
+
+At the end of BODY, this marks buffer BUFNAME unmodified and displays
+it in a window, but does not select it.  The normal way to do this is
+by calling `display-buffer', then running `temp-buffer-show-hook'.
+However, if `temp-buffer-show-function' is non-nil, it calls that
+function instead (and does not run `temp-buffer-show-hook').  The
+function gets one argument, the buffer to display.
+
+The return value of `with-output-to-temp-buffer' is the value of the
+last form in BODY.  If BODY does not finish normally, the buffer
+BUFNAME is not displayed.
+
+This runs the hook `temp-buffer-setup-hook' before BODY,
+with the buffer BUFNAME temporarily current.  It runs the hook
+`temp-buffer-show-hook' after displaying buffer BUFNAME, with that
+buffer temporarily current, and the window that was used to display it
+temporarily selected.  But it doesn't run `temp-buffer-show-hook'
+if it uses `temp-buffer-show-function'.
+
+By default, the setup hook puts the buffer into Help mode before running BODY.
+If BODY does not change the major mode, the show hook makes the buffer
+read-only, and scans it for function and variable names to make them into
+clickable cross-references.
+
+See the related form `with-temp-buffer-window'."
+  (declare (debug t))
+  (let ((old-dir (make-symbol "old-dir"))
+        (buf (make-symbol "buf")))
+    `(let* ((,old-dir default-directory)
+            (,buf
+             (with-current-buffer (get-buffer-create ,bufname)
+               (prog1 (current-buffer)
+                 (kill-all-local-variables)
+                 ;; FIXME: delete_all_overlays
+                 (setq default-directory ,old-dir)
+                 (setq buffer-read-only nil)
+                 (setq buffer-file-name nil)
+                 (setq buffer-undo-list t)
+                 (let ((inhibit-read-only t)
+                       (inhibit-modification-hooks t))
+                   (erase-buffer)
+                   (run-hooks 'temp-buffer-setup-hook)))))
+            (standard-output ,buf))
+       (prog1 (progn ,@body)
+         (internal-temp-output-buffer-show ,buf)))))
+
+(defmacro with-temp-file (file &rest body)
+  "Create a new buffer, evaluate BODY there, and write the buffer to FILE.
+The value returned is the value of the last form in BODY.
+See also `with-temp-buffer'."
+  (declare (indent 1) (debug t))
+  (let ((temp-file (make-symbol "temp-file"))
+       (temp-buffer (make-symbol "temp-buffer")))
+    `(let ((,temp-file ,file)
+          (,temp-buffer
+           (get-buffer-create (generate-new-buffer-name " *temp file*"))))
+       (unwind-protect
+          (prog1
+              (with-current-buffer ,temp-buffer
+                ,@body)
+            (with-current-buffer ,temp-buffer
+              (write-region nil nil ,temp-file nil 0)))
+        (and (buffer-name ,temp-buffer)
+             (kill-buffer ,temp-buffer))))))
+
+(defmacro with-temp-message (message &rest body)
+  "Display MESSAGE temporarily if non-nil while BODY is evaluated.
+The original message is restored to the echo area after BODY has finished.
+The value returned is the value of the last form in BODY.
+MESSAGE is written to the message log buffer if `message-log-max' is non-nil.
+If MESSAGE is nil, the echo area and message log buffer are unchanged.
+Use a MESSAGE of \"\" to temporarily clear the echo area."
+  (declare (debug t) (indent 1))
+  (let ((current-message (make-symbol "current-message"))
+       (temp-message (make-symbol "with-temp-message")))
+    `(let ((,temp-message ,message)
+          (,current-message))
+       (unwind-protect
+          (progn
+            (when ,temp-message
+              (setq ,current-message (current-message))
+              (message "%s" ,temp-message))
+            ,@body)
+        (and ,temp-message
+             (if ,current-message
+                 (message "%s" ,current-message)
+               (message nil)))))))
+
+(defmacro with-temp-buffer (&rest body)
+  "Create a temporary buffer, and evaluate BODY there like `progn'.
+See also `with-temp-file' and `with-output-to-string'."
+  (declare (indent 0) (debug t))
+  (let ((temp-buffer (make-symbol "temp-buffer")))
+    `(let ((,temp-buffer (generate-new-buffer " *temp*")))
+       ;; FIXME: kill-buffer can change current-buffer in some odd cases.
+       (with-current-buffer ,temp-buffer
+         (unwind-protect
+            (progn ,@body)
+           (and (buffer-name ,temp-buffer)
+                (kill-buffer ,temp-buffer)))))))
+
+(defmacro with-silent-modifications (&rest body)
+  "Execute BODY, pretending it does not modify the buffer.
+If BODY performs real modifications to the buffer's text, other
+than cosmetic ones, undo data may become corrupted.
+
+This macro will run BODY normally, but doesn't count its buffer
+modifications as being buffer modifications.  This affects things
+like `buffer-modified-p', checking whether the file is locked by
+someone else, running buffer modification hooks, and other things
+of that nature.
+
+Typically used around modifications of text-properties which do
+not really affect the buffer's content."
+  (declare (debug t) (indent 0))
+  (let ((modified (make-symbol "modified")))
+    `(let* ((,modified (buffer-modified-p))
+            (buffer-undo-list t)
+            (inhibit-read-only t)
+            (inhibit-modification-hooks t)
+            deactivate-mark
+            ;; Avoid setting and removing file locks and checking
+            ;; buffer's uptodate-ness w.r.t the underlying file.
+            buffer-file-name
+            buffer-file-truename)
+       (unwind-protect
+           (progn
+             ,@body)
+         (unless ,modified
+           (restore-buffer-modified-p nil))))))
+
+(defmacro with-output-to-string (&rest body)
+  "Execute BODY, return the text it sent to `standard-output', as a string."
+  (declare (indent 0) (debug t))
+  `(let ((standard-output
+         (get-buffer-create (generate-new-buffer-name " *string-output*"))))
+     (unwind-protect
+        (progn
+          (let ((standard-output standard-output))
+            ,@body)
+          (with-current-buffer standard-output
+            (buffer-string)))
+       (kill-buffer standard-output))))
+
+(defmacro with-local-quit (&rest body)
+  "Execute BODY, allowing quits to terminate BODY but not escape further.
+When a quit terminates BODY, `with-local-quit' returns nil but
+requests another quit.  That quit will be processed as soon as quitting
+is allowed once again.  (Immediately, if `inhibit-quit' is nil.)"
+  (declare (debug t) (indent 0))
+  `(condition-case nil
+       (let ((inhibit-quit nil))
+        ,@body)
+     (quit (setq quit-flag t)
+          ;; This call is to give a chance to handle quit-flag
+          ;; in case inhibit-quit is nil.
+          ;; Without this, it will not be handled until the next function
+          ;; call, and that might allow it to exit thru a condition-case
+          ;; that intends to handle the quit signal next time.
+          (eval '(ignore nil)))))
+
+(defmacro while-no-input (&rest body)
+  "Execute BODY only as long as there's no pending input.
+If input arrives, that ends the execution of BODY,
+and `while-no-input' returns t.  Quitting makes it return nil.
+If BODY finishes, `while-no-input' returns whatever value BODY produced."
+  (declare (debug t) (indent 0))
+  (let ((catch-sym (make-symbol "input")))
+    `(with-local-quit
+       (catch ',catch-sym
+        (let ((throw-on-input ',catch-sym))
+          (or (input-pending-p)
+              (progn ,@body)))))))
+
+(defmacro condition-case-unless-debug (var bodyform &rest handlers)
+  "Like `condition-case' except that it does not prevent debugging.
+More specifically if `debug-on-error' is set then the debugger will be invoked
+even if this catches the signal."
+  (declare (debug condition-case) (indent 2))
+  `(condition-case ,var
+       ,bodyform
+     ,@(mapcar (lambda (handler)
+                 `((debug ,@(if (listp (car handler)) (car handler)
+                              (list (car handler))))
+                   ,@(cdr handler)))
+               handlers)))
+
+(define-obsolete-function-alias 'condition-case-no-debug
+  'condition-case-unless-debug "24.1")
+
+(defmacro with-demoted-errors (format &rest body)
+  "Run BODY and demote any errors to simple messages.
+FORMAT is a string passed to `message' to format any error message.
+It should contain a single %-sequence; e.g., \"Error: %S\".
+
+If `debug-on-error' is non-nil, run BODY without catching its errors.
+This is to be used around code which is not expected to signal an error
+but which should be robust in the unexpected case that an error is signaled.
+
+For backward compatibility, if FORMAT is not a constant string, it
+is assumed to be part of BODY, in which case the message format
+used is \"Error: %S\"."
+  (declare (debug t) (indent 1))
+  (let ((err (make-symbol "err"))
+        (format (if (and (stringp format) body) format
+                  (prog1 "Error: %S"
+                    (if format (push format body))))))
+    `(condition-case-unless-debug ,err
+         ,(macroexp-progn body)
+       (error (message ,format ,err) nil))))
+
+(defmacro combine-after-change-calls (&rest body)
+  "Execute BODY, but don't call the after-change functions till the end.
+If BODY makes changes in the buffer, they are recorded
+and the functions on `after-change-functions' are called several times
+when BODY is finished.
+The return value is the value of the last form in BODY.
+
+If `before-change-functions' is non-nil, then calls to the after-change
+functions can't be deferred, so in that case this macro has no effect.
+
+Do not alter `after-change-functions' or `before-change-functions'
+in BODY."
+  (declare (indent 0) (debug t))
+  `(unwind-protect
+       (let ((combine-after-change-calls t))
+        . ,body)
+     (combine-after-change-execute)))
+
+(defmacro with-case-table (table &rest body)
+  "Execute the forms in BODY with TABLE as the current case table.
+The value returned is the value of the last form in BODY."
+  (declare (indent 1) (debug t))
+  (let ((old-case-table (make-symbol "table"))
+       (old-buffer (make-symbol "buffer")))
+    `(let ((,old-case-table (current-case-table))
+          (,old-buffer (current-buffer)))
+       (unwind-protect
+          (progn (set-case-table ,table)
+                 ,@body)
+        (with-current-buffer ,old-buffer
+          (set-case-table ,old-case-table))))))
+
+;;; Matching and match data.
+
+(defvar save-match-data-internal)
+
+;; We use save-match-data-internal as the local variable because
+;; that works ok in practice (people should not use that variable elsewhere).
+;; We used to use an uninterned symbol; the compiler handles that properly
+;; now, but it generates slower code.
+(defmacro save-match-data (&rest body)
+  "Execute the BODY forms, restoring the global value of the match data.
+The value returned is the value of the last form in BODY."
+  ;; It is better not to use backquote here,
+  ;; because that makes a bootstrapping problem
+  ;; if you need to recompile all the Lisp files using interpreted code.
+  (declare (indent 0) (debug t))
+  (list 'let
+       '((save-match-data-internal (match-data)))
+       (list 'unwind-protect
+             (cons 'progn body)
+             ;; It is safe to free (evaporate) markers immediately here,
+             ;; as Lisp programs should not copy from save-match-data-internal.
+             '(set-match-data save-match-data-internal 'evaporate))))
+
+(defun match-string (num &optional string)
+  "Return string of text matched by last search.
+NUM specifies which parenthesized expression in the last regexp.
+ Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
+Zero means the entire text matched by the whole regexp or whole string.
+STRING should be given if the last search was by `string-match' on STRING.
+If STRING is nil, the current buffer should be the same buffer
+the search/match was performed in."
+  (if (match-beginning num)
+      (if string
+         (substring string (match-beginning num) (match-end num))
+       (buffer-substring (match-beginning num) (match-end num)))))
+
+(defun match-string-no-properties (num &optional string)
+  "Return string of text matched by last search, without text properties.
+NUM specifies which parenthesized expression in the last regexp.
+ Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
+Zero means the entire text matched by the whole regexp or whole string.
+STRING should be given if the last search was by `string-match' on STRING.
+If STRING is nil, the current buffer should be the same buffer
+the search/match was performed in."
+  (if (match-beginning num)
+      (if string
+         (substring-no-properties string (match-beginning num)
+                                  (match-end num))
+       (buffer-substring-no-properties (match-beginning num)
+                                       (match-end num)))))
+
+
+(defun match-substitute-replacement (replacement
+                                    &optional fixedcase literal string subexp)
+  "Return REPLACEMENT as it will be inserted by `replace-match'.
+In other words, all back-references in the form `\\&' and `\\N'
+are substituted with actual strings matched by the last search.
+Optional FIXEDCASE, LITERAL, STRING and SUBEXP have the same
+meaning as for `replace-match'."
+  (let ((match (match-string 0 string)))
+    (save-match-data
+      (set-match-data (mapcar (lambda (x)
+                               (if (numberp x)
+                                   (- x (match-beginning 0))
+                                 x))
+                             (match-data t)))
+      (replace-match replacement fixedcase literal match subexp))))
+
+
+(defun looking-back (regexp &optional limit greedy)
+  "Return non-nil if text before point matches regular expression REGEXP.
+Like `looking-at' except matches before point, and is slower.
+LIMIT if non-nil speeds up the search by specifying a minimum
+starting position, to avoid checking matches that would start
+before LIMIT.
+
+If GREEDY is non-nil, extend the match backwards as far as
+possible, stopping when a single additional previous character
+cannot be part of a match for REGEXP.  When the match is
+extended, its starting position is allowed to occur before
+LIMIT.
+
+As a general recommendation, try to avoid using `looking-back'
+wherever possible, since it is slow."
+  (let ((start (point))
+       (pos
+        (save-excursion
+          (and (re-search-backward (concat "\\(?:" regexp "\\)\\=") limit t)
+               (point)))))
+    (if (and greedy pos)
+       (save-restriction
+         (narrow-to-region (point-min) start)
+         (while (and (> pos (point-min))
+                     (save-excursion
+                       (goto-char pos)
+                       (backward-char 1)
+                       (looking-at (concat "\\(?:"  regexp "\\)\\'"))))
+           (setq pos (1- pos)))
+         (save-excursion
+           (goto-char pos)
+           (looking-at (concat "\\(?:"  regexp "\\)\\'")))))
+    (not (null pos))))
+
+(defsubst looking-at-p (regexp)
+  "\
+Same as `looking-at' except this function does not change the match data."
+  (let ((inhibit-changing-match-data t))
+    (looking-at regexp)))
+
+(defsubst string-match-p (regexp string &optional start)
+  "\
+Same as `string-match' except this function does not change the match data."
+  (let ((inhibit-changing-match-data t))
+    (string-match regexp string start)))
+
+(defun subregexp-context-p (regexp pos &optional start)
+  "Return non-nil if POS is in a normal subregexp context in REGEXP.
+A subregexp context is one where a sub-regexp can appear.
+A non-subregexp context is for example within brackets, or within a
+repetition bounds operator `\\=\\{...\\}', or right after a `\\'.
+If START is non-nil, it should be a position in REGEXP, smaller
+than POS, and known to be in a subregexp context."
+  ;; Here's one possible implementation, with the great benefit that it
+  ;; reuses the regexp-matcher's own parser, so it understands all the
+  ;; details of the syntax.  A disadvantage is that it needs to match the
+  ;; error string.
+  (condition-case err
+      (progn
+        (string-match (substring regexp (or start 0) pos) "")
+        t)
+    (invalid-regexp
+     (not (member (cadr err) '("Unmatched [ or [^"
+                               "Unmatched \\{"
+                               "Trailing backslash")))))
+  ;; An alternative implementation:
+  ;; (defconst re-context-re
+  ;;   (let* ((harmless-ch "[^\\[]")
+  ;;          (harmless-esc "\\\\[^{]")
+  ;;          (class-harmless-ch "[^][]")
+  ;;          (class-lb-harmless "[^]:]")
+  ;;          (class-lb-colon-maybe-charclass ":\\([a-z]+:]\\)?")
+  ;;          (class-lb (concat "\\[\\(" class-lb-harmless
+  ;;                            "\\|" class-lb-colon-maybe-charclass "\\)"))
+  ;;          (class
+  ;;           (concat "\\[^?]?"
+  ;;                   "\\(" class-harmless-ch
+  ;;                   "\\|" class-lb "\\)*"
+  ;;                   "\\[?]"))     ; special handling for bare [ at end of re
+  ;;          (braces "\\\\{[0-9,]+\\\\}"))
+  ;;     (concat "\\`\\(" harmless-ch "\\|" harmless-esc
+  ;;             "\\|" class "\\|" braces "\\)*\\'"))
+  ;;   "Matches any prefix that corresponds to a normal subregexp context.")
+  ;; (string-match re-context-re (substring regexp (or start 0) pos))
+  )
+
+;;;; split-string
+
+(defconst split-string-default-separators "[ \f\t\n\r\v]+"
+  "The default value of separators for `split-string'.
+
+A regexp matching strings of whitespace.  May be locale-dependent
+\(as yet unimplemented).  Should not match non-breaking spaces.
+
+Warning: binding this to a different value and using it as default is
+likely to have undesired semantics.")
+
+;; The specification says that if both SEPARATORS and OMIT-NULLS are
+;; defaulted, OMIT-NULLS should be treated as t.  Simplifying the logical
+;; expression leads to the equivalent implementation that if SEPARATORS
+;; is defaulted, OMIT-NULLS is treated as t.
+(defun split-string (string &optional separators omit-nulls trim)
+  "Split STRING into substrings bounded by matches for SEPARATORS.
+
+The beginning and end of STRING, and each match for SEPARATORS, are
+splitting points.  The substrings matching SEPARATORS are removed, and
+the substrings between the splitting points are collected as a list,
+which is returned.
+
+If SEPARATORS is non-nil, it should be a regular expression matching text
+which separates, but is not part of, the substrings.  If nil it defaults to
+`split-string-default-separators', normally \"[ \\f\\t\\n\\r\\v]+\", and
+OMIT-NULLS is forced to t.
+
+If OMIT-NULLS is t, zero-length substrings are omitted from the list (so
+that for the default value of SEPARATORS leading and trailing whitespace
+are effectively trimmed).  If nil, all zero-length substrings are retained,
+which correctly parses CSV format, for example.
+
+If TRIM is non-nil, it should be a regular expression to match
+text to trim from the beginning and end of each substring.  If trimming
+makes the substring empty, it is treated as null.
+
+If you want to trim whitespace from the substrings, the reliably correct
+way is using TRIM.  Making SEPARATORS match that whitespace gives incorrect
+results when there is whitespace at the start or end of STRING.  If you
+see such calls to `split-string', please fix them.
+
+Note that the effect of `(split-string STRING)' is the same as
+`(split-string STRING split-string-default-separators t)'.  In the rare
+case that you wish to retain zero-length substrings when splitting on
+whitespace, use `(split-string STRING split-string-default-separators)'.
+
+Modifies the match data; use `save-match-data' if necessary."
+  (let* ((keep-nulls (not (if separators omit-nulls t)))
+        (rexp (or separators split-string-default-separators))
+        (start 0)
+        this-start this-end
+        notfirst
+        (list nil)
+        (push-one
+         ;; Push the substring in range THIS-START to THIS-END
+         ;; onto LIST, trimming it and perhaps discarding it.
+         (lambda ()
+           (when trim
+             ;; Discard the trim from start of this substring.
+             (let ((tem (string-match trim string this-start)))
+               (and (eq tem this-start)
+                    (setq this-start (match-end 0)))))
+
+           (when (or keep-nulls (< this-start this-end))
+             (let ((this (substring string this-start this-end)))
+
+               ;; Discard the trim from end of this substring.
+               (when trim
+                 (let ((tem (string-match (concat trim "\\'") this 0)))
+                   (and tem (< tem (length this))
+                        (setq this (substring this 0 tem)))))
+
+               ;; Trimming could make it empty; check again.
+               (when (or keep-nulls (> (length this) 0))
+                 (push this list)))))))
+
+    (while (and (string-match rexp string
+                             (if (and notfirst
+                                      (= start (match-beginning 0))
+                                      (< start (length string)))
+                                 (1+ start) start))
+               (< start (length string)))
+      (setq notfirst t)
+      (setq this-start start this-end (match-beginning 0)
+           start (match-end 0))
+
+      (funcall push-one))
+
+    ;; Handle the substring at the end of STRING.
+    (setq this-start start this-end (length string))
+    (funcall push-one)
+
+    (nreverse list)))
+
+(defun combine-and-quote-strings (strings &optional separator)
+  "Concatenate the STRINGS, adding the SEPARATOR (default \" \").
+This tries to quote the strings to avoid ambiguity such that
+  (split-string-and-unquote (combine-and-quote-strings strs)) == strs
+Only some SEPARATORs will work properly."
+  (let* ((sep (or separator " "))
+         (re (concat "[\\\"]" "\\|" (regexp-quote sep))))
+    (mapconcat
+     (lambda (str)
+       (if (string-match re str)
+          (concat "\"" (replace-regexp-in-string "[\\\"]" "\\\\\\&" str) "\"")
+        str))
+     strings sep)))
+
+(defun split-string-and-unquote (string &optional separator)
+  "Split the STRING into a list of strings.
+It understands Emacs Lisp quoting within STRING, such that
+  (split-string-and-unquote (combine-and-quote-strings strs)) == strs
+The SEPARATOR regexp defaults to \"\\s-+\"."
+  (let ((sep (or separator "\\s-+"))
+       (i (string-match "\"" string)))
+    (if (null i)
+       (split-string string sep t)     ; no quoting:  easy
+      (append (unless (eq i 0) (split-string (substring string 0 i) sep t))
+             (let ((rfs (read-from-string string i)))
+               (cons (car rfs)
+                     (split-string-and-unquote (substring string (cdr rfs))
+                                               sep)))))))
+
+
+;;;; Replacement in strings.
+
+(defun subst-char-in-string (fromchar tochar string &optional inplace)
+  "Replace FROMCHAR with TOCHAR in STRING each time it occurs.
+Unless optional argument INPLACE is non-nil, return a new string."
+  (let ((i (length string))
+       (newstr (if inplace string (copy-sequence string))))
+    (while (> i 0)
+      (setq i (1- i))
+      (if (eq (aref newstr i) fromchar)
+         (aset newstr i tochar)))
+    newstr))
+
+(defun replace-regexp-in-string (regexp rep string &optional
+                                       fixedcase literal subexp start)
+  "Replace all matches for REGEXP with REP in STRING.
+
+Return a new string containing the replacements.
+
+Optional arguments FIXEDCASE, LITERAL and SUBEXP are like the
+arguments with the same names of function `replace-match'.  If START
+is non-nil, start replacements at that index in STRING.
+
+REP is either a string used as the NEWTEXT arg of `replace-match' or a
+function.  If it is a function, it is called with the actual text of each
+match, and its value is used as the replacement text.  When REP is called,
+the match data are the result of matching REGEXP against a substring
+of STRING.
+
+To replace only the first match (if any), make REGEXP match up to \\'
+and replace a sub-expression, e.g.
+  (replace-regexp-in-string \"\\\\(foo\\\\).*\\\\'\" \"bar\" \" foo foo\" nil 
nil 1)
+    => \" bar foo\""
+
+  ;; To avoid excessive consing from multiple matches in long strings,
+  ;; don't just call `replace-match' continually.  Walk down the
+  ;; string looking for matches of REGEXP and building up a (reversed)
+  ;; list MATCHES.  This comprises segments of STRING which weren't
+  ;; matched interspersed with replacements for segments that were.
+  ;; [For a `large' number of replacements it's more efficient to
+  ;; operate in a temporary buffer; we can't tell from the function's
+  ;; args whether to choose the buffer-based implementation, though it
+  ;; might be reasonable to do so for long enough STRING.]
+  (let ((l (length string))
+       (start (or start 0))
+       matches str mb me)
+    (save-match-data
+      (while (and (< start l) (string-match regexp string start))
+       (setq mb (match-beginning 0)
+             me (match-end 0))
+       ;; If we matched the empty string, make sure we advance by one char
+       (when (= me mb) (setq me (min l (1+ mb))))
+       ;; Generate a replacement for the matched substring.
+       ;; Operate only on the substring to minimize string consing.
+       ;; Set up match data for the substring for replacement;
+       ;; presumably this is likely to be faster than munging the
+       ;; match data directly in Lisp.
+       (string-match regexp (setq str (substring string mb me)))
+       (setq matches
+             (cons (replace-match (if (stringp rep)
+                                      rep
+                                    (funcall rep (match-string 0 str)))
+                                  fixedcase literal str subexp)
+                   (cons (substring string start mb) ; unmatched prefix
+                         matches)))
+       (setq start me))
+      ;; Reconstruct a string from the pieces.
+      (setq matches (cons (substring string start l) matches)) ; leftover
+      (apply #'concat (nreverse matches)))))
+
+(defun string-prefix-p (str1 str2 &optional ignore-case)
+  "Return non-nil if STR1 is a prefix of STR2.
+If IGNORE-CASE is non-nil, the comparison is done without paying attention
+to case differences."
+  (eq t (compare-strings str1 nil nil
+                         str2 0 (length str1) ignore-case)))
+
+(defun string-suffix-p (suffix string  &optional ignore-case)
+  "Return non-nil if SUFFIX is a suffix of STRING.
+If IGNORE-CASE is non-nil, the comparison is done without paying
+attention to case differences."
+  (let ((start-pos (- (length string) (length suffix))))
+    (and (>= start-pos 0)
+         (eq t (compare-strings suffix nil nil
+                                string start-pos nil ignore-case)))))
+
+(defun bidi-string-mark-left-to-right (str)
+  "Return a string that can be safely inserted in left-to-right text.
+
+Normally, inserting a string with right-to-left (RTL) script into
+a buffer may cause some subsequent text to be displayed as part
+of the RTL segment (usually this affects punctuation characters).
+This function returns a string which displays as STR but forces
+subsequent text to be displayed as left-to-right.
+
+If STR contains any RTL character, this function returns a string
+consisting of STR followed by an invisible left-to-right mark
+\(LRM) character.  Otherwise, it returns STR."
+  (unless (stringp str)
+    (signal 'wrong-type-argument (list 'stringp str)))
+  (if (string-match "\\cR" str)
+      (concat str (propertize (string ?\x200e) 'invisible t))
+    str))
+
+;;;; Specifying things to do later.
+
+(defun load-history-regexp (file)
+  "Form a regexp to find FILE in `load-history'.
+FILE, a string, is described in the function `eval-after-load'."
+  (if (file-name-absolute-p file)
+      (setq file (file-truename file)))
+  (concat (if (file-name-absolute-p file) "\\`" "\\(\\`\\|/\\)")
+         (regexp-quote file)
+         (if (file-name-extension file)
+             ""
+           ;; Note: regexp-opt can't be used here, since we need to call
+           ;; this before Emacs has been fully started.  2006-05-21
+           (concat "\\(" (mapconcat 'regexp-quote load-suffixes "\\|") "\\)?"))
+         "\\(" (mapconcat 'regexp-quote jka-compr-load-suffixes "\\|")
+         "\\)?\\'"))
+
+(defun load-history-filename-element (file-regexp)
+  "Get the first elt of `load-history' whose car matches FILE-REGEXP.
+Return nil if there isn't one."
+  (let* ((loads load-history)
+        (load-elt (and loads (car loads))))
+    (save-match-data
+      (while (and loads
+                 (or (null (car load-elt))
+                     (not (string-match file-regexp (car load-elt)))))
+       (setq loads (cdr loads)
+             load-elt (and loads (car loads)))))
+    load-elt))
+
+(put 'eval-after-load 'lisp-indent-function 1)
+(defun eval-after-load (file form)
+  "Arrange that if FILE is loaded, FORM will be run immediately afterwards.
+If FILE is already loaded, evaluate FORM right now.
+FORM can be an Elisp expression (in which case it's passed to `eval'),
+or a function (in which case it's passed to `funcall' with no argument).
+
+If a matching file is loaded again, FORM will be evaluated again.
+
+If FILE is a string, it may be either an absolute or a relative file
+name, and may have an extension (e.g. \".el\") or may lack one, and
+additionally may or may not have an extension denoting a compressed
+format (e.g. \".gz\").
+
+When FILE is absolute, this first converts it to a true name by chasing
+symbolic links.  Only a file of this name (see next paragraph regarding
+extensions) will trigger the evaluation of FORM.  When FILE is relative,
+a file whose absolute true name ends in FILE will trigger evaluation.
+
+When FILE lacks an extension, a file name with any extension will trigger
+evaluation.  Otherwise, its extension must match FILE's.  A further
+extension for a compressed format (e.g. \".gz\") on FILE will not affect
+this name matching.
+
+Alternatively, FILE can be a feature (i.e. a symbol), in which case FORM
+is evaluated at the end of any file that `provide's this feature.
+If the feature is provided when evaluating code not associated with a
+file, FORM is evaluated immediately after the provide statement.
+
+Usually FILE is just a library name like \"font-lock\" or a feature name
+like 'font-lock.
+
+This function makes or adds to an entry on `after-load-alist'."
+  (declare (compiler-macro
+            (lambda (whole)
+              (if (eq 'quote (car-safe form))
+                  ;; Quote with lambda so the compiler can look inside.
+                  `(eval-after-load ,file (lambda () ,(nth 1 form)))
+                whole))))
+  ;; Add this FORM into after-load-alist (regardless of whether we'll be
+  ;; evaluating it now).
+  (let* ((regexp-or-feature
+         (if (stringp file)
+              (setq file (purecopy (load-history-regexp file)))
+            file))
+        (elt (assoc regexp-or-feature after-load-alist))
+         (func
+          (if (functionp form) form
+            ;; Try to use the "current" lexical/dynamic mode for `form'.
+            (eval `(lambda () ,form) lexical-binding))))
+    (unless elt
+      (setq elt (list regexp-or-feature))
+      (push elt after-load-alist))
+    ;; Is there an already loaded file whose name (or `provide' name)
+    ;; matches FILE?
+    (prog1 (if (if (stringp file)
+                  (load-history-filename-element regexp-or-feature)
+                (featurep file))
+              (funcall func))
+      (let ((delayed-func
+             (if (not (symbolp regexp-or-feature)) func
+               ;; For features, the after-load-alist elements get run when
+               ;; `provide' is called rather than at the end of the file.
+               ;; So add an indirection to make sure that `func' is really run
+               ;; "after-load" in case the provide call happens early.
+               (lambda ()
+                 (if (not load-file-name)
+                     ;; Not being provided from a file, run func right now.
+                     (funcall func)
+                   (let ((lfn load-file-name)
+                         ;; Don't use letrec, because equal (in
+                         ;; add/remove-hook) would get trapped in a cycle.
+                         (fun (make-symbol "eval-after-load-helper")))
+                     (fset fun (lambda (file)
+                                 (when (equal file lfn)
+                                   (remove-hook 'after-load-functions fun)
+                                   (funcall func))))
+                     (add-hook 'after-load-functions fun 'append)))))))
+        ;; Add FORM to the element unless it's already there.
+        (unless (member delayed-func (cdr elt))
+          (nconc elt (list delayed-func)))))))
+
+(defmacro with-eval-after-load (file &rest body)
+  "Execute BODY after FILE is loaded.
+FILE is normally a feature name, but it can also be a file name,
+in case that file does not provide any feature."
+  (declare (indent 1) (debug t))
+  `(eval-after-load ,file (lambda () ,@body)))
+
+(defvar after-load-functions nil
+  "Special hook run after loading a file.
+Each function there is called with a single argument, the absolute
+name of the file just loaded.")
+
+(defun do-after-load-evaluation (abs-file)
+  "Evaluate all `eval-after-load' forms, if any, for ABS-FILE.
+ABS-FILE, a string, should be the absolute true name of a file just loaded.
+This function is called directly from the C code."
+  ;; Run the relevant eval-after-load forms.
+  (dolist (a-l-element after-load-alist)
+    (when (and (stringp (car a-l-element))
+               (string-match-p (car a-l-element) abs-file))
+      ;; discard the file name regexp
+      (mapc #'funcall (cdr a-l-element))))
+  ;; Complain when the user uses obsolete files.
+  (when (string-match-p "/obsolete/[^/]*\\'" abs-file)
+    ;; Maybe we should just use display-warning?  This seems yucky...
+    (let* ((file (file-name-nondirectory abs-file))
+          (msg (format "Package %s is obsolete!"
+                       (substring file 0
+                                  (string-match "\\.elc?\\>" file)))))
+      ;; Cribbed from cl--compiling-file.
+      (if (and (boundp 'byte-compile--outbuffer)
+              (bufferp (symbol-value 'byte-compile--outbuffer))
+              (equal (buffer-name (symbol-value 'byte-compile--outbuffer))
+                     " *Compiler Output*"))
+         ;; Don't warn about obsolete files using other obsolete files.
+         (unless (and (stringp byte-compile-current-file)
+                      (string-match-p "/obsolete/[^/]*\\'"
+                                      (expand-file-name
+                                       byte-compile-current-file
+                                       byte-compile-root-dir)))
+           (byte-compile-log-warning msg))
+       (run-with-timer 0 nil
+                       (lambda (msg)
+                         (message "%s" msg)) msg))))
+
+  ;; Finally, run any other hook.
+  (run-hook-with-args 'after-load-functions abs-file))
+
+(defun eval-next-after-load (file)
+  "Read the following input sexp, and run it whenever FILE is loaded.
+This makes or adds to an entry on `after-load-alist'.
+FILE should be the name of a library, with no directory name."
+  (declare (obsolete eval-after-load "23.2"))
+  (eval-after-load file (read)))
+
+
+(defun display-delayed-warnings ()
+  "Display delayed warnings from `delayed-warnings-list'.
+Used from `delayed-warnings-hook' (which see)."
+  (dolist (warning (nreverse delayed-warnings-list))
+    (apply 'display-warning warning))
+  (setq delayed-warnings-list nil))
+
+(defun collapse-delayed-warnings ()
+  "Remove duplicates from `delayed-warnings-list'.
+Collapse identical adjacent warnings into one (plus count).
+Used from `delayed-warnings-hook' (which see)."
+  (let ((count 1)
+        collapsed warning)
+    (while delayed-warnings-list
+      (setq warning (pop delayed-warnings-list))
+      (if (equal warning (car delayed-warnings-list))
+          (setq count (1+ count))
+        (when (> count 1)
+          (setcdr warning (cons (format "%s [%d times]" (cadr warning) count)
+                                (cddr warning)))
+          (setq count 1))
+        (push warning collapsed)))
+    (setq delayed-warnings-list (nreverse collapsed))))
+
+;; At present this is only used for Emacs internals.
+;; Ref http://lists.gnu.org/archive/html/emacs-devel/2012-02/msg00085.html
+(defvar delayed-warnings-hook '(collapse-delayed-warnings
+                                display-delayed-warnings)
+  "Normal hook run to process and display delayed warnings.
+By default, this hook contains functions to consolidate the
+warnings listed in `delayed-warnings-list', display them, and set
+`delayed-warnings-list' back to nil.")
+
+(defun delay-warning (type message &optional level buffer-name)
+  "Display a delayed warning.
+Aside from going through `delayed-warnings-list', this is equivalent
+to `display-warning'."
+  (push (list type message level buffer-name) delayed-warnings-list))
+
+
+;;;; invisibility specs
+
+(defun add-to-invisibility-spec (element)
+  "Add ELEMENT to `buffer-invisibility-spec'.
+See documentation for `buffer-invisibility-spec' for the kind of elements
+that can be added."
+  (if (eq buffer-invisibility-spec t)
+      (setq buffer-invisibility-spec (list t)))
+  (setq buffer-invisibility-spec
+       (cons element buffer-invisibility-spec)))
+
+(defun remove-from-invisibility-spec (element)
+  "Remove ELEMENT from `buffer-invisibility-spec'."
+  (if (consp buffer-invisibility-spec)
+      (setq buffer-invisibility-spec
+           (delete element buffer-invisibility-spec))))
+
+;;;; Syntax tables.
+
+(defmacro with-syntax-table (table &rest body)
+  "Evaluate BODY with syntax table of current buffer set to TABLE.
+The syntax table of the current buffer is saved, BODY is evaluated, and the
+saved table is restored, even in case of an abnormal exit.
+Value is what BODY returns."
+  (declare (debug t) (indent 1))
+  (let ((old-table (make-symbol "table"))
+       (old-buffer (make-symbol "buffer")))
+    `(let ((,old-table (syntax-table))
+          (,old-buffer (current-buffer)))
+       (unwind-protect
+          (progn
+            (set-syntax-table ,table)
+            ,@body)
+        (save-current-buffer
+          (set-buffer ,old-buffer)
+          (set-syntax-table ,old-table))))))
+
+(defun make-syntax-table (&optional oldtable)
+  "Return a new syntax table.
+Create a syntax table which inherits from OLDTABLE (if non-nil) or
+from `standard-syntax-table' otherwise."
+  (let ((table (make-char-table 'syntax-table nil)))
+    (set-char-table-parent table (or oldtable (standard-syntax-table)))
+    table))
+
+(defun syntax-after (pos)
+  "Return the raw syntax descriptor for the char after POS.
+If POS is outside the buffer's accessible portion, return nil."
+  (unless (or (< pos (point-min)) (>= pos (point-max)))
+    (let ((st (if parse-sexp-lookup-properties
+                 (get-char-property pos 'syntax-table))))
+      (if (consp st) st
+       (aref (or st (syntax-table)) (char-after pos))))))
+
+(defun syntax-class (syntax)
+  "Return the code for the syntax class described by SYNTAX.
+
+SYNTAX should be a raw syntax descriptor; the return value is a
+integer which encodes the corresponding syntax class.  See Info
+node `(elisp)Syntax Table Internals' for a list of codes.
+
+If SYNTAX is nil, return nil."
+  (and syntax (logand (car syntax) 65535)))
+
+;; Utility motion commands
+
+;;  Whitespace
+
+(defun forward-whitespace (arg)
+  "Move point to the end of the next sequence of whitespace chars.
+Each such sequence may be a single newline, or a sequence of
+consecutive space and/or tab characters.
+With prefix argument ARG, do it ARG times if positive, or move
+backwards ARG times if negative."
+  (interactive "^p")
+  (if (natnump arg)
+      (re-search-forward "[ \t]+\\|\n" nil 'move arg)
+    (while (< arg 0)
+      (if (re-search-backward "[ \t]+\\|\n" nil 'move)
+         (or (eq (char-after (match-beginning 0)) ?\n)
+             (skip-chars-backward " \t")))
+      (setq arg (1+ arg)))))
+
+;;  Symbols
+
+(defun forward-symbol (arg)
+  "Move point to the next position that is the end of a symbol.
+A symbol is any sequence of characters that are in either the
+word constituent or symbol constituent syntax class.
+With prefix argument ARG, do it ARG times if positive, or move
+backwards ARG times if negative."
+  (interactive "^p")
+  (if (natnump arg)
+      (re-search-forward "\\(\\sw\\|\\s_\\)+" nil 'move arg)
+    (while (< arg 0)
+      (if (re-search-backward "\\(\\sw\\|\\s_\\)+" nil 'move)
+         (skip-syntax-backward "w_"))
+      (setq arg (1+ arg)))))
+
+;;  Syntax blocks
+
+(defun forward-same-syntax (&optional arg)
+  "Move point past all characters with the same syntax class.
+With prefix argument ARG, do it ARG times if positive, or move
+backwards ARG times if negative."
+  (interactive "^p")
+  (or arg (setq arg 1))
+  (while (< arg 0)
+    (skip-syntax-backward
+     (char-to-string (char-syntax (char-before))))
+    (setq arg (1+ arg)))
+  (while (> arg 0)
+    (skip-syntax-forward (char-to-string (char-syntax (char-after))))
+    (setq arg (1- arg))))
+
+
+;;;; Text clones
+
+(defvar text-clone--maintaining nil)
+
+(defun text-clone--maintain (ol1 after beg end &optional _len)
+  "Propagate the changes made under the overlay OL1 to the other clones.
+This is used on the `modification-hooks' property of text clones."
+  (when (and after (not undo-in-progress)
+             (not text-clone--maintaining)
+             (overlay-start ol1))
+    (let ((margin (if (overlay-get ol1 'text-clone-spreadp) 1 0)))
+      (setq beg (max beg (+ (overlay-start ol1) margin)))
+      (setq end (min end (- (overlay-end ol1) margin)))
+      (when (<= beg end)
+       (save-excursion
+         (when (overlay-get ol1 'text-clone-syntax)
+           ;; Check content of the clone's text.
+           (let ((cbeg (+ (overlay-start ol1) margin))
+                 (cend (- (overlay-end ol1) margin)))
+             (goto-char cbeg)
+             (save-match-data
+               (if (not (re-search-forward
+                         (overlay-get ol1 'text-clone-syntax) cend t))
+                   ;; Mark the overlay for deletion.
+                   (setq end cbeg)
+                 (when (< (match-end 0) cend)
+                   ;; Shrink the clone at its end.
+                   (setq end (min end (match-end 0)))
+                   (move-overlay ol1 (overlay-start ol1)
+                                 (+ (match-end 0) margin)))
+                 (when (> (match-beginning 0) cbeg)
+                   ;; Shrink the clone at its beginning.
+                   (setq beg (max (match-beginning 0) beg))
+                   (move-overlay ol1 (- (match-beginning 0) margin)
+                                 (overlay-end ol1)))))))
+         ;; Now go ahead and update the clones.
+         (let ((head (- beg (overlay-start ol1)))
+               (tail (- (overlay-end ol1) end))
+               (str (buffer-substring beg end))
+               (nothing-left t)
+               (text-clone--maintaining t))
+           (dolist (ol2 (overlay-get ol1 'text-clones))
+             (let ((oe (overlay-end ol2)))
+               (unless (or (eq ol1 ol2) (null oe))
+                 (setq nothing-left nil)
+                 (let ((mod-beg (+ (overlay-start ol2) head)))
+                   ;;(overlay-put ol2 'modification-hooks nil)
+                   (goto-char (- (overlay-end ol2) tail))
+                   (unless (> mod-beg (point))
+                     (save-excursion (insert str))
+                     (delete-region mod-beg (point)))
+                   ;;(overlay-put ol2 'modification-hooks 
'(text-clone--maintain))
+                   ))))
+           (if nothing-left (delete-overlay ol1))))))))
+
+(defun text-clone-create (start end &optional spreadp syntax)
+  "Create a text clone of START...END at point.
+Text clones are chunks of text that are automatically kept identical:
+changes done to one of the clones will be immediately propagated to the other.
+
+The buffer's content at point is assumed to be already identical to
+the one between START and END.
+If SYNTAX is provided it's a regexp that describes the possible text of
+the clones; the clone will be shrunk or killed if necessary to ensure that
+its text matches the regexp.
+If SPREADP is non-nil it indicates that text inserted before/after the
+clone should be incorporated in the clone."
+  ;; To deal with SPREADP we can either use an overlay with `nil t' along
+  ;; with insert-(behind|in-front-of)-hooks or use a slightly larger overlay
+  ;; (with a one-char margin at each end) with `t nil'.
+  ;; We opted for a larger overlay because it behaves better in the case
+  ;; where the clone is reduced to the empty string (we want the overlay to
+  ;; stay when the clone's content is the empty string and we want to use
+  ;; `evaporate' to make sure those overlays get deleted when needed).
+  ;;
+  (let* ((pt-end (+ (point) (- end start)))
+        (start-margin (if (or (not spreadp) (bobp) (<= start (point-min)))
+                          0 1))
+        (end-margin (if (or (not spreadp)
+                            (>= pt-end (point-max))
+                            (>= start (point-max)))
+                        0 1))
+         ;; FIXME: Reuse overlays at point to extend dups!
+        (ol1 (make-overlay (- start start-margin) (+ end end-margin) nil t))
+        (ol2 (make-overlay (- (point) start-margin) (+ pt-end end-margin) nil 
t))
+        (dups (list ol1 ol2)))
+    (overlay-put ol1 'modification-hooks '(text-clone--maintain))
+    (when spreadp (overlay-put ol1 'text-clone-spreadp t))
+    (when syntax (overlay-put ol1 'text-clone-syntax syntax))
+    ;;(overlay-put ol1 'face 'underline)
+    (overlay-put ol1 'evaporate t)
+    (overlay-put ol1 'text-clones dups)
+    ;;
+    (overlay-put ol2 'modification-hooks '(text-clone--maintain))
+    (when spreadp (overlay-put ol2 'text-clone-spreadp t))
+    (when syntax (overlay-put ol2 'text-clone-syntax syntax))
+    ;;(overlay-put ol2 'face 'underline)
+    (overlay-put ol2 'evaporate t)
+    (overlay-put ol2 'text-clones dups)))
+
+;;;; Mail user agents.
+
+;; Here we include just enough for other packages to be able
+;; to define them.
+
+(defun define-mail-user-agent (symbol composefunc sendfunc
+                                     &optional abortfunc hookvar)
+  "Define a symbol to identify a mail-sending package for `mail-user-agent'.
+
+SYMBOL can be any Lisp symbol.  Its function definition and/or
+value as a variable do not matter for this usage; we use only certain
+properties on its property list, to encode the rest of the arguments.
+
+COMPOSEFUNC is program callable function that composes an outgoing
+mail message buffer.  This function should set up the basics of the
+buffer without requiring user interaction.  It should populate the
+standard mail headers, leaving the `to:' and `subject:' headers blank
+by default.
+
+COMPOSEFUNC should accept several optional arguments--the same
+arguments that `compose-mail' takes.  See that function's documentation.
+
+SENDFUNC is the command a user would run to send the message.
+
+Optional ABORTFUNC is the command a user would run to abort the
+message.  For mail packages that don't have a separate abort function,
+this can be `kill-buffer' (the equivalent of omitting this argument).
+
+Optional HOOKVAR is a hook variable that gets run before the message
+is actually sent.  Callers that use the `mail-user-agent' may
+install a hook function temporarily on this hook variable.
+If HOOKVAR is nil, `mail-send-hook' is used.
+
+The properties used on SYMBOL are `composefunc', `sendfunc',
+`abortfunc', and `hookvar'."
+  (put symbol 'composefunc composefunc)
+  (put symbol 'sendfunc sendfunc)
+  (put symbol 'abortfunc (or abortfunc 'kill-buffer))
+  (put symbol 'hookvar (or hookvar 'mail-send-hook)))
+
+(defvar called-interactively-p-functions nil
+  "Special hook called to skip special frames in `called-interactively-p'.
+The functions are called with 3 arguments: (I FRAME1 FRAME2),
+where FRAME1 is a \"current frame\", FRAME2 is the next frame,
+I is the index of the frame after FRAME2.  It should return nil
+if those frames don't seem special and otherwise, it should return
+the number of frames to skip (minus 1).")
+
+(defconst internal--call-interactively (symbol-function 'call-interactively))
+
+(defun called-interactively-p (&optional kind)
+  "Return t if the containing function was called by `call-interactively'.
+If KIND is `interactive', then only return t if the call was made
+interactively by the user, i.e. not in `noninteractive' mode nor
+when `executing-kbd-macro'.
+If KIND is `any', on the other hand, it will return t for any kind of
+interactive call, including being called as the binding of a key or
+from a keyboard macro, even in `noninteractive' mode.
+
+This function is very brittle, it may fail to return the intended result when
+the code is debugged, advised, or instrumented in some form.  Some macros and
+special forms (such as `condition-case') may also sometimes wrap their bodies
+in a `lambda', so any call to `called-interactively-p' from those bodies will
+indicate whether that lambda (rather than the surrounding function) was called
+interactively.
+
+Instead of using this function, it is cleaner and more reliable to give your
+function an extra optional argument whose `interactive' spec specifies
+non-nil unconditionally (\"p\" is a good way to do this), or via
+\(not (or executing-kbd-macro noninteractive)).
+
+The only known proper use of `interactive' for KIND is in deciding
+whether to display a helpful message, or how to display it.  If you're
+thinking of using it for any other purpose, it is quite likely that
+you're making a mistake.  Think: what do you want to do when the
+command is called from a keyboard macro?"
+  (declare (advertised-calling-convention (kind) "23.1"))
+  (when (not (and (eq kind 'interactive)
+                  (or executing-kbd-macro noninteractive)))
+    (let* ((i 1) ;; 0 is the called-interactively-p frame.
+           frame nextframe
+           (get-next-frame
+            (lambda ()
+              (setq frame nextframe)
+              (setq nextframe (backtrace-frame i 'called-interactively-p))
+              ;; (message "Frame %d = %S" i nextframe)
+              (setq i (1+ i)))))
+      (funcall get-next-frame) ;; Get the first frame.
+      (while
+          ;; FIXME: The edebug and advice handling should be made modular and
+          ;; provided directly by edebug.el and nadvice.el.
+          (progn
+            ;; frame    =(backtrace-frame i-2)
+            ;; nextframe=(backtrace-frame i-1)
+            (funcall get-next-frame)
+            ;; `pcase' would be a fairly good fit here, but it sometimes moves
+            ;; branches within local functions, which then messes up the
+            ;; `backtrace-frame' data we get,
+            (or
+             ;; Skip special forms (from non-compiled code).
+             (and frame (null (car frame)))
+             ;; Skip also `interactive-p' (because we don't want to know if
+             ;; interactive-p was called interactively but if it's caller was)
+             ;; and `byte-code' (idem; this appears in subexpressions of things
+             ;; like condition-case, which are wrapped in a separate bytecode
+             ;; chunk).
+             ;; FIXME: For lexical-binding code, this is much worse,
+             ;; because the frames look like "byte-code -> funcall -> #[...]",
+             ;; which is not a reliable signature.
+             (memq (nth 1 frame) '(interactive-p 'byte-code))
+             ;; Skip package-specific stack-frames.
+             (let ((skip (run-hook-with-args-until-success
+                          'called-interactively-p-functions
+                          i frame nextframe)))
+               (pcase skip
+                 (`nil nil)
+                 (`0 t)
+                 (_ (setq i (+ i skip -1)) (funcall get-next-frame)))))))
+      ;; Now `frame' should be "the function from which we were called".
+      (pcase (cons frame nextframe)
+        ;; No subr calls `interactive-p', so we can rule that out.
+        (`((,_ ,(pred (lambda (f) (subrp (indirect-function f)))) . ,_) . ,_) 
nil)
+        ;; In case #<subr call-interactively> without going through the
+        ;; `call-interactively' symbol (bug#3984).
+        (`(,_ . (t ,(pred (eq internal--call-interactively)) . ,_)) t)
+        (`(,_ . (t call-interactively . ,_)) t)))))
+
+(defun interactive-p ()
+  "Return t if the containing function was run directly by user input.
+This means that the function was called with `call-interactively'
+\(which includes being called as the binding of a key)
+and input is currently coming from the keyboard (not a keyboard macro),
+and Emacs is not running in batch mode (`noninteractive' is nil).
+
+The only known proper use of `interactive-p' is in deciding whether to
+display a helpful message, or how to display it.  If you're thinking
+of using it for any other purpose, it is quite likely that you're
+making a mistake.  Think: what do you want to do when the command is
+called from a keyboard macro or in batch mode?
+
+To test whether your function was called with `call-interactively',
+either (i) add an extra optional argument and give it an `interactive'
+spec that specifies non-nil unconditionally (such as \"p\"); or (ii)
+use `called-interactively-p'."
+  (declare (obsolete called-interactively-p "23.2"))
+  (called-interactively-p 'interactive))
+
+(defun internal-push-keymap (keymap symbol)
+  (let ((map (symbol-value symbol)))
+    (unless (memq keymap map)
+      (unless (memq 'add-keymap-witness (symbol-value symbol))
+        (setq map (make-composed-keymap nil (symbol-value symbol)))
+        (push 'add-keymap-witness (cdr map))
+        (set symbol map))
+      (push keymap (cdr map)))))
+
+(defun internal-pop-keymap (keymap symbol)
+  (let ((map (symbol-value symbol)))
+    (when (memq keymap map)
+      (setf (cdr map) (delq keymap (cdr map))))
+    (let ((tail (cddr map)))
+      (and (or (null tail) (keymapp tail))
+           (eq 'add-keymap-witness (nth 1 map))
+           (set symbol tail)))))
+
+(define-obsolete-function-alias
+  'set-temporary-overlay-map 'set-transient-map "24.4")
+
+(defun set-transient-map (map &optional keep-pred on-exit)
+  "Set MAP as a temporary keymap taking precedence over other keymaps.
+Normally, MAP is used only once, to look up the very next key.
+However, if the optional argument KEEP-PRED is t, MAP stays
+active if a key from MAP is used.  KEEP-PRED can also be a
+function of no arguments: if it returns non-nil, then MAP stays
+active.
+
+Optional arg ON-EXIT, if non-nil, specifies a function that is
+called, with no arguments, after MAP is deactivated.
+
+This uses `overriding-terminal-local-map' which takes precedence over all other
+keymaps.  As usual, if no match for a key is found in MAP, the normal key
+lookup sequence then continues."
+  (let ((clearfun (make-symbol "clear-transient-map")))
+    ;; Don't use letrec, because equal (in add/remove-hook) would get trapped
+    ;; in a cycle.
+    (fset clearfun
+          (lambda ()
+            (with-demoted-errors "set-transient-map PCH: %S"
+              (unless (cond
+                       ((null keep-pred) nil)
+                       ((not (eq map (cadr overriding-terminal-local-map)))
+                        ;; There's presumably some other transient-map in
+                        ;; effect.  Wait for that one to terminate before we
+                        ;; remove ourselves.
+                        ;; For example, if isearch and C-u both use transient
+                        ;; maps, then the lifetime of the C-u should be nested
+                        ;; within isearch's, so the pre-command-hook of
+                        ;; isearch should be suspended during the C-u one so
+                        ;; we don't exit isearch just because we hit 1 after
+                        ;; C-u and that 1 exits isearch whereas it doesn't
+                        ;; exit C-u.
+                        t)
+                       ((eq t keep-pred)
+                        (eq this-command
+                            (lookup-key map (this-command-keys-vector))))
+                       (t (funcall keep-pred)))
+                (internal-pop-keymap map 'overriding-terminal-local-map)
+                (remove-hook 'pre-command-hook clearfun)
+                (when on-exit (funcall on-exit))))))
+    (add-hook 'pre-command-hook clearfun)
+    (internal-push-keymap map 'overriding-terminal-local-map)))
+
+;;;; Progress reporters.
+
+;; Progress reporter has the following structure:
+;;
+;;     (NEXT-UPDATE-VALUE . [NEXT-UPDATE-TIME
+;;                           MIN-VALUE
+;;                           MAX-VALUE
+;;                           MESSAGE
+;;                           MIN-CHANGE
+;;                           MIN-TIME])
+;;
+;; This weirdness is for optimization reasons: we want
+;; `progress-reporter-update' to be as fast as possible, so
+;; `(car reporter)' is better than `(aref reporter 0)'.
+;;
+;; NEXT-UPDATE-TIME is a float.  While `float-time' loses a couple
+;; digits of precision, it doesn't really matter here.  On the other
+;; hand, it greatly simplifies the code.
+
+(defsubst progress-reporter-update (reporter &optional value)
+  "Report progress of an operation in the echo area.
+REPORTER should be the result of a call to `make-progress-reporter'.
+
+If REPORTER is a numerical progress reporter---i.e. if it was
+ made using non-nil MIN-VALUE and MAX-VALUE arguments to
+ `make-progress-reporter'---then VALUE should be a number between
+ MIN-VALUE and MAX-VALUE.
+
+If REPORTER is a non-numerical reporter, VALUE should be nil.
+
+This function is relatively inexpensive.  If the change since
+last update is too small or insufficient time has passed, it does
+nothing."
+  (when (or (not (numberp value))      ; For pulsing reporter
+           (>= value (car reporter))) ; For numerical reporter
+    (progress-reporter-do-update reporter value)))
+
+(defun make-progress-reporter (message &optional min-value max-value
+                                      current-value min-change min-time)
+  "Return progress reporter object for use with `progress-reporter-update'.
+
+MESSAGE is shown in the echo area, with a status indicator
+appended to the end.  When you call `progress-reporter-done', the
+word \"done\" is printed after the MESSAGE.  You can change the
+MESSAGE of an existing progress reporter by calling
+`progress-reporter-force-update'.
+
+MIN-VALUE and MAX-VALUE, if non-nil, are starting (0% complete)
+and final (100% complete) states of operation; the latter should
+be larger.  In this case, the status message shows the percentage
+progress.
+
+If MIN-VALUE and/or MAX-VALUE is omitted or nil, the status
+message shows a \"spinning\", non-numeric indicator.
+
+Optional CURRENT-VALUE is the initial progress; the default is
+MIN-VALUE.
+Optional MIN-CHANGE is the minimal change in percents to report;
+the default is 1%.
+CURRENT-VALUE and MIN-CHANGE do not have any effect if MIN-VALUE
+and/or MAX-VALUE are nil.
+
+Optional MIN-TIME specifies the minimum interval time between
+echo area updates (default is 0.2 seconds.)  If the function
+`float-time' is not present, time is not tracked at all.  If the
+OS is not capable of measuring fractions of seconds, this
+parameter is effectively rounded up."
+  (when (string-match "[[:alnum:]]\\'" message)
+    (setq message (concat message "...")))
+  (unless min-time
+    (setq min-time 0.2))
+  (let ((reporter
+        ;; Force a call to `message' now
+        (cons (or min-value 0)
+              (vector (if (and (fboundp 'float-time)
+                               (>= min-time 0.02))
+                          (float-time) nil)
+                      min-value
+                      max-value
+                      message
+                      (if min-change (max (min min-change 50) 1) 1)
+                      min-time))))
+    (progress-reporter-update reporter (or current-value min-value))
+    reporter))
+
+(defun progress-reporter-force-update (reporter &optional value new-message)
+  "Report progress of an operation in the echo area unconditionally.
+
+The first two arguments are the same as in `progress-reporter-update'.
+NEW-MESSAGE, if non-nil, sets a new message for the reporter."
+  (let ((parameters (cdr reporter)))
+    (when new-message
+      (aset parameters 3 new-message))
+    (when (aref parameters 0)
+      (aset parameters 0 (float-time)))
+    (progress-reporter-do-update reporter value)))
+
+(defvar progress-reporter--pulse-characters ["-" "\\" "|" "/"]
+  "Characters to use for pulsing progress reporters.")
+
+(defun progress-reporter-do-update (reporter value)
+  (let* ((parameters   (cdr reporter))
+        (update-time  (aref parameters 0))
+        (min-value    (aref parameters 1))
+        (max-value    (aref parameters 2))
+        (text         (aref parameters 3))
+        (current-time (float-time))
+        (enough-time-passed
+         ;; See if enough time has passed since the last update.
+         (or (not update-time)
+             (when (>= current-time update-time)
+               ;; Calculate time for the next update
+               (aset parameters 0 (+ update-time (aref parameters 5)))))))
+    (cond ((and min-value max-value)
+          ;; Numerical indicator
+          (let* ((one-percent (/ (- max-value min-value) 100.0))
+                 (percentage  (if (= max-value min-value)
+                                  0
+                                (truncate (/ (- value min-value)
+                                             one-percent)))))
+            ;; Calculate NEXT-UPDATE-VALUE.  If we are not printing
+            ;; message because not enough time has passed, use 1
+            ;; instead of MIN-CHANGE.  This makes delays between echo
+            ;; area updates closer to MIN-TIME.
+            (setcar reporter
+                    (min (+ min-value (* (+ percentage
+                                            (if enough-time-passed
+                                                ;; MIN-CHANGE
+                                                (aref parameters 4)
+                                              1))
+                                         one-percent))
+                         max-value))
+            (when (integerp value)
+              (setcar reporter (ceiling (car reporter))))
+            ;; Only print message if enough time has passed
+            (when enough-time-passed
+              (if (> percentage 0)
+                  (message "%s%d%%" text percentage)
+                (message "%s" text)))))
+         ;; Pulsing indicator
+         (enough-time-passed
+          (let ((index (mod (1+ (car reporter)) 4))
+                (message-log-max nil))
+            (setcar reporter index)
+            (message "%s %s"
+                     text
+                     (aref progress-reporter--pulse-characters
+                           index)))))))
+
+(defun progress-reporter-done (reporter)
+  "Print reporter's message followed by word \"done\" in echo area."
+  (message "%sdone" (aref (cdr reporter) 3)))
+
+(defmacro dotimes-with-progress-reporter (spec message &rest body)
+  "Loop a certain number of times and report progress in the echo area.
+Evaluate BODY with VAR bound to successive integers running from
+0, inclusive, to COUNT, exclusive.  Then evaluate RESULT to get
+the return value (nil if RESULT is omitted).
+
+At each iteration MESSAGE followed by progress percentage is
+printed in the echo area.  After the loop is finished, MESSAGE
+followed by word \"done\" is printed.  This macro is a
+convenience wrapper around `make-progress-reporter' and friends.
+
+\(fn (VAR COUNT [RESULT]) MESSAGE BODY...)"
+  (declare (indent 2) (debug ((symbolp form &optional form) form body)))
+  (let ((temp (make-symbol "--dotimes-temp--"))
+       (temp2 (make-symbol "--dotimes-temp2--"))
+       (start 0)
+       (end (nth 1 spec)))
+    `(let ((,temp ,end)
+          (,(car spec) ,start)
+          (,temp2 (make-progress-reporter ,message ,start ,end)))
+       (while (< ,(car spec) ,temp)
+        ,@body
+        (progress-reporter-update ,temp2
+                                  (setq ,(car spec) (1+ ,(car spec)))))
+       (progress-reporter-done ,temp2)
+       nil ,@(cdr (cdr spec)))))
+
+
+;;;; Comparing version strings.
+
+(defconst version-separator "."
+  "Specify the string used to separate the version elements.
+
+Usually the separator is \".\", but it can be any other string.")
+
+
+(defconst version-regexp-alist
+  '(("^[-_+ ]?snapshot$"                                 . -4)
+    ;; treat "1.2.3-20050920" and "1.2-3" as snapshot releases
+    ("^[-_+]$"                                           . -4)
+    ;; treat "1.2.3-CVS" as snapshot release
+    ("^[-_+ ]?\\(cvs\\|git\\|bzr\\|svn\\|hg\\|darcs\\)$" . -4)
+    ("^[-_+ ]?alpha$"                                    . -3)
+    ("^[-_+ ]?beta$"                                     . -2)
+    ("^[-_+ ]?\\(pre\\|rc\\)$"                           . -1))
+  "Specify association between non-numeric version and its priority.
+
+This association is used to handle version string like \"1.0pre2\",
+\"0.9alpha1\", etc.  It's used by `version-to-list' (which see) to convert the
+non-numeric part of a version string to an integer.  For example:
+
+   String Version    Integer List Version
+   \"0.9snapshot\"     (0  9 -4)
+   \"1.0-git\"         (1  0 -4)
+   \"1.0pre2\"         (1  0 -1 2)
+   \"1.0PRE2\"         (1  0 -1 2)
+   \"22.8beta3\"       (22 8 -2 3)
+   \"22.8 Beta3\"      (22 8 -2 3)
+   \"0.9alpha1\"       (0  9 -3 1)
+   \"0.9AlphA1\"       (0  9 -3 1)
+   \"0.9 alpha\"       (0  9 -3)
+
+Each element has the following form:
+
+   (REGEXP . PRIORITY)
+
+Where:
+
+REGEXP         regexp used to match non-numeric part of a version string.
+               It should begin with the `^' anchor and end with a `$' to
+               prevent false hits.  Letter-case is ignored while matching
+               REGEXP.
+
+PRIORITY       a negative integer specifying non-numeric priority of REGEXP.")
+
+
+(defun version-to-list (ver)
+  "Convert version string VER into a list of integers.
+
+The version syntax is given by the following EBNF:
+
+   VERSION ::= NUMBER ( SEPARATOR NUMBER )*.
+
+   NUMBER ::= (0|1|2|3|4|5|6|7|8|9)+.
+
+   SEPARATOR ::= `version-separator' (which see)
+              | `version-regexp-alist' (which see).
+
+The NUMBER part is optional if SEPARATOR is a match for an element
+in `version-regexp-alist'.
+
+Examples of valid version syntax:
+
+   1.0pre2   1.0.7.5   22.8beta3   0.9alpha1   6.9.30Beta
+
+Examples of invalid version syntax:
+
+   1.0prepre2   1.0..7.5   22.8X3   alpha3.2   .5
+
+Examples of version conversion:
+
+   Version String    Version as a List of Integers
+   \"1.0.7.5\"         (1  0  7 5)
+   \"1.0pre2\"         (1  0 -1 2)
+   \"1.0PRE2\"         (1  0 -1 2)
+   \"22.8beta3\"       (22 8 -2 3)
+   \"22.8Beta3\"       (22 8 -2 3)
+   \"0.9alpha1\"       (0  9 -3 1)
+   \"0.9AlphA1\"       (0  9 -3 1)
+   \"0.9alpha\"        (0  9 -3)
+   \"0.9snapshot\"     (0  9 -4)
+   \"1.0-git\"         (1  0 -4)
+
+See documentation for `version-separator' and `version-regexp-alist'."
+  (or (and (stringp ver) (> (length ver) 0))
+      (error "Invalid version string: '%s'" ver))
+  ;; Change .x.y to 0.x.y
+  (if (and (>= (length ver) (length version-separator))
+          (string-equal (substring ver 0 (length version-separator))
+                        version-separator))
+      (setq ver (concat "0" ver)))
+  (save-match-data
+    (let ((i 0)
+         (case-fold-search t)          ; ignore case in matching
+         lst s al)
+      (while (and (setq s (string-match "[0-9]+" ver i))
+                 (= s i))
+       ;; handle numeric part
+       (setq lst (cons (string-to-number (substring ver i (match-end 0)))
+                       lst)
+             i   (match-end 0))
+       ;; handle non-numeric part
+       (when (and (setq s (string-match "[^0-9]+" ver i))
+                  (= s i))
+         (setq s (substring ver i (match-end 0))
+               i (match-end 0))
+         ;; handle alpha, beta, pre, etc. separator
+         (unless (string= s version-separator)
+           (setq al version-regexp-alist)
+           (while (and al (not (string-match (caar al) s)))
+             (setq al (cdr al)))
+           (cond (al
+                  (push (cdar al) lst))
+                 ;; Convert 22.3a to 22.3.1, 22.3b to 22.3.2, etc.
+                 ((string-match "^[-_+ ]?\\([a-zA-Z]\\)$" s)
+                  (push (- (aref (downcase (match-string 1 s)) 0) ?a -1)
+                        lst))
+                 (t (error "Invalid version syntax: '%s'" ver))))))
+      (if (null lst)
+         (error "Invalid version syntax: '%s'" ver)
+       (nreverse lst)))))
+
+
+(defun version-list-< (l1 l2)
+  "Return t if L1, a list specification of a version, is lower than L2.
+
+Note that a version specified by the list (1) is equal to (1 0),
+\(1 0 0), (1 0 0 0), etc.  That is, the trailing zeros are insignificant.
+Also, a version given by the list (1) is higher than (1 -1), which in
+turn is higher than (1 -2), which is higher than (1 -3)."
+  (while (and l1 l2 (= (car l1) (car l2)))
+    (setq l1 (cdr l1)
+         l2 (cdr l2)))
+  (cond
+   ;; l1 not null and l2 not null
+   ((and l1 l2) (< (car l1) (car l2)))
+   ;; l1 null and l2 null         ==> l1 length = l2 length
+   ((and (null l1) (null l2)) nil)
+   ;; l1 not null and l2 null     ==> l1 length > l2 length
+   (l1 (< (version-list-not-zero l1) 0))
+   ;; l1 null and l2 not null     ==> l2 length > l1 length
+   (t  (< 0 (version-list-not-zero l2)))))
+
+
+(defun version-list-= (l1 l2)
+  "Return t if L1, a list specification of a version, is equal to L2.
+
+Note that a version specified by the list (1) is equal to (1 0),
+\(1 0 0), (1 0 0 0), etc.  That is, the trailing zeros are insignificant.
+Also, a version given by the list (1) is higher than (1 -1), which in
+turn is higher than (1 -2), which is higher than (1 -3)."
+  (while (and l1 l2 (= (car l1) (car l2)))
+    (setq l1 (cdr l1)
+         l2 (cdr l2)))
+  (cond
+   ;; l1 not null and l2 not null
+   ((and l1 l2) nil)
+   ;; l1 null and l2 null     ==> l1 length = l2 length
+   ((and (null l1) (null l2)))
+   ;; l1 not null and l2 null ==> l1 length > l2 length
+   (l1 (zerop (version-list-not-zero l1)))
+   ;; l1 null and l2 not null ==> l2 length > l1 length
+   (t  (zerop (version-list-not-zero l2)))))
+
+
+(defun version-list-<= (l1 l2)
+  "Return t if L1, a list specification of a version, is lower or equal to L2.
+
+Note that integer list (1) is equal to (1 0), (1 0 0), (1 0 0 0),
+etc.  That is, the trailing zeroes are insignificant.  Also, integer
+list (1) is greater than (1 -1) which is greater than (1 -2)
+which is greater than (1 -3)."
+  (while (and l1 l2 (= (car l1) (car l2)))
+    (setq l1 (cdr l1)
+         l2 (cdr l2)))
+  (cond
+   ;; l1 not null and l2 not null
+   ((and l1 l2) (< (car l1) (car l2)))
+   ;; l1 null and l2 null     ==> l1 length = l2 length
+   ((and (null l1) (null l2)))
+   ;; l1 not null and l2 null ==> l1 length > l2 length
+   (l1 (<= (version-list-not-zero l1) 0))
+   ;; l1 null and l2 not null ==> l2 length > l1 length
+   (t  (<= 0 (version-list-not-zero l2)))))
+
+(defun version-list-not-zero (lst)
+  "Return the first non-zero element of LST, which is a list of integers.
+
+If all LST elements are zeros or LST is nil, return zero."
+  (while (and lst (zerop (car lst)))
+    (setq lst (cdr lst)))
+  (if lst
+      (car lst)
+    ;; there is no element different of zero
+    0))
+
+
+(defun version< (v1 v2)
+  "Return t if version V1 is lower (older) than V2.
+
+Note that version string \"1\" is equal to \"1.0\", \"1.0.0\", \"1.0.0.0\",
+etc.  That is, the trailing \".0\"s are insignificant.  Also, version
+string \"1\" is higher (newer) than \"1pre\", which is higher than \"1beta\",
+which is higher than \"1alpha\", which is higher than \"1snapshot\".
+Also, \"-GIT\", \"-CVS\" and \"-NNN\" are treated as snapshot versions."
+  (version-list-< (version-to-list v1) (version-to-list v2)))
+
+(defun version<= (v1 v2)
+  "Return t if version V1 is lower (older) than or equal to V2.
+
+Note that version string \"1\" is equal to \"1.0\", \"1.0.0\", \"1.0.0.0\",
+etc.  That is, the trailing \".0\"s are insignificant.  Also, version
+string \"1\" is higher (newer) than \"1pre\", which is higher than \"1beta\",
+which is higher than \"1alpha\", which is higher than \"1snapshot\".
+Also, \"-GIT\", \"-CVS\" and \"-NNN\" are treated as snapshot versions."
+  (version-list-<= (version-to-list v1) (version-to-list v2)))
+
+(defun version= (v1 v2)
+  "Return t if version V1 is equal to V2.
+
+Note that version string \"1\" is equal to \"1.0\", \"1.0.0\", \"1.0.0.0\",
+etc.  That is, the trailing \".0\"s are insignificant.  Also, version
+string \"1\" is higher (newer) than \"1pre\", which is higher than \"1beta\",
+which is higher than \"1alpha\", which is higher than \"1snapshot\".
+Also, \"-GIT\", \"-CVS\" and \"-NNN\" are treated as snapshot versions."
+  (version-list-= (version-to-list v1) (version-to-list v2)))
+
+
+;;; Misc.
+(defconst menu-bar-separator '("--")
+  "Separator for menus.")
+
+;; The following statement ought to be in print.c, but `provide' can't
+;; be used there.
+;; http://lists.gnu.org/archive/html/emacs-devel/2009-08/msg00236.html
+(when (hash-table-p (car (read-from-string
+                         (prin1-to-string (make-hash-table)))))
+  (provide 'hashtable-print-readable))
+
+;; This is used in lisp/Makefile.in and in leim/Makefile.in to
+;; generate file names for autoloads, custom-deps, and finder-data.
+(defun unmsys--file-name (file)
+  "Produce the canonical file name for FILE from its MSYS form.
+
+On systems other than MS-Windows, just returns FILE.
+On MS-Windows, converts /d/foo/bar form of file names
+passed by MSYS Make into d:/foo/bar that Emacs can grok.
+
+This function is called from lisp/Makefile and leim/Makefile."
+  (when (and (eq system-type 'windows-nt)
+            (string-match "\\`/[a-zA-Z]/" file))
+    (setq file (concat (substring file 1 2) ":" (substring file 2))))
+  file)
+
+
+;;; subr.el ends here
diff --git a/packages/context-coloring/context-coloring.el 
b/packages/context-coloring/context-coloring.el
index cb74ee7..c4423f0 100644
--- a/packages/context-coloring/context-coloring.el
+++ b/packages/context-coloring/context-coloring.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2014-2015  Free Software Foundation, Inc.
 
 ;; Author: Jackson Ray Hamilton <address@hidden>
-;; Version: 6.3.0
+;; Version: 6.4.1
 ;; Keywords: convenience faces tools
 ;; Package-Requires: ((emacs "24") (js2-mode "20150126"))
 ;; URL: https://github.com/jacksonrayhamilton/context-coloring
@@ -41,7 +41,7 @@
 
 (defun context-coloring-join (strings delimiter)
   "Join a list of STRINGS with the string DELIMITER."
-  (mapconcat 'identity strings delimiter))
+  (mapconcat #'identity strings delimiter))
 
 (defsubst context-coloring-trim-right (string)
   "Remove leading whitespace from STRING."
@@ -93,7 +93,7 @@ backgrounds."
 
 (defvar context-coloring-original-maximum-face nil
   "Fallback value for `context-coloring-maximum-face' when all
-  themes have been disabled.")
+themes have been disabled.")
 
 (setq context-coloring-maximum-face 7)
 
@@ -120,6 +120,106 @@ backgrounds."
   (context-coloring-level-face (min level context-coloring-maximum-face)))
 
 
+;;; 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-maybe-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.
+
+START, END and LENGTH are recorded for later use."
+  ;; 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-with-buffer (buffer)
+  "Color BUFFER and if it has changed."
+  (when (and (eq buffer (current-buffer))
+             context-coloring-changed-p)
+    (context-coloring-colorize-with-buffer buffer)
+    (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-maybe-colorize-idle-timer nil
+  "The currently-running idle timer for conditional coloring.")
+
+(defvar-local context-coloring-colorize-idle-timer nil
+  "The currently-running idle timer for unconditional coloring.")
+
+(defcustom context-coloring-default-delay 0.25
+  "Default (sometimes overridden) 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'"
+  :group 'context-coloring)
+
+(make-obsolete-variable
+ 'context-coloring-delay
+ 'context-coloring-default-delay
+ "6.4.0")
+
+(defun context-coloring-cancel-timer (timer)
+  "Cancel TIMER."
+  (when timer
+    (cancel-timer timer)))
+
+(defun context-coloring-schedule-coloring (time)
+  "Schedule coloring to occur once after Emacs is idle for TIME."
+  (context-coloring-cancel-timer context-coloring-colorize-idle-timer)
+  (setq context-coloring-colorize-idle-timer
+        (run-with-idle-timer
+         time
+         nil
+         #'context-coloring-colorize-with-buffer
+         (current-buffer))))
+
+(defun context-coloring-setup-idle-change-detection ()
+  "Setup idle change detection."
+  (let ((dispatch (context-coloring-get-dispatch-for-mode major-mode)))
+    (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-maybe-colorize-idle-timer
+          (run-with-idle-timer
+           (or (plist-get dispatch :delay) context-coloring-default-delay)
+           t
+           #'context-coloring-maybe-colorize-with-buffer
+           (current-buffer)))))
+
+(defun context-coloring-teardown-idle-change-detection ()
+  "Teardown idle change detection."
+  (context-coloring-cancel-scopification)
+  (dolist (timer (list context-coloring-colorize-idle-timer
+                       context-coloring-maybe-colorize-idle-timer))
+    (context-coloring-cancel-timer timer))
+  (remove-hook
+   'kill-buffer-hook #'context-coloring-teardown-idle-change-detection t)
+  (remove-hook
+   'after-change-functions #'context-coloring-change-function t))
+
+
 ;;; Colorization utilities
 
 (defsubst context-coloring-colorize-region (start end level)
@@ -130,10 +230,6 @@ the END point (exclusive) with the face corresponding to 
LEVEL."
    end
    `(face ,(context-coloring-bounded-level-face level))))
 
-(defcustom context-coloring-comments-and-strings nil
-  "If non-nil, also color comments and strings using `font-lock'."
-  :group 'context-coloring)
-
 (make-obsolete-variable
  'context-coloring-comments-and-strings
  "use `context-coloring-syntactic-comments' and
@@ -149,18 +245,21 @@ the END point (exclusive) with the face corresponding to 
LEVEL."
   :group 'context-coloring)
 
 (defun context-coloring-font-lock-syntactic-comment-function (state)
-  "Tell `font-lock' to color a comment but not a string."
+  "Tell `font-lock' to color a comment but not a string 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."
+  "Tell `font-lock' to color a string but not a comment according
+to STATE."
   (if (nth 3 state) font-lock-string-face nil))
 
-(defsubst context-coloring-maybe-colorize-comments-and-strings (&optional min 
max)
-  "Color the current buffer's comments and strings if
-`context-coloring-comments-and-strings' is non-nil."
-  (when (or context-coloring-comments-and-strings
-            context-coloring-syntactic-comments
+(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."
+  (when (or context-coloring-syntactic-comments
             context-coloring-syntactic-strings)
     (let ((min (or min (point-min)))
           (max (or max (point-max)))
@@ -168,10 +267,10 @@ the END point (exclusive) with the face corresponding to 
LEVEL."
            (cond
             ((and context-coloring-syntactic-comments
                   (not context-coloring-syntactic-strings))
-             'context-coloring-font-lock-syntactic-comment-function)
+             #'context-coloring-font-lock-syntactic-comment-function)
             ((and context-coloring-syntactic-strings
                   (not context-coloring-syntactic-comments))
-             'context-coloring-font-lock-syntactic-string-function)
+             #'context-coloring-font-lock-syntactic-string-function)
             (t
              font-lock-syntactic-face-function))))
       (save-excursion
@@ -248,7 +347,7 @@ variable."
   "Color the current buffer using the abstract syntax tree
 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-js2-scope-level-hash-table (make-hash-table :test 
#'eq))
   (setq context-coloring-point-max (point-max))
   (with-silent-modifications
     (js2-visit-ast
@@ -275,536 +374,746 @@ generated by `js2-mode'."
                 (context-coloring-js2-scope-level defining-scope))))))
          ;; The `t' indicates to search children.
          t)))
-    (context-coloring-maybe-colorize-comments-and-strings)))
+    (context-coloring-colorize-comments-and-strings)))
 
 
 ;;; Emacs Lisp colorization
 
-(defsubst context-coloring-make-scope (depth level)
-  (list
-   :depth depth
-   :level level
-   :variables (make-hash-table)))
-
-(defsubst context-coloring-scope-get-level (scope)
-  (plist-get scope :level))
-
-(defsubst context-coloring-scope-add-variable (scope variable)
-  (puthash variable t (plist-get scope :variables)))
-
-(defsubst context-coloring-scope-get-variable (scope variable)
-  (gethash variable (plist-get scope :variables)))
-
-(defsubst context-coloring-get-variable-level (scope-stack variable)
-  (let* (scope
-         level)
-    (while (and scope-stack (not level))
-      (setq scope (car scope-stack))
-      (cond
-       ((context-coloring-scope-get-variable scope variable)
-        (setq level (context-coloring-scope-get-level scope)))
-       (t
-        (setq scope-stack (cdr scope-stack)))))
-    ;; Assume a global variable.
-    (or level 0)))
-
-(defsubst context-coloring-make-backtick (end enabled)
-  (list
-   :end end
-   :enabled enabled))
-
-(defsubst context-coloring-backtick-get-end (backtick)
-  (plist-get backtick :end))
-
-(defsubst context-coloring-backtick-get-enabled (backtick)
-  (plist-get backtick :enabled))
-
-(defsubst context-coloring-backtick-enabled-p (backtick-stack)
-  (context-coloring-backtick-get-enabled (car backtick-stack)))
-
-(defsubst context-coloring-make-let-varlist (depth type)
-  (list
-   :depth depth
-   :type type
-   :vars '()))
-
-(defsubst context-coloring-let-varlist-get-type (let-varlist)
-  (plist-get let-varlist :type))
-
-(defsubst context-coloring-let-varlist-add-var (let-varlist var)
-  (plist-put let-varlist :vars (cons var (plist-get let-varlist :vars))))
-
-(defsubst context-coloring-let-varlist-pop-vars (let-varlist)
-  (let ((type (context-coloring-let-varlist-get-type let-varlist))
-        (vars (plist-get let-varlist :vars)))
-    (cond
-     ;; `let' binds all at once at the end.
-     ((eq type 'let)
-      (prog1
-          vars
-        (plist-put let-varlist :vars '())))
-     ;; `let*' binds incrementally.
-     ((eq type 'let*)
-      (prog1
-          (list (car vars))
-        (plist-put let-varlist :vars (cdr vars)))))))
-
 (defsubst context-coloring-forward-sws ()
   "Move forward through whitespace and comments."
   (while (forward-comment 1)))
 
-(defsubst context-coloring-forward-sexp-position ()
-  "Like vanilla `forward-sexp', but just return the position."
-  (scan-sexps (point) 1))
-
-(defsubst context-coloring-emacs-lisp-identifier-syntax-p (syntax-code)
-  (or (= 2 syntax-code)
-      (= 3 syntax-code)))
-
-(defsubst context-coloring-open-parenthesis-p (syntax-code)
-  (= 4 syntax-code))
-
-(defsubst context-coloring-close-parenthesis-p (syntax-code)
-  (= 5 syntax-code))
-
-(defsubst context-coloring-expression-prefix-p (syntax-code)
-  (= 6 syntax-code))
-
-(defsubst context-coloring-at-open-parenthesis-p ()
-  (= 4 (logand #xFFFF (car (syntax-after (point))))))
-
-(defsubst context-coloring-ppss-depth (ppss)
-  ;; Same as (nth 0 ppss).
-  (car ppss))
-
-(defsubst context-coloring-at-stack-depth-p (stack depth)
-  (= (plist-get (car stack) :depth) depth))
+(defsubst context-coloring-elisp-forward-sws ()
+  "Move forward through whitespace and comments, colorizing
+comments along the way."
+  (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."
+  (let ((start (point)))
+    (forward-sexp)
+    (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 that matches exactly WORD."
+  "Create a regexp matching exactly WORD."
   (concat "\\`" (regexp-quote word) "\\'"))
 
 (defsubst context-coloring-exact-or-regexp (words)
-  "Create a regexp that matches any exact word in WORDS."
+  "Create a regexp matching any exact word in WORDS."
   (context-coloring-join
-   (mapcar 'context-coloring-exact-regexp words) "\\|"))
-
-(defconst context-coloring-emacs-lisp-defun-regexp
-  (context-coloring-exact-or-regexp
-   '("defun" "defun*" "defsubst" "defmacro"
-     "cl-defun" "cl-defsubst" "cl-defmacro")))
-
-(defconst context-coloring-emacs-lisp-lambda-regexp
-  (context-coloring-exact-regexp "lambda"))
-
-(defconst context-coloring-emacs-lisp-let-regexp
-  (context-coloring-exact-regexp "let"))
-
-(defconst context-coloring-emacs-lisp-let*-regexp
-  (context-coloring-exact-regexp "let*"))
-
-(defconst context-coloring-arglist-arg-regexp
-  "\\`[^&:]")
-
-(defconst context-coloring-ignored-word-regexp
-  (concat "\\`[-+]?[0-9]\\|" (context-coloring-exact-or-regexp
-                              '("t" "nil" "." "?"))))
-
-(defconst context-coloring-COMMA-CHAR 44)
-(defconst context-coloring-BACKTICK-CHAR 96)
+   (mapcar #'context-coloring-exact-regexp words) "\\|"))
+
+(defconst context-coloring-elisp-ignored-word-regexp
+  (context-coloring-join (list "\\`[-+]?[0-9]"
+                               "\\`[&:].+"
+                               (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 "`"))
+
+(defsubst context-coloring-elisp-identifier-p (syntax-code)
+  "Check if SYNTAX-CODE is an elisp identifier constituent."
+  (or (= syntax-code context-coloring-WORD-CODE)
+      (= syntax-code context-coloring-SYMBOL-CODE)))
 
 (defvar context-coloring-parse-interruptable-p t
   "Set this to nil to force parse to continue until finished.")
 
-(defconst context-coloring-emacs-lisp-iterations-per-pause 1000
+(defconst context-coloring-elisp-sexps-per-pause 1000
   "Pause after this many iterations to check for user input.
 If user input is pending, stop the parse.  This makes for a
-smoother user experience for large files.
+smoother user experience for large files.")
+
+(defvar context-coloring-elisp-sexp-count 0
+  "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."
+  (setq context-coloring-elisp-sexp-count
+        (1+ context-coloring-elisp-sexp-count))
+  (when (and (zerop (% context-coloring-elisp-sexp-count
+                       context-coloring-elisp-sexps-per-pause))
+             context-coloring-parse-interruptable-p
+             (input-pending-p))
+    (throw 'interrupted t)))
+
+(defvar context-coloring-elisp-scope-stack '()
+  "List of scopes in the current parse.")
+
+(defsubst context-coloring-elisp-make-scope (level)
+  "Make a scope object for LEVEL."
+  (list
+   :level level
+   :variables '()))
+
+(defsubst context-coloring-elisp-scope-get-level (scope)
+  "Get the level of SCOPE object."
+  (plist-get scope :level))
+
+(defsubst context-coloring-elisp-scope-add-variable (scope variable)
+  "Add to SCOPE a VARIABLE."
+  (plist-put scope :variables (cons variable (plist-get scope :variables))))
 
-As of this writing, emacs lisp colorization seems to run at about
-60,000 iterations per second.  A default value of 1000 should
-provide visually \"instant\" updates at 60 frames per second.")
+(defsubst context-coloring-elisp-scope-has-variable (scope variable)
+  "Check if SCOPE has VARIABLE."
+  (member variable (plist-get scope :variables)))
 
-(defun context-coloring-emacs-lisp-colorize ()
-  "Color the current buffer by parsing emacs lisp sexps."
+(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."
+  (let* ((scope-stack context-coloring-elisp-scope-stack)
+         scope
+         level)
+    (while (and scope-stack (not level))
+      (setq scope (car scope-stack))
+      (cond
+       ((context-coloring-elisp-scope-has-variable scope variable)
+        (setq level (context-coloring-elisp-scope-get-level scope)))
+       (t
+        (setq scope-stack (cdr scope-stack)))))
+    ;; Assume a global variable.
+    (or level 0)))
+
+(defsubst context-coloring-elisp-get-current-scope-level ()
+  "Get the nesting level of the current scope."
+  (cond
+   ((car context-coloring-elisp-scope-stack)
+    (context-coloring-elisp-scope-get-level (car 
context-coloring-elisp-scope-stack)))
+   (t
+    0)))
+
+(defsubst context-coloring-elisp-push-scope ()
+  "Add a new scope to the bottom of the scope chain."
+  (push (context-coloring-elisp-make-scope
+         (1+ (context-coloring-elisp-get-current-scope-level)))
+        context-coloring-elisp-scope-stack))
+
+(defsubst context-coloring-elisp-pop-scope ()
+  "Remove the scope on the bottom of the scope chain."
+  (pop context-coloring-elisp-scope-stack))
+
+(defsubst context-coloring-elisp-add-variable (variable)
+  "Add VARIABLE to the current scope."
+  (context-coloring-elisp-scope-add-variable
+   (car context-coloring-elisp-scope-stack)
+   variable))
+
+(defsubst context-coloring-elisp-parse-bindable (callback)
+  "Parse the symbol at point, and if the symbol can be bound,
+invoke CALLBACK with it."
+  (let* ((arg-string (buffer-substring-no-properties
+                      (point)
+                      (progn (context-coloring-elisp-forward-sexp)
+                             (point)))))
+    (when (not (string-match-p
+                context-coloring-elisp-ignored-word-regexp
+                arg-string))
+      (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."
+  (let ((varlist '())
+        syntax-code)
+    ;; Enter.
+    (forward-char)
+    (while (/= (setq syntax-code (context-coloring-get-syntax-code))
+               context-coloring-CLOSE-PARENTHESIS-CODE)
+      (cond
+       ((= syntax-code context-coloring-OPEN-PARENTHESIS-CODE)
+        (forward-char)
+        (context-coloring-elisp-forward-sws)
+        (setq syntax-code (context-coloring-get-syntax-code))
+        (when (context-coloring-elisp-identifier-p syntax-code)
+          (context-coloring-elisp-parse-bindable
+           (lambda (var)
+             (push var varlist)))
+          (context-coloring-elisp-forward-sws)
+          (setq syntax-code (context-coloring-get-syntax-code))
+          (when (/= syntax-code context-coloring-CLOSE-PARENTHESIS-CODE)
+            (context-coloring-elisp-colorize-sexp)))
+        (context-coloring-elisp-forward-sws)
+        ;; Skip past the closing parenthesis.
+        (forward-char))
+       ((context-coloring-elisp-identifier-p syntax-code)
+        (context-coloring-elisp-parse-bindable
+         (lambda (var)
+           (push var varlist))))
+       (t
+        ;; Ignore artifacts.
+        (context-coloring-elisp-forward-sexp)))
+      (when (eq type 'let*)
+        (context-coloring-elisp-add-variable (pop varlist)))
+      (context-coloring-elisp-forward-sws))
+    (when (eq type 'let)
+      (while varlist
+        (context-coloring-elisp-add-variable (pop varlist))))
+    ;; Exit.
+    (forward-char)))
+
+(defun context-coloring-elisp-parse-arglist ()
+  "Parse the list of function arguments at point."
+  (let (syntax-code)
+    ;; Enter.
+    (forward-char)
+    (while (/= (setq syntax-code (context-coloring-get-syntax-code))
+               context-coloring-CLOSE-PARENTHESIS-CODE)
+      (cond
+       ((context-coloring-elisp-identifier-p syntax-code)
+        (context-coloring-elisp-parse-bindable
+         (lambda (arg)
+           (context-coloring-elisp-add-variable arg))))
+       (t
+        ;; Ignore artifacts.
+        (context-coloring-elisp-forward-sexp)))
+      (context-coloring-elisp-forward-sws))
+    ;; Exit.
+    (forward-char)))
+
+(defun context-coloring-elisp-skip-callee-name ()
+  "Skip past the opening parenthesis and name of a function."
+  ;; Enter.
+  (forward-char)
+  (context-coloring-elisp-forward-sws)
+  ;; Skip past the function name.
+  (forward-sexp)
+  (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."
+  (let ((start (point))
+        (end (progn (forward-sexp)
+                    (point))))
+    (context-coloring-elisp-push-scope)
+    ;; Splash the whole thing in one color.
+    (context-coloring-colorize-region
+     start
+     end
+     (context-coloring-elisp-get-current-scope-level))
+    ;; Even if the parse is interrupted, this region should still be colored
+    ;; syntactically.
+    (context-coloring-elisp-colorize-comments-and-strings-in-region
+     start
+     end)
+    (goto-char start)
+    (context-coloring-elisp-skip-callee-name)
+    (funcall callback)
+    (context-coloring-elisp-colorize-region (point) (1- end))
+    ;; Exit.
+    (forward-char)
+    (context-coloring-elisp-pop-scope)))
+
+(defun context-coloring-elisp-parse-header (callback start)
+  "Parse a function header at point with CALLBACK.  If there is
+no header, skip past the sexp at START."
+  (cond
+   ((= (context-coloring-get-syntax-code) 
context-coloring-OPEN-PARENTHESIS-CODE)
+    (funcall callback))
+   (t
+    ;; Skip it.
+    (goto-char start)
+    (context-coloring-elisp-forward-sexp))))
+
+(defun context-coloring-elisp-colorize-defun-like (callback)
+  "Color the defun-like function at point, parsing the header
+with CALLBACK."
+  (let ((start (point)))
+    (context-coloring-elisp-colorize-scope
+     (lambda ()
+       (cond
+        ((context-coloring-elisp-identifier-p 
(context-coloring-get-syntax-code))
+         ;; Color the defun's name with the top-level color.
+         (context-coloring-colorize-region
+          (point)
+          (progn (forward-sexp)
+                 (point))
+          0)
+         (context-coloring-elisp-forward-sws)
+         (context-coloring-elisp-parse-header callback start))
+        (t
+         ;; Skip it.
+         (goto-char start)
+         (context-coloring-elisp-forward-sexp)))))))
+
+(defun context-coloring-elisp-colorize-defun ()
+  "Color the `defun' at point."
+  (context-coloring-elisp-colorize-defun-like
+   'context-coloring-elisp-parse-arglist))
+
+(defun context-coloring-elisp-colorize-defadvice ()
+  "Color the `defadvice' at point."
+  (context-coloring-elisp-colorize-defun-like
+   (lambda ()
+     (let (syntax-code)
+       ;; Enter.
+       (forward-char)
+       (while (/= (setq syntax-code (context-coloring-get-syntax-code))
+                  context-coloring-CLOSE-PARENTHESIS-CODE)
+         (cond
+          ((= syntax-code context-coloring-OPEN-PARENTHESIS-CODE)
+           (context-coloring-elisp-parse-arglist))
+          (t
+           ;; Ignore artifacts.
+           (context-coloring-elisp-forward-sexp)))
+         (context-coloring-elisp-forward-sws))
+       ;; Exit.
+       (forward-char)))))
+
+(defun context-coloring-elisp-colorize-lambda-like (callback)
+  "Color the lambda-like function at point, parsing the header
+with CALLBACK."
+  (let ((start (point)))
+    (context-coloring-elisp-colorize-scope
+     (lambda ()
+       (context-coloring-elisp-parse-header callback start)))))
+
+(defun context-coloring-elisp-colorize-lambda ()
+  "Color the `lambda' at point."
+  (context-coloring-elisp-colorize-lambda-like
+   'context-coloring-elisp-parse-arglist))
+
+(defun context-coloring-elisp-colorize-let ()
+  "Color the `let' at point."
+  (context-coloring-elisp-colorize-lambda-like
+   (lambda ()
+     (context-coloring-elisp-parse-let-varlist 'let))))
+
+(defun context-coloring-elisp-colorize-let* ()
+  "Color the `let*' at point."
+  (context-coloring-elisp-colorize-lambda-like
+   (lambda ()
+     (context-coloring-elisp-parse-let-varlist 'let*))))
+
+(defun context-coloring-elisp-colorize-cond ()
+  "Color the `cond' at point."
+  (let (syntax-code)
+    (context-coloring-elisp-skip-callee-name)
+    (while (/= (setq syntax-code (context-coloring-get-syntax-code))
+               context-coloring-CLOSE-PARENTHESIS-CODE)
+      (cond
+       ((= syntax-code context-coloring-OPEN-PARENTHESIS-CODE)
+        ;; Colorize inside the parens.
+        (let ((start (point)))
+          (forward-sexp)
+          (context-coloring-elisp-colorize-region
+           (1+ start) (1- (point)))
+          ;; Exit.
+          (forward-char)))
+       (t
+        ;; Ignore artifacts.
+        (context-coloring-elisp-forward-sexp)))
+      (context-coloring-elisp-forward-sws))
+    ;; Exit.
+    (forward-char)))
+
+(defun context-coloring-elisp-colorize-condition-case ()
+  "Color the `condition-case' at point."
+  (let (syntax-code
+        variable
+        case-pos
+        case-end)
+    (context-coloring-elisp-colorize-scope
+     (lambda ()
+       (setq syntax-code (context-coloring-get-syntax-code))
+       ;; Gracefully ignore missing variables.
+       (when (context-coloring-elisp-identifier-p syntax-code)
+         (context-coloring-elisp-parse-bindable
+          (lambda (parsed-variable)
+            (setq variable parsed-variable)))
+         (context-coloring-elisp-forward-sws))
+       (context-coloring-elisp-colorize-sexp)
+       (context-coloring-elisp-forward-sws)
+       ;; Parse the handlers with the error variable in scope.
+       (when variable
+         (context-coloring-elisp-add-variable variable))
+       (while (/= (setq syntax-code (context-coloring-get-syntax-code))
+                  context-coloring-CLOSE-PARENTHESIS-CODE)
+         (cond
+          ((= syntax-code context-coloring-OPEN-PARENTHESIS-CODE)
+           (setq case-pos (point))
+           (context-coloring-elisp-forward-sexp)
+           (setq case-end (point))
+           (goto-char case-pos)
+           ;; Enter.
+           (forward-char)
+           (context-coloring-elisp-forward-sws)
+           (setq syntax-code (context-coloring-get-syntax-code))
+           (when (/= syntax-code context-coloring-CLOSE-PARENTHESIS-CODE)
+             ;; Skip the condition name(s).
+             (context-coloring-elisp-forward-sexp)
+             ;; Color the remaining portion of the handler.
+             (context-coloring-elisp-colorize-region
+              (point)
+              (1- case-end)))
+           ;; Exit.
+           (forward-char))
+          (t
+           ;; Ignore artifacts.
+           (context-coloring-elisp-forward-sexp)))
+         (context-coloring-elisp-forward-sws))))))
+
+(defun context-coloring-elisp-colorize-dolist ()
+  "Color the `dolist' at point."
+  (let (syntax-code
+        (index 0))
+    (context-coloring-elisp-colorize-scope
+     (lambda ()
+       (setq syntax-code (context-coloring-get-syntax-code))
+       (when (= syntax-code context-coloring-OPEN-PARENTHESIS-CODE)
+         (forward-char)
+         (context-coloring-elisp-forward-sws)
+         (while (/= (setq syntax-code (context-coloring-get-syntax-code))
+                    context-coloring-CLOSE-PARENTHESIS-CODE)
+           (cond
+            ((and
+              (or (= index 0) (= index 2))
+              (context-coloring-elisp-identifier-p syntax-code))
+             ;; Add the first or third name to the scope.
+             (context-coloring-elisp-parse-bindable
+              (lambda (variable)
+                (context-coloring-elisp-add-variable variable))))
+            (t
+             ;; Color artifacts.
+             (context-coloring-elisp-colorize-sexp)))
+           (context-coloring-elisp-forward-sws)
+           (setq index (1+ index)))
+         ;; Exit.
+         (forward-char))))))
+
+(defun context-coloring-elisp-colorize-quote ()
+  "Color the `quote' at point."
+  (let* ((start (point))
+         (end (progn (forward-sexp)
+                     (point))))
+    (context-coloring-colorize-region
+     start
+     end
+     (context-coloring-elisp-get-current-scope-level))
+    (context-coloring-elisp-colorize-comments-and-strings-in-region start 
end)))
+
+(defvar context-coloring-elisp-callee-dispatch-hash-table
+  (let ((table (make-hash-table :test 'equal)))
+    (dolist (callee '("defun" "defun*" "defsubst" "defmacro" "cl-defun" 
"cl-defsubst" "cl-defmacro"))
+      (puthash callee #'context-coloring-elisp-colorize-defun table))
+    (dolist (callee '("condition-case" "condition-case-unless-debug"))
+      (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)
+    (puthash "let*" #'context-coloring-elisp-colorize-let* 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)
+    (puthash "quote" #'context-coloring-elisp-colorize-quote table)
+    (puthash "backquote" #'context-coloring-elisp-colorize-backquote table)
+    table)
+  "Map function names to their coloring functions.")
+
+(defun context-coloring-elisp-colorize-parenthesized-sexp ()
+  "Color the sexp enclosed by parenthesis at point."
+  (context-coloring-elisp-increment-sexp-count)
+  (let* ((start (point))
+         (end (progn (forward-sexp)
+                     (point)))
+         (syntax-code (progn (goto-char start)
+                             (forward-char)
+                             ;; Coloring is unnecessary here, it'll happen
+                             ;; presently.
+                             (context-coloring-forward-sws)
+                             (context-coloring-get-syntax-code)))
+         dispatch-function)
+    ;; Figure out if the sexp is a special form.
+    (cond
+     ((and (context-coloring-elisp-identifier-p syntax-code)
+           (setq dispatch-function (gethash
+                                    (buffer-substring-no-properties
+                                     (point)
+                                     (progn (forward-sexp)
+                                            (point)))
+                                    
context-coloring-elisp-callee-dispatch-hash-table)))
+      (goto-char start)
+      (funcall dispatch-function))
+     ;; Not a special form; just colorize the remaining region.
+     (t
+      (context-coloring-colorize-region
+       start
+       end
+       (context-coloring-elisp-get-current-scope-level))
+      (context-coloring-elisp-colorize-region (point) (1- end))
+      (forward-char)))))
+
+(defun context-coloring-elisp-colorize-symbol ()
+  "Color the symbol at point."
+  (context-coloring-elisp-increment-sexp-count)
+  (let* ((symbol-pos (point))
+         (symbol-end (progn (forward-sexp)
+                            (point)))
+         (symbol-string (buffer-substring-no-properties
+                         symbol-pos
+                         symbol-end)))
+    (cond
+     ((string-match-p context-coloring-elisp-ignored-word-regexp 
symbol-string))
+     (t
+      (context-coloring-colorize-region
+       symbol-pos
+       symbol-end
+       (context-coloring-elisp-get-variable-level
+        symbol-string))))))
+
+(defun context-coloring-elisp-colorize-backquote-form ()
+  "Color the backquote form at point."
+  (let ((start (point))
+        (end (progn (forward-sexp)
+                    (point)))
+        char)
+    (goto-char start)
+    (while (> end (progn (forward-char)
+                         (point)))
+      (setq char (char-after))
+      (when (= char context-coloring-COMMA-CHAR)
+        (forward-char)
+        (when (= (char-after) context-coloring-AT-CHAR)
+          ;; If we don't do this "@" could be interpreted as a symbol.
+          (forward-char))
+        (context-coloring-elisp-forward-sws)
+        (context-coloring-elisp-colorize-sexp)))
+    ;; We could probably do this as part of the above loop but it'd be
+    ;; repetitive.
+    (context-coloring-elisp-colorize-comments-and-strings-in-region
+     start end)))
+
+(defun context-coloring-elisp-colorize-backquote ()
+  "Color the `backquote' at point."
+  (context-coloring-elisp-skip-callee-name)
+  (context-coloring-elisp-colorize-backquote-form)
+  ;; Exit.
+  (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."
+  (context-coloring-elisp-increment-sexp-count)
+  (cond
+   ((/= (char-after) context-coloring-BACKTICK-CHAR)
+    (context-coloring-elisp-forward-sexp))
+   (t
+    (context-coloring-elisp-colorize-backquote-form))))
+
+(defun context-coloring-elisp-colorize-comment ()
+  "Color the comment at point."
+  (context-coloring-elisp-increment-sexp-count)
+  (context-coloring-elisp-forward-sws))
+
+(defun context-coloring-elisp-colorize-string ()
+  "Color the string at point."
+  (context-coloring-elisp-increment-sexp-count)
+  (let ((start (point)))
+    (forward-sexp)
+    (context-coloring-colorize-comments-and-strings start (point))))
+
+;; Elisp has whitespace, words, symbols, open/close parenthesis, expression
+;; prefix, string quote, comment starters/enders and escape syntax classes 
only.
+
+(defun context-coloring-elisp-colorize-sexp ()
+  "Color the sexp at point."
+  (let ((syntax-code (context-coloring-get-syntax-code)))
+    (cond
+     ((= syntax-code context-coloring-OPEN-PARENTHESIS-CODE)
+      (context-coloring-elisp-colorize-parenthesized-sexp))
+     ((context-coloring-elisp-identifier-p syntax-code)
+      (context-coloring-elisp-colorize-symbol))
+     ((= syntax-code context-coloring-EXPRESSION-PREFIX-CODE)
+      (context-coloring-elisp-colorize-expression-prefix))
+     ((= syntax-code context-coloring-STRING-QUOTE-CODE)
+      (context-coloring-elisp-colorize-string))
+     ((= syntax-code context-coloring-ESCAPE-CODE)
+      (forward-char 2)))))
+
+(defun context-coloring-elisp-colorize-comments-and-strings-in-region (start 
end)
+  "Color comments and strings between START and END."
+  (let (syntax-code)
+    (goto-char start)
+    (while (> end (progn (skip-syntax-forward "^\"<\\" end)
+                         (point)))
+      (setq syntax-code (context-coloring-get-syntax-code))
+      (cond
+       ((= syntax-code context-coloring-STRING-QUOTE-CODE)
+        (context-coloring-elisp-colorize-string))
+       ((= syntax-code context-coloring-COMMENT-START-CODE)
+        (context-coloring-elisp-colorize-comment))
+       ((= syntax-code context-coloring-ESCAPE-CODE)
+        (forward-char 2))))))
+
+(defun context-coloring-elisp-colorize-region (start end)
+  "Color everything between START and END."
+  (let (syntax-code)
+    (goto-char start)
+    (while (> end (progn (skip-syntax-forward "^w_('\"<\\" end)
+                         (point)))
+      (setq syntax-code (context-coloring-get-syntax-code))
+      (cond
+       ((= syntax-code context-coloring-OPEN-PARENTHESIS-CODE)
+        (context-coloring-elisp-colorize-parenthesized-sexp))
+       ((context-coloring-elisp-identifier-p syntax-code)
+        (context-coloring-elisp-colorize-symbol))
+       ((= syntax-code context-coloring-EXPRESSION-PREFIX-CODE)
+        (context-coloring-elisp-colorize-expression-prefix))
+       ((= syntax-code context-coloring-STRING-QUOTE-CODE)
+        (context-coloring-elisp-colorize-string))
+       ((= syntax-code context-coloring-COMMENT-START-CODE)
+        (context-coloring-elisp-colorize-comment))
+       ((= syntax-code context-coloring-ESCAPE-CODE)
+        (forward-char 2))))))
+
+(defun context-coloring-elisp-colorize-region-initially (start end)
+  "Begin coloring everything between START and END."
+  (setq context-coloring-elisp-sexp-count 0)
+  (setq context-coloring-elisp-scope-stack '())
+  (let ((inhibit-point-motion-hooks t)
+        (case-fold-search nil)
+        ;; This is a recursive-descent parser, so give it a big stack.
+        (max-lisp-eval-depth (max max-lisp-eval-depth 3000))
+        (max-specpdl-size (max max-specpdl-size 3000)))
+    (context-coloring-elisp-colorize-region start end)))
+
+(defun context-coloring-elisp-colorize ()
+  "Color the current buffer, parsing elisp to determine its
+scopes and variables."
+  (interactive)
   (with-silent-modifications
     (save-excursion
-      ;; TODO: Can probably make this lazy to the nearest defun.
-      (goto-char (point-min))
-      (let* ((inhibit-point-motion-hooks t)
-             (end (point-max))
-             (iteration-count 0)
-             (last-fontified-position (point))
-             beginning-of-current-defun
-             end-of-current-defun
-             (last-ppss-pos (point))
-             (ppss (syntax-ppss))
-             ppss-depth
-             ;; -1 never matches a depth.  This is a minor optimization.
-             (scope-stack `(,(context-coloring-make-scope -1 0)))
-             (backtick-stack '())
-             (let-varlist-stack '())
-             (let-var-stack '())
-             popped-vars
-             one-word-found-p
-             in-defun-p
-             in-lambda-p
-             in-let-p
-             in-let*-p
-             defun-arglist
-             defun-arg
-             let-varlist
-             let-varlist-type
-             variable
-             variable-end
-             variable-string
-             variable-scope-level
-             token-pos
-             token-syntax
-             token-syntax-code
-             token-char
-             child-0-pos
-             child-0-end
-             child-0-syntax
-             child-0-syntax-code
-             child-0-string
-             child-1-pos
-             child-1-end
-             child-1-syntax
-             child-1-syntax-code
-             child-2-end)
-        (while (> end (progn (skip-syntax-forward "^()w_'" end)
-                             (point)))
-          ;; Sparingly-executed tasks.
-          (setq iteration-count (1+ iteration-count))
-          (when (zerop (% iteration-count
-                          context-coloring-emacs-lisp-iterations-per-pause))
-            ;; Fontify until the end of the current defun because doing it in
-            ;; chunks based soley on point could result in partial
-            ;; re-fontifications over the contents of scopes.
-            (save-excursion
-              (end-of-defun)
-              (setq end-of-current-defun (point))
-              (beginning-of-defun)
-              (setq beginning-of-current-defun (point)))
-
-            ;; Fontify in chunks.
-            (context-coloring-maybe-colorize-comments-and-strings
-             last-fontified-position
-             (cond
-              ;; We weren't actually in a defun, so don't color the next one, 
as
-              ;; that could result in `font-lock' properties being added to it.
-              ((> beginning-of-current-defun (point))
-               (point))
-              (t
-               end-of-current-defun)))
-            (setq last-fontified-position (point))
-            (when (and context-coloring-parse-interruptable-p
-                       (input-pending-p))
-              (throw 'interrupted t)))
-
-          (setq token-pos (point))
-          (setq token-syntax (syntax-after token-pos))
-          (setq token-syntax-code (logand #xFFFF (car token-syntax)))
-          (setq token-char (char-after))
-          (setq ppss (parse-partial-sexp last-ppss-pos token-pos nil nil ppss))
-          (setq last-ppss-pos token-pos)
+      (condition-case nil
           (cond
-
-           ;; Resolve an invalid state.
-           ((cond
-             ;; Inside string?
-             ((nth 3 ppss)
-              (skip-syntax-forward "^\"" end)
-              (forward-char)
-              t)
-             ;; Inside comment?
-             ((nth 4 ppss)
-              (skip-syntax-forward "^>" end)
-              t)))
-
-           ;; Need to check early in case there's a comma.
-           ((context-coloring-expression-prefix-p token-syntax-code)
-            (forward-char)
-            (cond
-             ;; Skip top-level symbols.
-             ((not (or backtick-stack
-                       (= token-char context-coloring-BACKTICK-CHAR)))
-              (goto-char (context-coloring-forward-sexp-position)))
-             ;; Push a backtick state.
-             ((or (= token-char context-coloring-BACKTICK-CHAR)
-                  (= token-char context-coloring-COMMA-CHAR))
-              (setq backtick-stack (cons (context-coloring-make-backtick
-                                          
(context-coloring-forward-sexp-position)
-                                          (= token-char 
context-coloring-BACKTICK-CHAR))
-                                         backtick-stack)))))
-
-           ;; Pop a backtick state.
-           ((and backtick-stack
-                 (>= (point) (context-coloring-backtick-get-end (car 
backtick-stack))))
-            (setq backtick-stack (cdr backtick-stack)))
-
-           ;; Restricted by an enabled backtick.
-           ((and backtick-stack
-                 (context-coloring-backtick-enabled-p backtick-stack))
-            (forward-char))
-
-           ((context-coloring-open-parenthesis-p token-syntax-code)
-            (forward-char)
-            ;; Look for function calls.
-            (context-coloring-forward-sws)
-            (setq child-0-pos (point))
-            (setq child-0-syntax (syntax-after child-0-pos))
-            (setq child-0-syntax-code (logand #xFFFF (car child-0-syntax)))
-            (cond
-             ((context-coloring-emacs-lisp-identifier-syntax-p 
child-0-syntax-code)
-              (setq one-word-found-p t)
-              (setq child-0-end (scan-sexps child-0-pos 1))
-              (setq child-0-string (buffer-substring-no-properties child-0-pos 
child-0-end))
-              (cond
-               ;; Parse a var in a `let' varlist.
-               ((and
-                 let-varlist-stack
-                 (context-coloring-at-stack-depth-p
-                  let-varlist-stack
-                  ;; 1- because we're inside the varlist.
-                  (1- (context-coloring-ppss-depth ppss))))
-                (context-coloring-let-varlist-add-var
-                 (car let-varlist-stack)
-                 (intern child-0-string))
-                (setq let-var-stack (cons (context-coloring-ppss-depth ppss)
-                                          let-var-stack)))
-               ((string-match-p context-coloring-emacs-lisp-defun-regexp 
child-0-string)
-                (setq in-defun-p t))
-               ((string-match-p context-coloring-emacs-lisp-lambda-regexp 
child-0-string)
-                (setq in-lambda-p t))
-               ((string-match-p context-coloring-emacs-lisp-let-regexp 
child-0-string)
-                (setq in-let-p t)
-                (setq let-varlist-type 'let))
-               ((string-match-p context-coloring-emacs-lisp-let*-regexp 
child-0-string)
-                (setq in-let*-p t)
-                (setq let-varlist-type 'let*)))))
-            (when (or in-defun-p
-                      in-lambda-p
-                      in-let-p
-                      in-let*-p)
-              (setq scope-stack (cons (context-coloring-make-scope
-                                       (context-coloring-ppss-depth ppss)
-                                       (1+ (context-coloring-scope-get-level
-                                            (car scope-stack))))
-                                      scope-stack)))
-            ;; TODO: Maybe wasteful but doing this conditionally doesn't make
-            ;; much of a difference.
-            (context-coloring-colorize-region token-pos
-                                              (scan-sexps token-pos 1)
-                                              (context-coloring-scope-get-level
-                                               (car scope-stack)))
-            (cond
-             ((or in-defun-p
-                  in-lambda-p)
-              (goto-char child-0-end)
-              (when in-defun-p
-                ;; Look for a function name.
-                (context-coloring-forward-sws)
-                (setq child-1-pos (point))
-                (setq child-1-syntax (syntax-after child-1-pos))
-                (setq child-1-syntax-code (logand #xFFFF (car child-1-syntax)))
-                (cond
-                 ((context-coloring-emacs-lisp-identifier-syntax-p 
child-1-syntax-code)
-                  (setq child-1-end (scan-sexps child-1-pos 1))
-                  ;; Defuns are global, so use level 0.
-                  (context-coloring-colorize-region child-1-pos child-1-end 0)
-                  (goto-char child-1-end))))
-              ;; Look for an arglist.
-              (context-coloring-forward-sws)
-              (when (context-coloring-at-open-parenthesis-p)
-                ;; (Actually it should be `child-1-end' for `lambda'.)
-                (setq child-2-end (context-coloring-forward-sexp-position))
-                (setq defun-arglist (read (buffer-substring-no-properties
-                                           (point)
-                                           child-2-end)))
-                (while defun-arglist
-                  (setq defun-arg (car defun-arglist))
-                  (when (and (symbolp defun-arg)
-                             (string-match-p
-                              context-coloring-arglist-arg-regexp
-                              (symbol-name defun-arg)))
-                    (context-coloring-scope-add-variable
-                     (car scope-stack)
-                     defun-arg))
-                  (setq defun-arglist (cdr defun-arglist)))
-                (goto-char child-2-end))
-              ;; Cleanup.
-              (setq in-defun-p nil)
-              (setq in-lambda-p nil))
-             ((or in-let-p
-                  in-let*-p)
-              (goto-char child-0-end)
-              ;; Look for a varlist.
-              (context-coloring-forward-sws)
-              (setq child-1-pos (point))
-              (setq child-1-syntax (syntax-after child-1-pos))
-              (setq child-1-syntax-code (logand #xFFFF (car child-1-syntax)))
-              (when (context-coloring-open-parenthesis-p child-1-syntax-code)
-                ;; Begin parsing the varlist.
-                (forward-char)
-                (setq let-varlist-stack (cons 
(context-coloring-make-let-varlist
-                                               ;; 1+ because we parsed it at a
-                                               ;; higher depth.
-                                               (1+ 
(context-coloring-ppss-depth ppss))
-                                               let-varlist-type)
-                                              let-varlist-stack)))
-              ;; Cleanup.
-              (setq in-let-p nil)
-              (setq in-let*-p nil))
-             (t
-              (goto-char (cond
-                          ;; If there was a word, continue parsing after it.
-                          (one-word-found-p
-                           (1+ child-0-end))
-                          (t
-                           (1+ token-pos))))))
-            ;; Cleanup.
-            (setq one-word-found-p nil))
-
-           ((context-coloring-emacs-lisp-identifier-syntax-p token-syntax-code)
-            (setq variable-end (context-coloring-forward-sexp-position))
-            (setq variable-string (buffer-substring-no-properties
-                                   token-pos
-                                   variable-end))
-            (cond
-             ;; Ignore constants such as numbers, keywords, t, nil.  These 
can't
-             ;; be rebound, so they should be treated like syntax.
-             ((string-match-p context-coloring-ignored-word-regexp 
variable-string))
-             ((keywordp (read variable-string)))
-             (t
-              (setq variable (intern variable-string))
-              (cond
-               ;; Parse a `let' varlist's uninitialized var.
-               ((and
-                 let-varlist-stack
-                 (context-coloring-at-stack-depth-p
-                  let-varlist-stack
-                  ;; 1- because we're inside the varlist.
-                  (1- (context-coloring-ppss-depth ppss))))
-                (setq let-varlist (car let-varlist-stack))
-                (setq let-varlist-type (context-coloring-let-varlist-get-type 
let-varlist))
-                (cond
-                 ;; Defer `let' binding until the end of the varlist.
-                 ((eq let-varlist-type 'let)
-                  (context-coloring-let-varlist-add-var let-varlist variable))
-                 ;; Bind a `let*' right away.
-                 ((eq let-varlist-type 'let*)
-                  (context-coloring-scope-add-variable (car scope-stack) 
variable))))
-               (t
-                (setq variable-scope-level
-                      (context-coloring-get-variable-level scope-stack 
variable))
-                (when (/= variable-scope-level 
(context-coloring-scope-get-level
-                                                (car scope-stack)))
-                  (context-coloring-colorize-region
-                   token-pos
-                   variable-end
-                   variable-scope-level))))))
-            (goto-char variable-end))
-
-           ((context-coloring-close-parenthesis-p token-syntax-code)
-            (forward-char)
-            (setq ppss (parse-partial-sexp last-ppss-pos (point) nil nil ppss))
-            (setq last-ppss-pos (point))
-            (setq ppss-depth (context-coloring-ppss-depth ppss))
-            ;; TODO: Order might matter here but I'm not certain.
-            (when (context-coloring-at-stack-depth-p scope-stack ppss-depth)
-              (setq scope-stack (cdr scope-stack)))
-            (when (and
-                   let-var-stack
-                   (= (car let-var-stack) ppss-depth))
-              (setq let-var-stack (cdr let-var-stack))
-              (when (eq (context-coloring-let-varlist-get-type (car 
let-varlist-stack))
-                        'let*)
-                (setq popped-vars (context-coloring-let-varlist-pop-vars
-                                   (car let-varlist-stack)))))
-            (when (and
-                   let-varlist-stack
-                   (context-coloring-at-stack-depth-p let-varlist-stack 
ppss-depth))
-              (setq popped-vars (context-coloring-let-varlist-pop-vars
-                                 (car let-varlist-stack)))
-              (setq let-varlist-stack (cdr let-varlist-stack)))
-            (while popped-vars
-              (context-coloring-scope-add-variable (car scope-stack) (car 
popped-vars))
-              (setq popped-vars (cdr popped-vars))))
-
-           ))
-        ;; Fontify the last stretch.
-        (context-coloring-maybe-colorize-comments-and-strings
-         last-fontified-position
-         (point))))))
+           ;; Just colorize the changed region.
+           (context-coloring-changed-p
+            (let* (;; Prevent `beginning-of-defun' from making poor 
assumptions.
+                   (open-paren-in-column-0-is-defun-start nil)
+                   ;; Seek the beginning and end of the previous and next
+                   ;; offscreen defuns, so just enough is colored.
+                   (start (progn (goto-char context-coloring-changed-start)
+                                 (while (and (< (point-min) (point))
+                                             (pos-visible-in-window-p))
+                                   (end-of-line 0))
+                                 (beginning-of-defun)
+                                 (point)))
+                   (end (progn (goto-char context-coloring-changed-end)
+                               (while (and (> (point-max) (point))
+                                           (pos-visible-in-window-p))
+                                 (forward-line 1))
+                               (end-of-defun)
+                               (point))))
+              (context-coloring-elisp-colorize-region-initially start end)
+              ;; Fast coloring is nice, but if the code is not well-formed
+              ;; (e.g. an unclosed string literal is parsed at any time) then
+              ;; there could be leftover incorrectly-colored code offscreen.  
So
+              ;; do a clean sweep as soon as appropriate.
+              (context-coloring-schedule-coloring 
context-coloring-default-delay)))
+           (t
+            (context-coloring-elisp-colorize-region-initially (point-min) 
(point-max))))
+        ;; Scan errors can happen virtually anywhere if parenthesis are
+        ;; unbalanced.  Just swallow them.  (`progn' for test coverage.)
+        (scan-error (progn))))))
 
 
 ;;; Shell command scopification / colorization
 
 (defun context-coloring-apply-tokens (tokens)
-  "Process 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."
-  (with-silent-modifications
-    (let ((i 0)
-          (len (length tokens)))
-      (while (< i len)
-        (context-coloring-colorize-region
-         (elt tokens i)
-         (elt tokens (+ i 1))
-         (elt tokens (+ i 2)))
-        (setq i (+ i 3))))
-    (context-coloring-maybe-colorize-comments-and-strings)))
+  "Process a string of TOKENS to apply context-based coloring to
+the current buffer.  Tokens are 3 integers: start, end, level.  A
+new token occurrs after every 3rd element, and the elements are
+separated by commas."
+  (let* ((tokens (mapcar #'string-to-number (split-string tokens ","))))
+    (while tokens
+      (context-coloring-colorize-region
+       (pop tokens)
+       (pop tokens)
+       (pop tokens))))
+  (context-coloring-colorize-comments-and-strings))
 
 (defun context-coloring-parse-array (array)
-  "Parse ARRAY as a flat JSON array of numbers."
-  (let ((braceless (substring (context-coloring-trim array) 1 -1)))
-    (cond
-     ((> (length braceless) 0)
-      (vconcat
-       (mapcar 'string-to-number (split-string braceless ","))))
-     (t
-      (vector)))))
+  "Parse ARRAY as a flat JSON array of numbers and use the tokens
+to colorize the buffer."
+  (let* ((braceless (substring-no-properties (context-coloring-trim array) 1 
-1)))
+    (when (> (length braceless) 0)
+      (with-silent-modifications
+        (context-coloring-apply-tokens braceless)))))
+
+(defvar-local context-coloring-scopifier-cancel-function nil
+  "Kills the current scopification process.")
 
 (defvar-local context-coloring-scopifier-process nil
   "The single scopifier process that can be running.")
 
-(defun context-coloring-kill-scopifier ()
-  "Kill the currently-running scopifier process."
+(defun context-coloring-cancel-scopification ()
+  "Stop the currently-running scopifier from scopifying."
+  (when context-coloring-scopifier-cancel-function
+    (funcall context-coloring-scopifier-cancel-function)
+    (setq context-coloring-scopifier-cancel-function nil))
   (when (not (null context-coloring-scopifier-process))
     (delete-process context-coloring-scopifier-process)
     (setq context-coloring-scopifier-process nil)))
 
-(defun context-coloring-scopify-shell-command (command callback)
-  "Invoke a scopifier via COMMAND, read its response
-asynchronously and invoke CALLBACK with its output."
-
-  ;; Prior running tokenization is implicitly obsolete if this function is
-  ;; called.
-  (context-coloring-kill-scopifier)
-
-  ;; Start the process.
-  (setq context-coloring-scopifier-process
-        (start-process-shell-command "scopifier" nil command))
-
-  (let ((output ""))
-
+(defun context-coloring-shell-command (command callback)
+  "Invoke COMMAND, read its response asynchronously and invoke
+CALLBACK with its output.  Return the command process."
+  (let ((process (start-process-shell-command "context-coloring-process" nil 
command))
+        (output ""))
     ;; The process may produce output in multiple chunks.  This filter
     ;; accumulates the chunks into a message.
     (set-process-filter
-     context-coloring-scopifier-process
+     process
      (lambda (_process chunk)
        (setq output (concat output chunk))))
-
     ;; When the process's message is complete, this sentinel parses it as JSON
     ;; and applies the tokens to the buffer.
     (set-process-sentinel
-     context-coloring-scopifier-process
+     process
      (lambda (_process event)
        (when (equal "finished\n" event)
-         (funcall callback output))))))
+         (funcall callback output))))
+    process))
+
+(defun context-coloring-scopify-shell-command (command callback)
+  "Invoke a scopifier via COMMAND, read its response
+asynchronously and invoke CALLBACK with its output."
+  ;; Prior running tokenization is implicitly obsolete if this function is
+  ;; called.
+  (context-coloring-cancel-scopification)
+  ;; Start the process.
+  (setq context-coloring-scopifier-process
+        (context-coloring-shell-command command callback)))
 
 (defun context-coloring-send-buffer-to-scopifier ()
   "Give the scopifier process its input so it can begin
@@ -815,31 +1124,103 @@ scopifying."
   (process-send-eof
    context-coloring-scopifier-process))
 
-(defun context-coloring-scopify-and-colorize (command &optional callback)
-  "Invoke a scopifier via COMMAND with the current buffer's contents,
-read the scopifier's response asynchronously and apply a parsed
-list of tokens to `context-coloring-apply-tokens'.
+(defun context-coloring-start-scopifier-server (command host port callback)
+  "Connect to or start a scopifier server with COMMAND, HOST and PORT.
+Invoke CALLBACK with a network stream when the server is ready
+for connections."
+  (let* ((connect
+          (lambda ()
+            (let ((stream (open-network-stream "context-coloring-stream" nil 
host port)))
+              (funcall callback stream)))))
+    ;; Try to connect in case a server is running, otherwise start one.
+    (condition-case nil
+        (progn
+          (funcall connect))
+      (error
+       (let ((server (start-process-shell-command
+                      "context-coloring-scopifier-server" nil
+                      (context-coloring-join
+                       (list command
+                             "--server"
+                             "--host" host
+                             "--port" (number-to-string port))
+                       " ")))
+             (output ""))
+         ;; Connect as soon as the "listening" message is printed.
+         (set-process-filter
+          server
+          (lambda (_process chunk)
+            (setq output (concat output chunk))
+            (when (string-match-p (format "^Scopifier listening at %s:%s$" 
host port) output)
+              (funcall connect)))))))))
+
+(defun context-coloring-send-buffer-to-scopifier-server (command host port 
callback)
+  "Send the current buffer to the scopifier server running with
+COMMAND, HOST and PORT.  Invoke CALLBACK with the server's
+response (a stringified JSON array)."
+  (context-coloring-start-scopifier-server
+   command host port
+   (lambda (process)
+     (let* ((body (buffer-substring-no-properties (point-min) (point-max)))
+            (header (concat "POST / HTTP/1.0\r\n"
+                            "Host: localhost\r\n"
+                            "Content-Type: application/x-www-form-urlencoded"
+                            "; charset=UTF8\r\n"
+                            (format "Content-Length: %d\r\n" (length body))
+                            "\r\n"))
+            (output "")
+            (active t))
+       (set-process-filter
+        process
+        (lambda (_process chunk)
+          (setq output (concat output chunk))))
+       (set-process-sentinel
+        process
+        (lambda (_process event)
+          (when (and (equal "connection broken by remote peer\n" event)
+                     active)
+            ;; Strip the response headers.
+            (string-match "\r\n\r\n" output)
+            (setq output (substring-no-properties output (match-end 0)))
+            (funcall callback output))))
+       (process-send-string process (concat header body "\r\n"))
+       (setq context-coloring-scopifier-cancel-function
+             (lambda ()
+               "Cancel this scopification."
+               (setq active nil)))))))
+
+(defun context-coloring-scopify-and-colorize-server (command host port 
&optional callback)
+  "Color the current buffer via the server started with COMMAND,
+HOST and PORT.  Invoke CALLBACK when complete."
+  (let ((buffer (current-buffer)))
+    (context-coloring-send-buffer-to-scopifier-server
+     command host port
+     (lambda (output)
+       (with-current-buffer buffer
+         (context-coloring-parse-array output))
+       (when callback (funcall callback))))))
 
-Invoke CALLBACK when complete."
+(defun context-coloring-scopify-and-colorize (command &optional callback)
+  "Color the current buffer via COMMAND.  Invoke CALLBACK when
+complete."
   (let ((buffer (current-buffer)))
     (context-coloring-scopify-shell-command
      command
      (lambda (output)
-       (let ((tokens (context-coloring-parse-array output)))
-         (with-current-buffer buffer
-           (context-coloring-apply-tokens tokens))
-         (setq context-coloring-scopifier-process nil)
-         (when callback (funcall callback))))))
+       (with-current-buffer buffer
+         (context-coloring-parse-array output))
+       (setq context-coloring-scopifier-process nil)
+       (when callback (funcall callback)))))
   (context-coloring-send-buffer-to-scopifier))
 
 
 ;;; Dispatch
 
-(defvar context-coloring-dispatch-hash-table (make-hash-table :test 'eq)
+(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.")
+lists, which contain details about the strategies.")
 
-(defvar context-coloring-mode-hash-table (make-hash-table :test 'eq)
+(defvar context-coloring-mode-hash-table (make-hash-table :test #'eq)
   "Map major mode names to dispatch property lists.")
 
 (defun context-coloring-get-dispatch-for-mode (mode)
@@ -856,11 +1237,11 @@ Invoke CALLBACK when complete."
 
 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.
+and color in a single function (`:colorizer'), parse with a shell
+command that returns scope data (`:command'), or parse with a
+server that returns scope data (`:command', `:host' and `:port').
+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'.
@@ -870,9 +1251,6 @@ PROPERTIES must include `:modes' and one of `:colorizer',
 `: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'.
 
@@ -880,6 +1258,13 @@ buffer a returns a flat vector of start, end and level 
data.
 sent via stdin, and with a flat JSON array of start, end and
 level data returned via stdout.
 
+`:host' - Hostname of the scopifier server, e.g. \"localhost\".
+
+`:port' - Port number of the scopifier server, e.g. 80, 1337.
+
+`:delay' - Delay between buffer update and colorization, to
+override `context-coloring-default-delay'.
+
 `:version' - Minimum required version that should be printed when
 executing `:command' with a \"--version\" flag.  The version
 should be numeric, e.g. \"2\", \"19700101\", \"1.2.3\",
@@ -892,14 +1277,12 @@ should be numeric, e.g. \"2\", \"19700101\", \"1.2.3\",
 `context-coloring-mode' is disabled."
   (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"))
+      (error "No colorizer or command defined for dispatch"))
     (puthash symbol properties context-coloring-dispatch-hash-table)
     (dolist (mode modes)
       (puthash mode properties context-coloring-mode-hash-table))))
@@ -920,24 +1303,12 @@ Invoke CALLBACK when complete; see 
`context-coloring-dispatch'."
      (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
-that it should be colored again by
-`context-coloring-colorize-idle-timer' if that timer is being
-used.")
-
-(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-kill-scopifier)
-  (setq context-coloring-changed t))
-
-(defun context-coloring-maybe-colorize (buffer)
-  "Colorize the current buffer if it has changed."
-  (when (and (eq buffer (current-buffer))
-             context-coloring-changed)
-    (setq context-coloring-changed nil)
-    (context-coloring-colorize)))
+(defun context-coloring-colorize-with-buffer (buffer)
+  "Color BUFFER."
+  ;; Don't select deleted buffers.
+  (when (get-buffer buffer)
+    (with-current-buffer buffer
+      (context-coloring-colorize))))
 
 
 ;;; Versioning
@@ -983,19 +1354,20 @@ version number required for the current major mode."
     (when dispatch
       (let ((version (plist-get dispatch :version))
             (command (plist-get dispatch :command)))
-        (context-coloring-scopify-shell-command
+        (context-coloring-shell-command
          (context-coloring-join (list command "--version") " ")
          (lambda (output)
-           (if (context-coloring-check-version version output)
-               (progn
-                 (when callback (funcall callback t)))
-             (when callback (funcall callback nil)))
+           (cond
+            ((context-coloring-check-version version output)
+             (when callback (funcall callback t)))
+            (t
+             (when callback (funcall callback nil))))
            (run-hooks 'context-coloring-check-scopifier-version-hook)))))))
 
 
 ;;; Themes
 
-(defvar context-coloring-theme-hash-table (make-hash-table :test 'eq)
+(defvar context-coloring-theme-hash-table (make-hash-table :test #'eq)
   "Map theme names to theme properties.")
 
 (defun context-coloring-theme-p (theme)
@@ -1007,9 +1379,9 @@ version number required for the current major mode."
   "Extract a level from a face.")
 
 (defvar context-coloring-originally-set-theme-hash-table
-  (make-hash-table :test 'eq)
+  (make-hash-table :test #'eq)
   "Cache custom themes who originally set their own
-  `context-coloring-level-N-face' faces.")
+`context-coloring-level-N-face' faces.")
 
 (defun context-coloring-theme-originally-set-p (theme)
   "Return t if there is a `context-coloring-level-N-face'
@@ -1086,7 +1458,7 @@ which must already exist and which *should* already be 
enabled."
     (when (custom-theme-enabled-p theme)
       (setq context-coloring-maximum-face (- (length colors) 1)))
     (apply
-     'custom-theme-set-faces
+     #'custom-theme-set-faces
      theme
      (mapcar
       (lambda (color)
@@ -1192,13 +1564,14 @@ precedence, i.e. the car of `custom-enabled-themes'."
   "Update `context-coloring-maximum-face'."
   (when (custom-theme-p theme) ; Guard against non-existent themes.
     (let ((enabled-theme (car custom-enabled-themes)))
-      (if (context-coloring-theme-p enabled-theme)
-          (progn
-            (context-coloring-enable-theme enabled-theme))
+      (cond
+       ((context-coloring-theme-p enabled-theme)
+        (context-coloring-enable-theme enabled-theme))
+       (t
         ;; Assume we are back to no theme; act as if nothing ever happened.
         ;; This is still prone to intervention, but rather extraordinarily.
         (setq context-coloring-maximum-face
-              context-coloring-original-maximum-face)))))
+              context-coloring-original-maximum-face))))))
 
 (context-coloring-define-theme
  'ample
@@ -1335,44 +1708,6 @@ precedence, i.e. the car of `custom-enabled-themes'."
            "#dca3a3"))
 
 
-;;; Change detection
-
-(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-kill-scopifier)
-  (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))
-
-
 ;;; Built-in dispatches
 
 (context-coloring-define-dispatch
@@ -1380,25 +1715,28 @@ Supported modes: `js-mode', `js3-mode', 
`emacs-lisp-mode'"
  :modes '(js-mode js3-mode)
  :executable "scopifier"
  :command "scopifier"
- :version "v1.1.1")
+ :version "v1.2.1"
+ :host "localhost"
+ :port 6969)
 
 (context-coloring-define-dispatch
  'javascript-js2
  :modes '(js2-mode)
- :colorizer 'context-coloring-js2-colorize
+ :colorizer #'context-coloring-js2-colorize
  :setup
  (lambda ()
-   (add-hook 'js2-post-parse-callbacks 'context-coloring-colorize nil t))
+   (add-hook 'js2-post-parse-callbacks #'context-coloring-colorize nil t))
  :teardown
  (lambda ()
-   (remove-hook 'js2-post-parse-callbacks 'context-coloring-colorize t)))
+   (remove-hook 'js2-post-parse-callbacks #'context-coloring-colorize t)))
 
 (context-coloring-define-dispatch
  'emacs-lisp
  :modes '(emacs-lisp-mode)
- :colorizer 'context-coloring-emacs-lisp-colorize
- :setup 'context-coloring-setup-idle-change-detection
- :teardown 'context-coloring-teardown-idle-change-detection)
+ :colorizer #'context-coloring-elisp-colorize
+ :delay 0.016 ;; Thanks to lazy colorization this can be 60 frames per second.
+ :setup #'context-coloring-setup-idle-change-detection
+ :teardown #'context-coloring-teardown-idle-change-detection)
 
 (defun context-coloring-dispatch (&optional callback)
   "Determine the optimal track for scopification / coloring of
@@ -1408,91 +1746,111 @@ Invoke CALLBACK when complete.  It is invoked 
synchronously for
 elisp tracks, and asynchronously for shell command tracks."
   (let* ((dispatch (context-coloring-get-dispatch-for-mode major-mode))
          (colorizer (plist-get dispatch :colorizer))
-         (scopifier (plist-get dispatch :scopifier))
          (command (plist-get dispatch :command))
+         (host (plist-get dispatch :host))
+         (port (plist-get dispatch :port))
          interrupted-p)
     (cond
-     ((or colorizer scopifier)
+     (colorizer
       (setq interrupted-p
             (catch 'interrupted
-              (cond
-               (colorizer
-                (funcall colorizer))
-               (scopifier
-                (context-coloring-apply-tokens (funcall scopifier))))))
+              (funcall colorizer)))
+      (when (and (not interrupted-p)
+                 callback)
+        (funcall callback)))
+     (command
       (cond
-       (interrupted-p
-        (setq context-coloring-changed t))
+       ((and host port)
+        (context-coloring-scopify-and-colorize-server command host port 
callback))
        (t
-        (when callback (funcall callback)))))
-     (command
-      (context-coloring-scopify-and-colorize command callback)))))
+        (context-coloring-scopify-and-colorize command callback)))))))
 
 
 ;;; Minor mode
 
 ;;;###autoload
 (define-minor-mode context-coloring-mode
-  "Context-based code coloring, inspired by Douglas Crockford."
+  "Toggle contextual code coloring.
+With a prefix argument ARG, enable Context Coloring mode if ARG
+is positive, and disable it otherwise.  If called from Lisp,
+enable the mode if ARG is omitted or nil.
+
+Context Coloring mode is a buffer-local minor mode.  When
+enabled, code is colored by scope.  Scopes are colored
+hierarchically.  Variables referenced from nested scopes retain
+the color of their defining scopes.  Certain syntax, like
+comments and strings, is still colored with `font-lock'.
+
+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.
+
+New language / major mode support can be added with
+`context-coloring-define-dispatch', which see.
+
+Feature inspired by Douglas Crockford."
   nil " Context" nil
-  (if (not context-coloring-mode)
-      (progn
-        (let ((dispatch (context-coloring-get-dispatch-for-mode major-mode)))
-          (when dispatch
-            (let ((command (plist-get dispatch :command))
-                  (teardown (plist-get dispatch :teardown)))
-              (when command
-                (context-coloring-teardown-idle-change-detection))
-              (when teardown
-                (funcall teardown)))))
-        (font-lock-mode)
-        (jit-lock-mode t))
-
+  (cond
+   (context-coloring-mode
     ;; Font lock is incompatible with this mode; the converse is also true.
     (font-lock-mode 0)
     (jit-lock-mode nil)
-
     ;; ...but we do use font-lock functions here.
     (font-lock-set-defaults)
-
-    ;; Safely change the valye of this function as necessary.
+    ;; Safely change the value of this function as necessary.
     (make-local-variable 'font-lock-syntactic-face-function)
-
     (let ((dispatch (context-coloring-get-dispatch-for-mode major-mode)))
-      (if dispatch
-          (progn
-            (let ((command (plist-get dispatch :command))
-                  (version (plist-get dispatch :version))
-                  (executable (plist-get dispatch :executable))
-                  (setup (plist-get dispatch :setup))
-                  (colorize-initially-p t))
-              (when command
-                ;; Shell commands recolor on change, idly.
-                (cond
-                 ((and executable
-                       (null (executable-find executable)))
-                  (message "Executable \"%s\" not found" executable)
-                  (setq colorize-initially-p nil))
-                 (version
-                  (context-coloring-check-scopifier-version
-                   (lambda (sufficient-p)
-                     (if sufficient-p
-                         (progn
-                           (context-coloring-setup-idle-change-detection)
-                           (context-coloring-colorize))
-                       (message "Update to the minimum version of \"%s\" (%s)"
-                                executable version))))
-                  (setq colorize-initially-p nil))
-                 (t
-                  (context-coloring-setup-idle-change-detection))))
-              (when setup
-                (funcall setup))
-              ;; Colorize once initially.
-              (when colorize-initially-p
-                (let ((context-coloring-parse-interruptable-p nil))
-                  (context-coloring-colorize)))))
-        (when (null dispatch)
-          (message "Context coloring is not available for this major 
mode"))))))
+      (cond
+       (dispatch
+        (let ((command (plist-get dispatch :command))
+              (version (plist-get dispatch :version))
+              (executable (plist-get dispatch :executable))
+              (setup (plist-get dispatch :setup))
+              (colorize-initially-p t))
+          (when command
+            ;; Shell commands recolor on change, idly.
+            (cond
+             ((and executable
+                   (null (executable-find executable)))
+              (message "Executable \"%s\" not found" executable)
+              (setq colorize-initially-p nil))
+             (version
+              (context-coloring-check-scopifier-version
+               (lambda (sufficient-p)
+                 (cond
+                  (sufficient-p
+                   (context-coloring-setup-idle-change-detection)
+                   (context-coloring-colorize))
+                  (t
+                   (message "Update to the minimum version of \"%s\" (%s)"
+                            executable version)))))
+              (setq colorize-initially-p nil))
+             (t
+              (context-coloring-setup-idle-change-detection))))
+          (when setup
+            (funcall setup))
+          ;; Colorize once initially.
+          (when colorize-initially-p
+            (let ((context-coloring-parse-interruptable-p nil))
+              (context-coloring-colorize)))))
+       (t
+        (message "Context coloring is not available for this major mode")))))
+   (t
+    (let ((dispatch (context-coloring-get-dispatch-for-mode major-mode)))
+      (when dispatch
+        (let ((command (plist-get dispatch :command))
+              (teardown (plist-get dispatch :teardown)))
+          (when command
+            (context-coloring-teardown-idle-change-detection))
+          (when teardown
+            (funcall teardown)))))
+    (font-lock-mode)
+    (jit-lock-mode t))))
 
 (provide 'context-coloring)
 
diff --git a/packages/context-coloring/test/context-coloring-coverage.el 
b/packages/context-coloring/test/context-coloring-coverage.el
index 2fe8fa9..107908c 100644
--- a/packages/context-coloring/test/context-coloring-coverage.el
+++ b/packages/context-coloring/test/context-coloring-coverage.el
@@ -53,7 +53,7 @@
 
 (defun context-coloring-coverage-join (strings delimiter)
   "Join a list of STRINGS with the string DELIMITER."
-  (mapconcat 'identity strings delimiter))
+  (mapconcat #'identity strings delimiter))
 
 (defun context-coloring-coverage-percentage (dividend divisor)
   "Get the percentage of DIVIDEND / DIVISOR with precision 2."
@@ -109,7 +109,7 @@
   "Generate reports for all files in COVERAGE-DATA."
   (context-coloring-coverage-join
    (mapcar
-    'context-coloring-coverage-format-source-file
+    #'context-coloring-coverage-format-source-file
     (cdr (assq 'source_files coverage-data)))
    "\n"))
 
@@ -119,7 +119,8 @@
   (setq undercover-force-coverage t)
   (setenv "COVERALLS_REPO_TOKEN" "noop")
   (undercover "context-coloring.el"
-              (:report-file context-coloring-coverage-output-file))
+              (:report-file context-coloring-coverage-output-file)
+              (:send-report nil))
   (add-hook
    'kill-emacs-hook
    (lambda ()
@@ -151,4 +152,4 @@
 
 (provide 'context-coloring-coverage)
 
-;; context-coloring-coverage.el ends here
+;;; 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 e22ee29..7020589 100644
--- a/packages/context-coloring/test/context-coloring-test.el
+++ b/packages/context-coloring/test/context-coloring-test.el
@@ -25,6 +25,7 @@
 
 ;;; Code:
 
+(require 'cl-lib)
 (require 'context-coloring)
 (require 'ert-async)
 (require 'js2-mode)
@@ -37,36 +38,18 @@
   "This file's directory.")
 
 (defun context-coloring-test-read-file (path)
-  "Read a file's contents from PATH into a string."
+  "Return the file's contents from PATH as a string."
   (with-temp-buffer
     (insert-file-contents (expand-file-name path context-coloring-test-path))
     (buffer-string)))
 
-(defun context-coloring-test-setup ()
-  "Prepare before all tests."
-  (setq context-coloring-syntactic-comments nil)
-  (setq context-coloring-syntactic-strings nil))
-
-(defun context-coloring-test-cleanup ()
-  "Cleanup after all tests."
-  (setq context-coloring-comments-and-strings nil)
-  (setq context-coloring-js-block-scopes 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
 buffer."
   `(with-temp-buffer
-     (unwind-protect
-         (progn
-           (context-coloring-test-setup)
-           (insert (context-coloring-test-read-file ,fixture))
-           ,@body)
-       (context-coloring-test-cleanup))))
+     (progn
+       (insert (context-coloring-test-read-file ,fixture))
+       ,@body)))
 
 (defun context-coloring-test-with-temp-buffer-async (callback)
   "Create a temporary buffer, and evaluate CALLBACK there.  A
@@ -82,273 +65,192 @@ is done."
             (kill-buffer temp-buffer))
        (set-buffer previous-buffer)))))
 
-(defun context-coloring-test-with-fixture-async
-    (fixture callback &optional setup)
+(defun context-coloring-test-with-fixture-async (fixture callback)
   "With the relative FIXTURE, evaluate CALLBACK in a temporary
 buffer.  A teardown callback is passed to CALLBACK for it to
-invoke when it is done.  An optional SETUP callback can run
-arbitrary code before the mode is invoked."
+invoke when it is done."
   (context-coloring-test-with-temp-buffer-async
    (lambda (done-with-temp-buffer)
-     (context-coloring-test-setup)
-     (when setup (funcall setup))
      (insert (context-coloring-test-read-file fixture))
      (funcall
       callback
       (lambda ()
-        (context-coloring-test-cleanup)
         (funcall done-with-temp-buffer))))))
 
 
 ;;; 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)
-     (js-mode)
-     (context-coloring-mode)
-     (context-coloring-colorize
-      (lambda ()
-        (funcall callback done-with-test))))
-   setup))
-
-(defmacro context-coloring-test-js2-mode (fixture setup &rest body)
-  "Use FIXTURE as the subject matter for test logic in BODY."
-  `(context-coloring-test-with-fixture
-    ,fixture
-    (require 'js2-mode)
-    (setq js2-mode-show-parse-errors nil)
-    (setq js2-mode-show-strict-warnings nil)
-    (js2-mode)
-    (when ,setup (funcall ,setup))
-    (context-coloring-mode)
-    ,@body))
-
-(cl-defmacro context-coloring-test-deftest-js-mode (name &key fixture-name)
-  "Define an asynchronous test for `js-mode' with the name NAME
-in the typical format."
+(cl-defmacro context-coloring-test-define-deftest (name
+                                                   &key mode
+                                                   &key extension
+                                                   &key no-fixture
+                                                   &key async
+                                                   &key post-colorization
+                                                   &key 
enable-context-coloring-mode
+                                                   &key get-args
+                                                   &key before-each
+                                                   &key after-each)
+  "Define a deftest defmacro for tests prefixed with NAME. MODE
+is called to set up tests' environments.  EXTENSION denotes the
+suffix for tests' fixture files.  If NO-FIXTURE is non-nil, don't
+use a fixture.  If ASYNC is non-nil, pass a callback to the
+defined tests' bodies for them to call when they are done.  If
+POST-COLORIZATION is non-nil, the tests run after
+`context-coloring-colorize' finishes asynchronously.  If
+ENABLE-CONTEXT-COLORING-MODE is non-nil, `context-coloring-mode'
+is activated before tests.  GET-ARGS provides arguments to apply
+to BEFORE-EACH, AFTER-EACH, and each tests' body, before and
+after functions.  Functions BEFORE-EACH and AFTER-EACH run before
+the major mode is activated before each test, and after each
+test, even if an error is signaled."
   (declare (indent defun))
-  (let ((test-name (intern (format "context-coloring-test-js-mode-%s" name)))
-        (fixture (format "./fixtures/%s.js" (or fixture-name name)))
-        (function-name (intern-soft
-                        (format "context-coloring-test-js-%s" name)))
-        (setup-function-name (intern-soft
-                              (format
-                               "context-coloring-test-js-%s-setup" name))))
-    `(ert-deftest-async ,test-name (done)
-                        (context-coloring-test-js-mode
-                         ,fixture
-                         (lambda (teardown)
-                           (unwind-protect
-                               (,function-name)
-                             (funcall teardown))
-                           (funcall done))
-                         ',setup-function-name))))
-
-(cl-defmacro context-coloring-test-deftest-js2-mode (name &key fixture-name)
-  "Define a test for `js2-mode' with the name NAME in the typical
-format."
+  (let ((macro-name (intern (format "context-coloring-test-deftest%s"
+                                    (cond
+                                     ;; No name means no dash.
+                                     ((eq name nil) "")
+                                     (t (format "-%s" name)))))))
+    `(cl-defmacro ,macro-name (name
+                               body
+                               &key fixture
+                               &key before
+                               &key after)
+       ,(format "Define a test for `%s' suffixed with NAME.
+
+Function BODY makes assertions.
+%s
+
+Functions BEFORE and AFTER run before and after the test, even if
+an error is signaled.
+
+BODY is run after `context-coloring-mode' is activated, or after
+initial colorization if colorization should occur."
+                (cadr mode)
+                (cond
+                 (no-fixture "
+There is no fixture, unless FIXTURE is specified.")
+                 (t
+                  (format "
+The default fixture has a filename matching NAME (plus the
+filetype extension, \"%s\"), unless FIXTURE is specified to
+override it."
+                          extension))))
+       (declare (indent defun))
+       ;; Commas in nested backquotes are not evaluated.  Binding the variables
+       ;; here is probably the cleanest workaround.
+       (let ((mode ,mode)
+             (get-args ',(cond
+                          (get-args get-args)
+                          (t '(lambda () (list)))))
+             (args (make-symbol "args"))
+             (before-each ',before-each)
+             (after-each ',after-each)
+             (test-name (intern (format ,(format "%s-%%s"
+                                                 (cond
+                                                  (name)
+                                                  (t "sync"))) name)))
+             (fixture (cond
+                       (fixture (format "./fixtures/%s" fixture))
+                       (,no-fixture "./fixtures/empty")
+                       (t (format ,(format "./fixtures/%%s.%s" extension) 
name)))))
+         ,@(cond
+            ((or async post-colorization)
+             `((let ((post-colorization ,post-colorization))
+                 `(ert-deftest-async ,test-name (done)
+                    (let ((,args (funcall ,get-args)))
+                      (context-coloring-test-with-fixture-async
+                       ,fixture
+                       (lambda (done-with-fixture)
+                         (when ,before-each (apply ,before-each ,args))
+                         (,mode)
+                         (when ,before (apply ,before ,args))
+                         (cond
+                          (,post-colorization
+                           (context-coloring-colorize
+                            (lambda ()
+                              (unwind-protect
+                                  (progn
+                                    (apply ,body ,args))
+                                (when ,after (apply ,after ,args))
+                                (when ,after-each (apply ,after-each ,args))
+                                (funcall done-with-fixture))
+                              (funcall done))))
+                          (t
+                           ;; Leave error handling up to the user.
+                           (apply ,body (append
+                                         (list (lambda ()
+                                                 (when ,after (apply ,after 
,args))
+                                                 (when ,after-each (apply 
,after-each ,args))
+                                                 (funcall done-with-fixture)
+                                                 (funcall done)))
+                                         ,args)))))))))))
+            (t
+             `((let ((enable-context-coloring-mode 
,enable-context-coloring-mode))
+                 `(ert-deftest ,test-name ()
+                    (let ((,args (funcall ,get-args)))
+                      (context-coloring-test-with-fixture
+                       ,fixture
+                       (when ,before-each (apply ,before-each ,args))
+                       (,mode)
+                       (when ,before (apply ,before ,args))
+                       (when ,enable-context-coloring-mode 
(context-coloring-mode))
+                       (unwind-protect
+                           (progn
+                             (apply ,body ,args))
+                         (when ,after (apply ,after ,args))
+                         (when ,after-each (apply ,after-each 
,args))))))))))))))
+
+(context-coloring-test-define-deftest nil
+  :mode #'fundamental-mode
+  :no-fixture t)
+
+(context-coloring-test-define-deftest async
+  :mode #'fundamental-mode
+  :no-fixture t
+  :async t)
+
+(context-coloring-test-define-deftest js
+  :mode #'js-mode
+  :extension "js"
+  :post-colorization t)
+
+(context-coloring-test-define-deftest js2
+  :mode #'js2-mode
+  :extension "js"
+  :enable-context-coloring-mode t
+  :before-each (lambda ()
+                 (setq js2-mode-show-parse-errors nil)
+                 (setq js2-mode-show-strict-warnings nil)))
+
+(defmacro context-coloring-test-deftest-js-js2 (&rest args)
+  "Simultaneously define the same test for js and js2 (with
+ARGS)."
   (declare (indent defun))
-  (let ((test-name (intern (format "context-coloring-test-js2-mode-%s" name)))
-        (fixture (format "./fixtures/%s.js" (or fixture-name name)))
-        (function-name (intern-soft
-                        (format "context-coloring-test-js-%s" name)))
-        (setup-function-name (intern-soft
-                              (format
-                               "context-coloring-test-js-%s-setup" name))))
-    `(ert-deftest ,test-name ()
-       (context-coloring-test-js2-mode
-        ,fixture
-        ',setup-function-name
-        (,function-name)))))
-
-(cl-defmacro context-coloring-test-deftest-emacs-lisp-mode (name
-                                                            body
-                                                            &key setup)
-  "Define a test for `emacs-lisp-mode' with name and fixture as
-NAME, with BODY containing the assertions, and SETUP defining the
-environment."
-  (declare (indent defun))
-  (let ((test-name (intern (format "context-coloring-emacs-lisp-mode-%s" 
name)))
-        (fixture (format "./fixtures/%s.el" name)))
-    `(ert-deftest ,test-name ()
-       (context-coloring-test-with-fixture
-        ,fixture
-        (emacs-lisp-mode)
-        (when ,setup (funcall ,setup))
-        (context-coloring-mode)
-        (funcall ,body)))))
+  `(progn
+     (context-coloring-test-deftest-js ,@args)
+     (context-coloring-test-deftest-js2 ,@args)))
+
+(context-coloring-test-define-deftest emacs-lisp
+  :mode #'emacs-lisp-mode
+  :extension "el"
+  :enable-context-coloring-mode t)
+
+(context-coloring-test-define-deftest define-theme
+  :mode #'fundamental-mode
+  :no-fixture t
+  :get-args (lambda ()
+              (list (context-coloring-test-get-next-theme)))
+  :after-each (lambda (theme)
+                (setq context-coloring-maximum-face 7)
+                (setq context-coloring-original-maximum-face
+                      context-coloring-maximum-face)
+                (disable-theme theme)
+                (context-coloring-test-kill-buffer "*Warnings*")))
 
 
 ;;; Assertion functions
 
-(defun context-coloring-test-assert-position-level (position level)
-  "Assert that POSITION has LEVEL."
-  (let ((face (get-text-property position 'face))
-        actual-level)
-    (when (not (and face
-                    (let* ((face-string (symbol-name face))
-                           (matches (string-match
-                                     context-coloring-level-face-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 at position %s, "
-                                "which is \"%s\", to be %s; "
-                                "but it was %s")
-                        position
-                        (buffer-substring-no-properties position (1+ 
position)) level
-                        actual-level)))))
-
-(defun context-coloring-test-assert-position-face (position face-regexp)
-  "Assert that the face at POSITION satisfies FACE-REGEXP."
-  (let ((face (get-text-property position 'face)))
-    (when (or
-           ;; Pass a non-string to do an `equal' check (against a symbol or 
nil).
-           (unless (stringp face-regexp)
-             (not (equal face-regexp face)))
-           ;; Otherwise do the matching.
-           (when (stringp face-regexp)
-             (not (string-match-p face-regexp (symbol-name face)))))
-      (ert-fail (format (concat "Expected face at position %s, "
-                                "which is \"%s\", to be %s; "
-                                "but it was %s")
-                        position
-                        (buffer-substring-no-properties position (1+ 
position)) face-regexp
-                        face)))))
-
-(defun context-coloring-test-assert-position-comment (position)
-  (context-coloring-test-assert-position-face
-   position "\\`font-lock-comment\\(-delimiter\\)?-face\\'"))
-
-(defun context-coloring-test-assert-position-constant-comment (position)
-  (context-coloring-test-assert-position-face position 
'(font-lock-constant-face
-                                                         
font-lock-comment-face)))
-
-(defun context-coloring-test-assert-position-string (position)
-  (context-coloring-test-assert-position-face position 'font-lock-string-face))
-
-(defun context-coloring-test-assert-position-nil (position)
-  (context-coloring-test-assert-position-face position nil))
-
-(defun context-coloring-test-assert-coloring (map)
-  "Assert that the current buffer's coloring matches MAP."
-  ;; Omit the superfluous, formatting-related leading newline.  Can't use
-  ;; `save-excursion' here because if an assertion fails it will cause future
-  ;; tests to get messed up.
-  (goto-char (point-min))
-  (let* ((map (substring map 1))
-         (index 0)
-         char-string
-         char)
-    (while (< index (length map))
-      (setq char-string (substring map index (1+ index)))
-      (setq char (string-to-char char-string))
-      (cond
-       ;; Newline
-       ((= char 10)
-        (next-logical-line)
-        (beginning-of-line))
-       ;; Number
-       ((and (>= char 48)
-             (<= char 57))
-        (context-coloring-test-assert-position-level
-         (point) (string-to-number char-string))
-        (forward-char))
-       ;; ';' = Comment
-       ((= char 59)
-        (context-coloring-test-assert-position-comment (point))
-        (forward-char))
-       ;; 'c' = Constant comment
-       ((= char 99)
-        (context-coloring-test-assert-position-constant-comment (point))
-        (forward-char))
-       ;; 'n' = nil
-       ((= char 110)
-        (context-coloring-test-assert-position-nil (point))
-        (forward-char))
-       ;; 's' = String
-       ((= char 115)
-        (context-coloring-test-assert-position-string (point))
-        (forward-char))
-       (t
-        (forward-char)))
-      (setq index (1+ index)))))
-
-(defmacro context-coloring-test-assert-region (&rest body)
-  "Assert something about the face of points in a region.
-Provides the free variables `i', `length', `point', `face' and
-`actual-level' to the code in BODY."
-  `(let ((i 0)
-         (length (- end start)))
-     (while (< i length)
-       (let* ((point (+ i start))
-              (face (get-text-property point 'face)))
-         ,@body)
-       (setq i (+ i 1)))))
-
-(defun context-coloring-test-assert-region-level (start end level)
-  "Assert that all points in the range [START, END) are of level
-LEVEL."
-  (context-coloring-test-assert-region
-   (let (actual-level)
-     (when (not (when face
-                  (let* ((face-string (symbol-name face))
-                         (matches (string-match
-                                   context-coloring-level-face-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-get-last-message ()
+  "Get the last message in the current messages bufffer."
   (let ((messages (split-string
                    (buffer-substring-no-properties
                     (point-min)
@@ -398,38 +300,6 @@ EXPECTED-FACE."
                       (with-current-buffer buffer
                         (buffer-string))))))
 
-(defun context-coloring-test-kill-buffer (buffer)
-  "Kill BUFFER if it exists."
-  (when (get-buffer buffer) (kill-buffer buffer)))
-
-(defun context-coloring-test-assert-face (level foreground &optional negate)
-  "Assert that a face for LEVEL exists and that its `:foreground'
-is FOREGROUND, or the inverse if NEGATE is non-nil."
-  (let* ((face (context-coloring-level-face level))
-         actual-foreground)
-    (when (not (or negate
-                   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 (funcall (if negate 'identity 'not)
-                   (string-equal foreground actual-foreground))
-      (ert-fail (format (concat "Expected face for level `%s' "
-                                "%sto have foreground `%s'; "
-                                "but it %s.")
-                        level
-                        (if negate "not " "") foreground
-                        (if negate
-                            "did" (format "was `%s'" actual-foreground)))))))
-
-(defun context-coloring-test-assert-not-face (&rest arguments)
-  "Assert that LEVEL does not have a face with `:foreground'
-FOREGROUND.  Apply ARGUMENTS to
-`context-coloring-test-assert-face', see that function."
-  (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))
@@ -446,205 +316,169 @@ FOREGROUND.  Apply ARGUMENTS to
     (when (not error-signaled-p)
       (ert-fail "Expected an error to be thrown, but there wasn't."))))
 
+
+;;; Miscellaneous tests
+
 (defun context-coloring-test-assert-trimmed (result expected)
+  "Assert that RESULT is trimmed like 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.")
+(context-coloring-test-deftest trim
+  (lambda ()
+    (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")))
+
+(context-coloring-test-deftest-async mode-startup
+  (lambda (done)
+    (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 done)))
+    (context-coloring-mode))
+  :after (lambda ()
+           ;; TODO: This won't run if there is a timeout.  Will probably have 
to
+           ;; roll our own `ert-deftest-async'.
+           (setq context-coloring-colorize-hook nil)))
+
+(defmacro context-coloring-test-define-derived-mode (name)
+  "Define a derived mode exclusively for any test with NAME."
+  (let ((name (intern (format "context-coloring-test-%s-mode" name))))
+    `(define-derived-mode ,name fundamental-mode "Testing")))
+
+(context-coloring-test-define-derived-mode change-detection)
 
 ;; 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
+(context-coloring-test-deftest-async change-detection
+  (lambda (done)
+    (context-coloring-define-dispatch
      'idle-change
-     :modes '(context-coloring-change-detection-mode)
+     :modes '(context-coloring-test-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 (current-buffer))))
-     (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/empty"
-   (context-coloring-mode)
-   (context-coloring-test-assert-message
-    "Context coloring is not available for this major mode"
-    "*Messages*")))
-
-(ert-deftest context-coloring-test-derived-mode ()
-  (context-coloring-test-with-fixture
-   "./fixtures/empty"
-   (lisp-interaction-mode)
-   (context-coloring-mode)
-   (context-coloring-test-assert-not-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-test-change-detection-mode)
+    (add-hook
+     'context-coloring-colorize-hook
+     (lambda ()
+       (setq context-coloring-colorize-hook nil)
+       (add-hook
+        'context-coloring-colorize-hook
+        (lambda ()
+          (funcall done)))
+       (insert " ")
+       (set-window-buffer (selected-window) (current-buffer))
+       (context-coloring-maybe-colorize-with-buffer (current-buffer))))
+    (context-coloring-mode))
+  :after (lambda ()
+           (setq context-coloring-colorize-hook nil)))
+
+(context-coloring-test-deftest check-version
+  (lambda ()
+    (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."))))
+
+(context-coloring-test-deftest unsupported-mode
+  (lambda ()
     (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-assert-message
+     "Context coloring is not available for this major mode"
+     "*Messages*")))
+
+(context-coloring-test-deftest derived-mode
+  (lambda ()
+    (lisp-interaction-mode)
+    (context-coloring-mode)
+    (context-coloring-test-assert-not-message
+     "Context coloring is not available for this major mode"
+     "*Messages*")))
+
+(context-coloring-test-define-derived-mode define-dispatch-error)
+
+(context-coloring-test-deftest define-dispatch-error
+  (lambda ()
+    (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 or command defined for dispatch")))
+
+(context-coloring-test-define-derived-mode missing-executable)
+
+(context-coloring-test-deftest missing-executable
+  (lambda ()
+    (context-coloring-define-dispatch
+     'scopifier
+     :modes '(context-coloring-test-missing-executable-mode)
+     :command ""
+     :executable "__should_not_exist__")
     (context-coloring-test-missing-executable-mode)
     (context-coloring-mode)))
 
-(define-derived-mode
-  context-coloring-test-unsupported-version-mode
-  fundamental-mode
-  "Testing"
-  "Prevent `context-coloring-test-unsupported-version' from
-  having any unintentional side-effects on mode support.")
-
-(ert-deftest-async context-coloring-test-unsupported-version (done)
-  (context-coloring-define-dispatch
-   'outta-date
-   :modes '(context-coloring-test-unsupported-version-mode)
-   :executable "node"
-   :command "node test/binaries/outta-date"
-   :version "v2.1.3")
-  (context-coloring-test-with-fixture-async
-   "./fixtures/empty"
-   (lambda (teardown)
-     (context-coloring-test-unsupported-version-mode)
-     (add-hook
-      'context-coloring-check-scopifier-version-hook
-      (lambda ()
-        (unwind-protect
-            (progn
-              ;; Normally the executable would be something like "outta-date"
-              ;; rather than "node".
-              (context-coloring-test-assert-message
-               "Update to the minimum version of \"node\" (v2.1.3)"
-               "*Messages*"))
-          (funcall teardown))
-        (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-test-define-derived-mode unsupported-version)
+
+(context-coloring-test-deftest-async unsupported-version
+  (lambda (done)
     (context-coloring-define-dispatch
-     'disable-mode
-     :modes '(context-coloring-test-disable-mode-mode)
+     'outta-date
+     :modes '(context-coloring-test-unsupported-version-mode)
      :executable "node"
-     :command "node test/binaries/noop"
-     :teardown (lambda ()
-                 (setq torn-down t)))
-    (context-coloring-test-with-fixture-async
-     "./fixtures/empty"
-     (lambda (teardown)
+     :command "node test/binaries/outta-date"
+     :version "v2.1.3")
+    (context-coloring-test-unsupported-version-mode)
+    (add-hook
+     'context-coloring-check-scopifier-version-hook
+     (lambda ()
        (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)))))
+             ;; Normally the executable would be something like "outta-date"
+             ;; rather than "node".
+             (context-coloring-test-assert-message
+              "Update to the minimum version of \"node\" (v2.1.3)"
+              "*Messages*"))
+         (funcall done))))
+    (context-coloring-mode))
+  :after (lambda ()
+           (setq context-coloring-check-scopifier-version-hook nil)))
+
+(context-coloring-test-define-derived-mode disable-mode)
+
+(context-coloring-test-deftest-async disable-mode
+  (lambda (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)))
+      (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 done)))))
+
+
+;;; Theme tests
 
 (defvar context-coloring-test-theme-index 0
   "Unique index for unique theme names.")
@@ -657,14 +491,42 @@ FOREGROUND.  Apply ARGUMENTS to
     (setq context-coloring-test-theme-index
           (+ context-coloring-test-theme-index 1))))
 
+(defun context-coloring-test-assert-face (level foreground &optional negate)
+  "Assert that a face for LEVEL exists and that its `:foreground'
+is FOREGROUND, or the inverse if NEGATE is non-nil."
+  (let* ((face (context-coloring-level-face level))
+         actual-foreground)
+    (when (not (or negate
+                   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 (funcall (if negate #'identity #'not)
+                   (string-equal foreground actual-foreground))
+      (ert-fail (format (concat "Expected face for level `%s' "
+                                "%sto have foreground `%s'; "
+                                "but it %s.")
+                        level
+                        (if negate "not " "") foreground
+                        (if negate
+                            "did" (format "was `%s'" actual-foreground)))))))
+
+(defun context-coloring-test-assert-not-face (&rest arguments)
+  "Assert that LEVEL does not have a face with `:foreground'
+FOREGROUND.  Apply ARGUMENTS to
+`context-coloring-test-assert-face', see that function."
+  (apply #'context-coloring-test-assert-face
+         (append arguments '(t))))
+
 (defun context-coloring-test-assert-theme-originally-set-p
     (settings &optional negate)
-  "Assert that `context-coloring-theme-originally-set-p' returns
-t for a theme with SETTINGS, or the inverse if NEGATE is
+  "Assert that `context-coloring-theme-originally-set-p' will
+return t for a theme with SETTINGS, or the inverse if NEGATE is
 non-nil."
   (let ((theme (context-coloring-test-get-next-theme)))
     (put theme 'theme-settings settings)
-    (when (funcall (if negate 'identity 'not)
+    (when (funcall (if negate #'identity #'not)
                    (context-coloring-theme-originally-set-p theme))
       (ert-fail (format (concat "Expected theme `%s' with settings `%s' "
                                 "%sto be considered to have defined a level, "
@@ -678,21 +540,21 @@ non-nil."
 return t for a theme with SETTINGS.  Apply ARGUMENTS to
 `context-coloring-test-assert-theme-originally-set-p', see that
 function."
-  (apply 'context-coloring-test-assert-theme-originally-set-p
+  (apply #'context-coloring-test-assert-theme-originally-set-p
          (append arguments '(t))))
 
-(ert-deftest context-coloring-test-theme-originally-set-p ()
-  (context-coloring-test-assert-theme-originally-set-p
-   '((theme-face context-coloring-level-0-face)))
-  (context-coloring-test-assert-theme-originally-set-p
-   '((theme-face face)
-     (theme-face context-coloring-level-0-face)))
-  (context-coloring-test-assert-theme-originally-set-p
-   '((theme-face context-coloring-level-0-face)
-     (theme-face face)))
-  (context-coloring-test-assert-not-theme-originally-set-p
-   '((theme-face face)))
-  )
+(context-coloring-test-deftest theme-originally-set-p
+  (lambda ()
+    (context-coloring-test-assert-theme-originally-set-p
+     '((theme-face context-coloring-level-0-face)))
+    (context-coloring-test-assert-theme-originally-set-p
+     '((theme-face face)
+       (theme-face context-coloring-level-0-face)))
+    (context-coloring-test-assert-theme-originally-set-p
+     '((theme-face context-coloring-level-0-face)
+       (theme-face face)))
+    (context-coloring-test-assert-not-theme-originally-set-p
+     '((theme-face face)))))
 
 (defun context-coloring-test-assert-theme-settings-highest-level
     (settings expected-level)
@@ -707,7 +569,7 @@ EXPECTED-LEVEL."
   "Assert that THEME has the highest level EXPECTED-LEVEL, or the
 inverse if NEGATE is non-nil."
   (let ((highest-level (context-coloring-theme-highest-level theme)))
-    (when (funcall (if negate 'identity 'not) (eq highest-level 
expected-level))
+    (when (funcall (if negate #'identity #'not) (eq highest-level 
expected-level))
       (ert-fail (format (concat "Expected theme with settings `%s' "
                                 "%sto have a highest level of `%s', "
                                 "but it %s.")
@@ -720,63 +582,49 @@ inverse if NEGATE is non-nil."
 Apply ARGUMENTS to
 `context-coloring-test-assert-theme-highest-level', see that
 function."
-  (apply 'context-coloring-test-assert-theme-highest-level
+  (apply #'context-coloring-test-assert-theme-highest-level
          (append arguments '(t))))
 
-(ert-deftest context-coloring-test-theme-highest-level ()
-  (context-coloring-test-assert-theme-settings-highest-level
-   '((theme-face foo))
-   -1)
-  (context-coloring-test-assert-theme-settings-highest-level
-   '((theme-face context-coloring-level-0-face))
-   0)
-  (context-coloring-test-assert-theme-settings-highest-level
-   '((theme-face context-coloring-level-1-face))
-   1)
-  (context-coloring-test-assert-theme-settings-highest-level
-   '((theme-face context-coloring-level-1-face)
-     (theme-face context-coloring-level-0-face))
-   1)
-  (context-coloring-test-assert-theme-settings-highest-level
-   '((theme-face context-coloring-level-0-face)
-     (theme-face context-coloring-level-1-face))
-   1)
-  )
-
-(defmacro context-coloring-test-deftest-define-theme (name &rest body)
-  "Define a test with name NAME and an automatically-generated
-theme symbol available as a free variable `theme'.  Side-effects
-from enabling themes are reversed after BODY is executed and the
-test completes."
-  (declare (indent defun))
-  (let ((deftest-name (intern
-                       (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)
-           (context-coloring-test-cleanup))))))
+(context-coloring-test-deftest theme-highest-level
+  (lambda ()
+    (context-coloring-test-assert-theme-settings-highest-level
+     '((theme-face foo))
+     -1)
+    (context-coloring-test-assert-theme-settings-highest-level
+     '((theme-face context-coloring-level-0-face))
+     0)
+    (context-coloring-test-assert-theme-settings-highest-level
+     '((theme-face context-coloring-level-1-face))
+     1)
+    (context-coloring-test-assert-theme-settings-highest-level
+     '((theme-face context-coloring-level-1-face)
+       (theme-face context-coloring-level-0-face))
+     1)
+    (context-coloring-test-assert-theme-settings-highest-level
+     '((theme-face context-coloring-level-0-face)
+       (theme-face context-coloring-level-1-face))
+     1)))
+
+(defun context-coloring-test-kill-buffer (buffer)
+  "Kill BUFFER if it exists."
+  (when (get-buffer buffer) (kill-buffer buffer)))
 
 (defun context-coloring-test-deftheme (theme)
   "Dynamically define theme THEME."
   (eval (macroexpand `(deftheme ,theme))))
 
 (context-coloring-test-deftest-define-theme additive
-  (context-coloring-test-deftheme theme)
-  (context-coloring-define-theme
-   theme
-   :colors '("#aaaaaa"
-             "#bbbbbb"))
-  (context-coloring-test-assert-no-message "*Warnings*")
-  (enable-theme theme)
-  (context-coloring-test-assert-no-message "*Warnings*")
-  (context-coloring-test-assert-face 0 "#aaaaaa")
-  (context-coloring-test-assert-face 1 "#bbbbbb"))
+  (lambda (theme)
+    (context-coloring-test-deftheme theme)
+    (context-coloring-define-theme
+     theme
+     :colors '("#aaaaaa"
+               "#bbbbbb"))
+    (context-coloring-test-assert-no-message "*Warnings*")
+    (enable-theme theme)
+    (context-coloring-test-assert-no-message "*Warnings*")
+    (context-coloring-test-assert-face 0 "#aaaaaa")
+    (context-coloring-test-assert-face 1 "#bbbbbb")))
 
 (defun context-coloring-test-assert-defined-warning (theme)
   "Assert that a warning about colors already being defined for
@@ -788,139 +636,147 @@ theme THEME is signaled."
    "*Warnings*"))
 
 (context-coloring-test-deftest-define-theme unintentional-override
-  (context-coloring-test-deftheme theme)
-  (custom-theme-set-faces
-   theme
-   '(context-coloring-level-0-face ((t (:foreground "#aaaaaa"))))
-   '(context-coloring-level-1-face ((t (:foreground "#bbbbbb")))))
-  (context-coloring-define-theme
-   theme
-   :colors '("#cccccc"
-             "#dddddd"))
-  (context-coloring-test-assert-defined-warning theme)
-  (context-coloring-test-kill-buffer "*Warnings*")
-  (enable-theme theme)
-  (context-coloring-test-assert-defined-warning theme)
-  (context-coloring-test-assert-face 0 "#cccccc")
-  (context-coloring-test-assert-face 1 "#dddddd"))
+  (lambda (theme)
+    (context-coloring-test-deftheme theme)
+    (custom-theme-set-faces
+     theme
+     '(context-coloring-level-0-face ((t (:foreground "#aaaaaa"))))
+     '(context-coloring-level-1-face ((t (:foreground "#bbbbbb")))))
+    (context-coloring-define-theme
+     theme
+     :colors '("#cccccc"
+               "#dddddd"))
+    (context-coloring-test-assert-defined-warning theme)
+    (context-coloring-test-kill-buffer "*Warnings*")
+    (enable-theme theme)
+    (context-coloring-test-assert-defined-warning theme)
+    (context-coloring-test-assert-face 0 "#cccccc")
+    (context-coloring-test-assert-face 1 "#dddddd")))
 
 (context-coloring-test-deftest-define-theme intentional-override
-  (context-coloring-test-deftheme theme)
-  (custom-theme-set-faces
-   theme
-   '(context-coloring-level-0-face ((t (:foreground "#aaaaaa"))))
-   '(context-coloring-level-1-face ((t (:foreground "#bbbbbb")))))
-  (context-coloring-define-theme
-   theme
-   :override t
-   :colors '("#cccccc"
-             "#dddddd"))
-  (context-coloring-test-assert-no-message "*Warnings*")
-  (enable-theme theme)
-  (context-coloring-test-assert-no-message "*Warnings*")
-  (context-coloring-test-assert-face 0 "#cccccc")
-  (context-coloring-test-assert-face 1 "#dddddd"))
+  (lambda (theme)
+    (context-coloring-test-deftheme theme)
+    (custom-theme-set-faces
+     theme
+     '(context-coloring-level-0-face ((t (:foreground "#aaaaaa"))))
+     '(context-coloring-level-1-face ((t (:foreground "#bbbbbb")))))
+    (context-coloring-define-theme
+     theme
+     :override t
+     :colors '("#cccccc"
+               "#dddddd"))
+    (context-coloring-test-assert-no-message "*Warnings*")
+    (enable-theme theme)
+    (context-coloring-test-assert-no-message "*Warnings*")
+    (context-coloring-test-assert-face 0 "#cccccc")
+    (context-coloring-test-assert-face 1 "#dddddd")))
 
 (context-coloring-test-deftest-define-theme pre-recede
-  (context-coloring-define-theme
-   theme
-   :recede t
-   :colors '("#aaaaaa"
-             "#bbbbbb"))
-  (context-coloring-test-deftheme theme)
-  (custom-theme-set-faces
-   theme
-   '(context-coloring-level-0-face ((t (:foreground "#cccccc"))))
-   '(context-coloring-level-1-face ((t (:foreground "#dddddd")))))
-  (enable-theme theme)
-  (context-coloring-test-assert-no-message "*Warnings*")
-  (context-coloring-test-assert-face 0 "#cccccc")
-  (context-coloring-test-assert-face 1 "#dddddd"))
+  (lambda (theme)
+    (context-coloring-define-theme
+     theme
+     :recede t
+     :colors '("#aaaaaa"
+               "#bbbbbb"))
+    (context-coloring-test-deftheme theme)
+    (custom-theme-set-faces
+     theme
+     '(context-coloring-level-0-face ((t (:foreground "#cccccc"))))
+     '(context-coloring-level-1-face ((t (:foreground "#dddddd")))))
+    (enable-theme theme)
+    (context-coloring-test-assert-no-message "*Warnings*")
+    (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"))
+  (lambda (theme)
+    (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
-   theme
-   '(context-coloring-level-0-face ((t (:foreground "#aaaaaa"))))
-   '(context-coloring-level-1-face ((t (:foreground "#bbbbbb")))))
-  (context-coloring-define-theme
-   theme
-   :recede t
-   :colors '("#cccccc"
-             "#dddddd"))
-  (context-coloring-test-assert-no-message "*Warnings*")
-  (context-coloring-test-assert-face 0 "#aaaaaa")
-  (context-coloring-test-assert-face 1 "#bbbbbb")
-  (enable-theme theme)
-  (context-coloring-test-assert-no-message "*Warnings*")
-  (context-coloring-test-assert-face 0 "#aaaaaa")
-  (context-coloring-test-assert-face 1 "#bbbbbb"))
+  (lambda (theme)
+    (context-coloring-test-deftheme theme)
+    (custom-theme-set-faces
+     theme
+     '(context-coloring-level-0-face ((t (:foreground "#aaaaaa"))))
+     '(context-coloring-level-1-face ((t (:foreground "#bbbbbb")))))
+    (context-coloring-define-theme
+     theme
+     :recede t
+     :colors '("#cccccc"
+               "#dddddd"))
+    (context-coloring-test-assert-no-message "*Warnings*")
+    (context-coloring-test-assert-face 0 "#aaaaaa")
+    (context-coloring-test-assert-face 1 "#bbbbbb")
+    (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 recede-not-defined
-  (context-coloring-test-deftheme theme)
-  (custom-theme-set-faces
-   theme
-   '(foo-face ((t (:foreground "#ffffff")))))
-  (context-coloring-define-theme
-   theme
-   :recede t
-   :colors '("#aaaaaa"
-             "#bbbbbb"))
-  (context-coloring-test-assert-no-message "*Warnings*")
-  (context-coloring-test-assert-face 0 "#aaaaaa")
-  (context-coloring-test-assert-face 1 "#bbbbbb")
-  (enable-theme theme)
-  (context-coloring-test-assert-no-message "*Warnings*")
-  (context-coloring-test-assert-face 0 "#aaaaaa")
-  (context-coloring-test-assert-face 1 "#bbbbbb"))
+  (lambda (theme)
+    (context-coloring-test-deftheme theme)
+    (custom-theme-set-faces
+     theme
+     '(foo-face ((t (:foreground "#ffffff")))))
+    (context-coloring-define-theme
+     theme
+     :recede t
+     :colors '("#aaaaaa"
+               "#bbbbbb"))
+    (context-coloring-test-assert-no-message "*Warnings*")
+    (context-coloring-test-assert-face 0 "#aaaaaa")
+    (context-coloring-test-assert-face 1 "#bbbbbb")
+    (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 unintentional-obstinance
-  (context-coloring-define-theme
-   theme
-   :colors '("#aaaaaa"
-             "#bbbbbb"))
-  (context-coloring-test-deftheme theme)
-  (custom-theme-set-faces
-   theme
-   '(context-coloring-level-0-face ((t (:foreground "#cccccc"))))
-   '(context-coloring-level-1-face ((t (:foreground "#dddddd")))))
-  (enable-theme theme)
-  (context-coloring-test-assert-defined-warning theme)
-  (context-coloring-test-assert-face 0 "#aaaaaa")
-  (context-coloring-test-assert-face 1 "#bbbbbb"))
+  (lambda (theme)
+    (context-coloring-define-theme
+     theme
+     :colors '("#aaaaaa"
+               "#bbbbbb"))
+    (context-coloring-test-deftheme theme)
+    (custom-theme-set-faces
+     theme
+     '(context-coloring-level-0-face ((t (:foreground "#cccccc"))))
+     '(context-coloring-level-1-face ((t (:foreground "#dddddd")))))
+    (enable-theme theme)
+    (context-coloring-test-assert-defined-warning theme)
+    (context-coloring-test-assert-face 0 "#aaaaaa")
+    (context-coloring-test-assert-face 1 "#bbbbbb")))
 
 (context-coloring-test-deftest-define-theme intentional-obstinance
-  (context-coloring-define-theme
-   theme
-   :override t
-   :colors '("#aaaaaa"
-             "#bbbbbb"))
-  (context-coloring-test-deftheme theme)
-  (custom-theme-set-faces
-   theme
-   '(context-coloring-level-0-face ((t (:foreground "#cccccc"))))
-   '(context-coloring-level-1-face ((t (:foreground "#dddddd")))))
-  (enable-theme theme)
-  (context-coloring-test-assert-no-message "*Warnings*")
-  (context-coloring-test-assert-face 0 "#aaaaaa")
-  (context-coloring-test-assert-face 1 "#bbbbbb"))
+  (lambda (theme)
+    (context-coloring-define-theme
+     theme
+     :override t
+     :colors '("#aaaaaa"
+               "#bbbbbb"))
+    (context-coloring-test-deftheme theme)
+    (custom-theme-set-faces
+     theme
+     '(context-coloring-level-0-face ((t (:foreground "#cccccc"))))
+     '(context-coloring-level-1-face ((t (:foreground "#dddddd")))))
+    (enable-theme theme)
+    (context-coloring-test-assert-no-message "*Warnings*")
+    (context-coloring-test-assert-face 0 "#aaaaaa")
+    (context-coloring-test-assert-face 1 "#bbbbbb")))
 
 (defun context-coloring-test-assert-maximum-face (maximum &optional negate)
   "Assert that `context-coloring-maximum-face' is MAXIMUM, or the
 inverse if NEGATE is non-nil."
-  (when (funcall (if negate 'identity 'not)
+  (when (funcall (if negate #'identity #'not)
                  (eq context-coloring-maximum-face maximum))
     (ert-fail (format (concat "Expected `context-coloring-maximum-face' "
                               "%sto be `%s', "
@@ -934,199 +790,282 @@ inverse if NEGATE is non-nil."
   "Assert that `context-coloring-maximum-face' is not MAXIMUM.
 Apply ARGUMENTS to `context-coloring-test-assert-maximum-face',
 see that function."
-  (apply 'context-coloring-test-assert-maximum-face
+  (apply #'context-coloring-test-assert-maximum-face
          (append arguments '(t))))
 
 (context-coloring-test-deftest-define-theme disable-cascade
-  (let ((maximum-face-value 9999))
-    (setq context-coloring-maximum-face maximum-face-value)
-    (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)
+  (lambda (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-maximum-face
-     maximum-face-value)))
-
-(defun context-coloring-test-js-function-scopes ()
-  "Test fixtures/functions-scopes.js."
-  (context-coloring-test-assert-region-level 1 9 0)
-  (context-coloring-test-assert-region-level 9 23 1)
-  (context-coloring-test-assert-region-level 23 25 0)
-  (context-coloring-test-assert-region-level 25 34 1)
-  (context-coloring-test-assert-region-level 34 35 0)
-  (context-coloring-test-assert-region-level 35 52 1)
-  (context-coloring-test-assert-region-level 52 66 2)
-  (context-coloring-test-assert-region-level 66 72 1)
-  (context-coloring-test-assert-region-level 72 81 2)
-  (context-coloring-test-assert-region-level 81 82 1)
-  (context-coloring-test-assert-region-level 82 87 2)
-  (context-coloring-test-assert-region-level 87 89 1))
-
-(context-coloring-test-deftest-js-mode function-scopes)
-(context-coloring-test-deftest-js2-mode function-scopes)
-
-(defun context-coloring-test-js-global ()
-  "Test fixtures/global.js."
-  (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))
-
-(context-coloring-test-deftest-js-mode global)
-(context-coloring-test-deftest-js2-mode global)
-
-(defun context-coloring-test-js-block-scopes ()
-  "Test fixtures/block-scopes.js."
-  (context-coloring-test-assert-region-level 20 64 1)
-   (setq context-coloring-js-block-scopes t)
-   (context-coloring-colorize)
-   (context-coloring-test-assert-region-level 20 27 1)
-   (context-coloring-test-assert-region-level 27 41 2)
-   (context-coloring-test-assert-region-level 41 42 1)
-   (context-coloring-test-assert-region-level 42 64 2))
-
-(context-coloring-test-deftest-js2-mode block-scopes)
-
-(defun context-coloring-test-js-catch ()
-  "Test fixtures/js-catch.js."
-  (context-coloring-test-assert-region-level 20 27 1)
-  (context-coloring-test-assert-region-level 27 51 2)
-  (context-coloring-test-assert-region-level 51 52 1)
-  (context-coloring-test-assert-region-level 52 73 2)
-  (context-coloring-test-assert-region-level 73 101 3)
-  (context-coloring-test-assert-region-level 101 102 1)
-  (context-coloring-test-assert-region-level 102 117 3)
-  (context-coloring-test-assert-region-level 117 123 2))
-
-(context-coloring-test-deftest-js-mode catch)
-(context-coloring-test-deftest-js2-mode catch)
-
-(defun context-coloring-test-js-key-names ()
-  "Test fixtures/key-names.js."
-  (context-coloring-test-assert-region-level 20 63 1))
-
-(context-coloring-test-deftest-js-mode key-names)
-(context-coloring-test-deftest-js2-mode key-names)
-
-(defun context-coloring-test-js-property-lookup ()
-  "Test fixtures/property-lookup.js."
-  (context-coloring-test-assert-region-level 20 26 0)
-  (context-coloring-test-assert-region-level 26 38 1)
-  (context-coloring-test-assert-region-level 38 44 0)
-  (context-coloring-test-assert-region-level 44 52 1)
-  (context-coloring-test-assert-region-level 57 63 0)
-  (context-coloring-test-assert-region-level 63 74 1))
-
-(context-coloring-test-deftest-js-mode property-lookup)
-(context-coloring-test-deftest-js2-mode property-lookup)
-
-(defun context-coloring-test-js-key-values ()
-  "Test fixtures/key-values.js."
-  (context-coloring-test-assert-region-level 78 79 1))
-
-(context-coloring-test-deftest-js-mode key-values)
-(context-coloring-test-deftest-js2-mode key-values)
-
-(defun context-coloring-test-js-syntactic-comments-and-strings ()
-  "Test comments and strings."
-  (context-coloring-test-assert-region-level 1 8 0)
-  (context-coloring-test-assert-region-comment-delimiter 9 12)
-  (context-coloring-test-assert-region-comment 12 16)
-  (context-coloring-test-assert-region-comment-delimiter 17 20)
-  (context-coloring-test-assert-region-comment 20 27)
-  (context-coloring-test-assert-region-string 28 40)
-  (context-coloring-test-assert-region-level 40 41 0))
-
-(defun context-coloring-test-js-syntactic-comments-and-strings-setup ()
-  (setq context-coloring-syntactic-comments t)
-  (setq context-coloring-syntactic-strings t))
-
-(context-coloring-test-deftest-js-mode syntactic-comments-and-strings
-  :fixture-name comments-and-strings)
-(context-coloring-test-deftest-js2-mode syntactic-comments-and-strings
-  :fixture-name comments-and-strings)
-
-(defalias 'context-coloring-test-js-comments-and-strings
-  'context-coloring-test-js-syntactic-comments-and-strings
-  "Test comments and strings.  Deprecated.")
-
-(defun context-coloring-test-js-comments-and-strings-setup ()
-  "Setup comments and strings.  Deprecated."
-  (setq context-coloring-comments-and-strings t))
-
-(context-coloring-test-deftest-js-mode comments-and-strings)
-(context-coloring-test-deftest-js2-mode comments-and-strings)
-
-(defun context-coloring-test-js-syntactic-comments ()
-  "Test syntactic comments."
-  (context-coloring-test-assert-region-level 1 8 0)
-  (context-coloring-test-assert-region-comment-delimiter 9 12)
-  (context-coloring-test-assert-region-comment 12 16)
-  (context-coloring-test-assert-region-comment-delimiter 17 20)
-  (context-coloring-test-assert-region-comment 20 27)
-  (context-coloring-test-assert-region-level 28 41 0))
-
-(defun context-coloring-test-js-syntactic-comments-setup ()
-  "Setup syntactic comments."
-  (setq context-coloring-syntactic-comments t))
-
-(context-coloring-test-deftest-js-mode syntactic-comments
-  :fixture-name comments-and-strings)
-(context-coloring-test-deftest-js2-mode syntactic-comments
-  :fixture-name comments-and-strings)
-
-(defun context-coloring-test-js-syntactic-strings ()
-  "Test syntactic strings."
-  (context-coloring-test-assert-region-level 1 28 0)
-  (context-coloring-test-assert-region-string 28 40)
-  (context-coloring-test-assert-region-level 40 41 0))
-
-(defun context-coloring-test-js-syntactic-strings-setup ()
-  "Setup syntactic strings."
-  (setq context-coloring-syntactic-strings t))
-
-(context-coloring-test-deftest-js-mode syntactic-strings
-  :fixture-name comments-and-strings)
-(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)
-
-(context-coloring-test-deftest-emacs-lisp-mode defun
+         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))))
+
+
+;;; Coloring tests
+
+(defun context-coloring-test-assert-position-level (position level)
+  "Assert that POSITION has LEVEL."
+  (let ((face (get-text-property position 'face))
+        actual-level)
+    (when (not (and face
+                    (let* ((face-string (symbol-name face))
+                           (matches (string-match
+                                     context-coloring-level-face-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 at position %s, "
+                                "which is \"%s\", to be %s; "
+                                "but it was %s")
+                        position
+                        (buffer-substring-no-properties position (1+ 
position)) level
+                        actual-level)))))
+
+(defun context-coloring-test-assert-position-face (position face-regexp)
+  "Assert that the face at POSITION satisfies FACE-REGEXP."
+  (let ((face (get-text-property position 'face)))
+    (when (or
+           ;; Pass a non-string to do an `equal' check (against a symbol or 
nil).
+           (unless (stringp face-regexp)
+             (not (equal face-regexp face)))
+           ;; Otherwise do the matching.
+           (when (stringp face-regexp)
+             (not (string-match-p face-regexp (symbol-name face)))))
+      (ert-fail (format (concat "Expected face at position %s, "
+                                "which is \"%s\", to be %s; "
+                                "but it was %s")
+                        position
+                        (buffer-substring-no-properties position (1+ 
position)) face-regexp
+                        face)))))
+
+(defun context-coloring-test-assert-position-comment (position)
+  "Assert that the face at POSITION is a comment."
+  (context-coloring-test-assert-position-face
+   position "\\`font-lock-comment\\(-delimiter\\)?-face\\'"))
+
+(defun context-coloring-test-assert-position-constant-comment (position)
+  "Assert that the face at POSITION is a constant comment."
+  (context-coloring-test-assert-position-face position 
'(font-lock-constant-face
+                                                         
font-lock-comment-face)))
+
+(defun context-coloring-test-assert-position-string (position)
+  "Assert that the face at POSITION is a string."
+  (context-coloring-test-assert-position-face position 'font-lock-string-face))
+
+(defun context-coloring-test-assert-position-nil (position)
+  "Assert that the face at POSITION is nil."
+  (context-coloring-test-assert-position-face position nil))
+
+(defun context-coloring-test-assert-coloring (map)
+  "Assert that the current buffer's coloring will match MAP.
+
+MAP's newlines should correspond to the current fixture.
+
+The following characters appearing in MAP assert coloring for
+corresponding points in the fixture:
+
+0-9: Level equals number.
+C: Face is constant comment.
+c: Face is comment.
+n: Face is nil.
+s: Face is string.
+
+Any other characters are discarded.  Characters \"x\" and any
+other non-letters are guaranteed to always be discarded."
+  ;; Omit the superfluous, formatting-related leading newline.  Can't use
+  ;; `save-excursion' here because if an assertion fails it will cause future
+  ;; tests to get messed up.
+  (goto-char (point-min))
+  (let* ((map (substring map 1))
+         (index 0)
+         char-string
+         char)
+    (while (< index (length map))
+      (setq char-string (substring map index (1+ index)))
+      (setq char (string-to-char char-string))
+      (cond
+       ;; Newline
+       ((= char 10)
+        (forward-line)
+        (beginning-of-line))
+       ;; Number
+       ((and (>= char 48)
+             (<= char 57))
+        (context-coloring-test-assert-position-level
+         (point) (string-to-number char-string))
+        (forward-char))
+       ;; 'C' = Constant comment
+       ((= char 67)
+        (context-coloring-test-assert-position-constant-comment (point))
+        (forward-char))
+       ;; 'c' = Comment
+       ((= char 99)
+        (context-coloring-test-assert-position-comment (point))
+        (forward-char))
+       ;; 'n' = nil
+       ((= char 110)
+        (context-coloring-test-assert-position-nil (point))
+        (forward-char))
+       ;; 's' = String
+       ((= char 115)
+        (context-coloring-test-assert-position-string (point))
+        (forward-char))
+       (t
+        (forward-char)))
+      (setq index (1+ index)))))
+
+(context-coloring-test-deftest-js-js2 function-scopes
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+000 0 0 11111111 11 110
+11111111 011 1
+    111 1 1 22222222 22 221
+    22222222 122 22
+1")))
+
+(context-coloring-test-deftest-js-js2 global
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+(xxxxxxxx () {
+    111 1 1 00000001xxx11
+}());")))
+
+(context-coloring-test-deftest-js2 block-scopes
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+(xxxxxxxx () {
+    11 111 2
+        222 12
+        222 22
+    2
+}());"))
+  :before (lambda ()
+            (setq context-coloring-js-block-scopes t))
+  :after (lambda ()
+           (setq context-coloring-js-block-scopes nil)))
+
+(context-coloring-test-deftest-js-js2 catch
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+(xxxxxxxx () {
+    111 11 22222 222 2
+        222 1 2 22
+        222 22 33333 333 3
+            333 1 3 33
+        3
+    2
+}());")))
+
+(context-coloring-test-deftest-js-js2 key-names
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+(xxxxxxxx () {
+    111111 1
+        11 11
+        1 1 1
+    11
+}());")))
+
+(context-coloring-test-deftest-js-js2 property-lookup
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+(xxxxxxxx () {
+    0000001111111
+    0000001 111111
+    00000011111111111
+}());")))
+
+(context-coloring-test-deftest-js-js2 key-values
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+(xxxxxxxx () {
+    xxx x;
+    (xxxxxxxx () {
+        xxxxxx {
+            x: 1
+        };
+    }());
+}());")))
+
+(context-coloring-test-deftest-js-js2 syntactic-comments-and-strings
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+0000 00
+ccccccc
+cccccccccc
+ssssssssssss0"))
+  :fixture "comments-and-strings.js")
+
+(context-coloring-test-deftest-js-js2 syntactic-comments
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+0000 00
+ccccccc
+cccccccccc
+0000000000000"))
+  :fixture "comments-and-strings.js"
+  :before (lambda ()
+            (setq context-coloring-syntactic-strings nil))
+  :after (lambda ()
+           (setq context-coloring-syntactic-strings t)))
+
+(context-coloring-test-deftest-js-js2 syntactic-strings
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+0000 00
+0000000
+0000000000
+ssssssssssss0"))
+  :fixture "comments-and-strings.js"
+  :before (lambda ()
+            (setq context-coloring-syntactic-comments nil))
+  :after (lambda ()
+           (setq context-coloring-syntactic-comments t)))
+
+(context-coloring-test-deftest-js2 unterminated-comment
+  ;; As long as `add-text-properties' doesn't signal an error, this test 
passes.
+  (lambda ()))
+
+(context-coloring-test-deftest-emacs-lisp defun
   (lambda ()
     (context-coloring-test-assert-coloring "
 111111 000 1111 111 111111111 1111
@@ -1135,48 +1074,77 @@ see that function."
 0000 0 0 00
 
 111111 01
-111111 111")))
+111111 111
+111111 0 1sss11")))
 
-(context-coloring-test-deftest-emacs-lisp-mode lambda
+(context-coloring-test-deftest-emacs-lisp defadvice
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+1111111111 0 1111111 111111 11111 111 111111111
+  2222 222 122
+    22 1 2221")))
+
+(context-coloring-test-deftest-emacs-lisp lambda
   (lambda ()
     (context-coloring-test-assert-coloring "
 00000000 1111111 1111
            11111111 11 2222222 2222
                          222 22 12 2221 111 0 00")))
 
-(context-coloring-test-deftest-emacs-lisp-mode quote
+(context-coloring-test-deftest-emacs-lisp quote
   (lambda ()
     (context-coloring-test-assert-coloring "
+(xxxxx 0000000 00 00000)
+(xxx () (xxxxxxxxx (,0000)))
+
 (xxxxx x (x)
   (xx (xx x 111
       111111 1 111 111
-      111111 1 1111111111 11 111 1 111 1 00001 10000 11 00001 1 100001111")))
+      111111 1 1111111111 11 111 1 111 1 00001 10000 11 00001 1 10000
+                 sss ccc
+                 1111
+
+(xxxxxx '(sss cc
+          sss cc
+          ))
+
+(xxxxxx () 111111 11111)")))
 
-(context-coloring-test-deftest-emacs-lisp-mode comment
+(context-coloring-test-deftest-emacs-lisp splice
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+(xxxxxx ()
+  111111 00001 100001)")))
+
+(context-coloring-test-deftest-emacs-lisp comment
   (lambda ()
     ;; Just check that the comment isn't parsed syntactically.
     (context-coloring-test-assert-coloring "
 (xxxxx x ()
-  (xx (x xxxxx-xxxx xx)   ;;;;;;;;;;
-      11 00000-0000 11))) ;;;;;;;;;;"))
-  :setup (lambda ()
-           (setq context-coloring-syntactic-comments t)))
+  (xx (x xxxxx-xxxx xx)   cccccccccc
+      11 00000-0000 11))) cccccccccc")))
 
-(context-coloring-test-deftest-emacs-lisp-mode string
+(context-coloring-test-deftest-emacs-lisp string
   (lambda ()
     (context-coloring-test-assert-coloring "
 (xxxxx x (x)
-  (xxxxxx x x sss 1 0 sssss 0 1 sssssss11"))
-  :setup (lambda ()
-           (setq context-coloring-syntactic-strings t)))
+  (xxxxxx x x sss 1 0 sssss 0 1 sssssss11")))
 
-(context-coloring-test-deftest-emacs-lisp-mode ignored
+(context-coloring-test-deftest-emacs-lisp ignored
   (lambda ()
     (context-coloring-test-assert-coloring "
 (xxxxx x ()
-  (x x 1 11 11 111 11 1 111 (1 1 1)))")))
+  (x x 1 11 11 111 111 11 11 11 1 111 (1 1 1)))")))
+
+(context-coloring-test-deftest-emacs-lisp sexp
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+(xxx ()
+  `,@sss
+  `,@11
+  `,@11)")))
 
-(context-coloring-test-deftest-emacs-lisp-mode let
+(context-coloring-test-deftest-emacs-lisp let
   (lambda ()
     (context-coloring-test-assert-coloring "
 1111 11
@@ -1186,9 +1154,12 @@ see that function."
                22 02
                22 000022
            2222 2 2 2 00002211
-  1111 1 1 1 000011")))
+  1111 1 1 1 000011
+
+1111 cc ccccccc
+    1sss11")))
 
-(context-coloring-test-deftest-emacs-lisp-mode let*
+(context-coloring-test-deftest-emacs-lisp let*
   (lambda ()
     (context-coloring-test-assert-coloring "
 11111 11
@@ -1203,31 +1174,99 @@ see that function."
     2222 1 1 2 2 2 000022
   1111 1 1 1 0 0 000011")))
 
+(context-coloring-test-deftest-emacs-lisp cond
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+(xxx (x)
+  11111
+   11 11
+   10000 11
+   1111 1 00001 11
+   11 11111 1 000011
+   cc c
+   sss1)")))
+
+(context-coloring-test-deftest-emacs-lisp condition-case
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+1111111111-1111 111
+    111111 000 00001
+  111111 111 00001
+  1111111 111111 111 000011
+
+(111111111-1111-111111-11111 111
+    cc c
+    (xxx () 222)
+  (11111 (xxx () 222))
+  sss)")))
+
+(context-coloring-test-deftest-emacs-lisp dolist
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+1111111 111111
+  2222222 2222 1111 2222222
+    3333333 33 33 222 1111 2222223321")))
+
 (defun context-coloring-test-insert-unread-space ()
+  "Simulate the insertion of a space as if by a user."
   (setq unread-command-events (cons '(t . 32)
                                     unread-command-events)))
 
 (defun context-coloring-test-remove-faces ()
+  "Remove all faces in the current buffer."
   (remove-text-properties (point-min) (point-max) '(face nil)))
 
-(context-coloring-test-deftest-emacs-lisp-mode iteration
+(context-coloring-test-deftest-emacs-lisp iteration
   (lambda ()
-    (let ((context-coloring-emacs-lisp-iterations-per-pause 1))
+    (let ((context-coloring-elisp-sexps-per-pause 2))
       (context-coloring-colorize)
       (context-coloring-test-assert-coloring "
-;; `cc' `cc'
+cc `CC' `CC'
 (xxxxx x ())")
       (context-coloring-test-remove-faces)
       (context-coloring-test-insert-unread-space)
       (context-coloring-colorize)
-      ;; The first iteration will color the first part of the comment, but
-      ;; that's it.  Then it will be interrupted.
+      ;; Coloring is interrupted after the first "sexp" (the comment in this
+      ;; case).
       (context-coloring-test-assert-coloring "
-;; nnnn nnnn
-nnnnnn n nnn")))
-  :setup (lambda ()
-           (setq context-coloring-syntactic-comments t)
-           (setq context-coloring-syntactic-strings t)))
+cc `CC' `CC'
+nnnnnn n nnn"))))
+
+(context-coloring-test-deftest-emacs-lisp changed
+  (lambda ()
+    (context-coloring-test-remove-faces)
+    ;; Goto line 3.
+    (goto-char (point-min))
+    (forward-line (1- 3))
+    (insert " ")
+    ;; Mock `pos-visible-in-window-p' because in batch mode `get-buffer-window'
+    ;; returns nil.  Emacs must not have a window in that environment.
+    (cl-letf (((symbol-function 'pos-visible-in-window-p)
+               (let ((calls 0))
+                 (lambda ()
+                   (prog1
+                       ;; First and third calls start from center.  Second and
+                       ;; fourth calls are made immediately after moving past
+                       ;; the first defun in either direction "off screen".
+                       (cond
+                        ((= calls 0) t)
+                        ((= calls 1) nil)
+                        ((= calls 2) t)
+                        ((= calls 4) nil))
+                     (setq calls (1+ calls)))))))
+      (context-coloring-colorize))
+    (context-coloring-test-assert-coloring "
+nnnn  n nnn nnnnnnnn
+0000
+
+0000
+nnnnn n nnn nnnnnnnn")))
+
+(context-coloring-test-deftest-emacs-lisp unbalanced-parenthesis
+  (lambda ()
+    (context-coloring-test-assert-coloring "
+1111 111
+nnnn nn")))
 
 (provide 'context-coloring-test)
 
diff --git a/packages/context-coloring/test/fixtures/changed.el 
b/packages/context-coloring/test/fixtures/changed.el
new file mode 100644
index 0000000..28c9602
--- /dev/null
+++ b/packages/context-coloring/test/fixtures/changed.el
@@ -0,0 +1,5 @@
+(l1)  ; Not colored.
+(l2)
+
+(l4)
+(l5)  ; Not colored.
diff --git a/packages/context-coloring/test/fixtures/cond.el 
b/packages/context-coloring/test/fixtures/cond.el
new file mode 100644
index 0000000..d5aae5b
--- /dev/null
+++ b/packages/context-coloring/test/fixtures/cond.el
@@ -0,0 +1,8 @@
+(let (a)
+  (cond
+   (a t)
+   (free t)
+   ((eq a free) t)
+   (t (list a free))
+   ;; c
+   "s"))
diff --git a/packages/context-coloring/test/fixtures/condition-case.el 
b/packages/context-coloring/test/fixtures/condition-case.el
new file mode 100644
index 0000000..151f591
--- /dev/null
+++ b/packages/context-coloring/test/fixtures/condition-case.el
@@ -0,0 +1,10 @@
+(condition-case err
+    (progn err free)
+  (error err free)
+  ((debug error) err free))
+
+(condition-case-unless-debug nil
+    ;; c
+    (let () nil)
+  (error (let () nil))
+  "s")
diff --git a/packages/context-coloring/test/fixtures/defadvice.el 
b/packages/context-coloring/test/fixtures/defadvice.el
new file mode 100644
index 0000000..da1f0eb
--- /dev/null
+++ b/packages/context-coloring/test/fixtures/defadvice.el
@@ -0,0 +1,3 @@
+(defadvice a (before advice first (b) activate)
+  (let ((c b))
+    (+ b c)))
diff --git a/packages/context-coloring/test/fixtures/defun.el 
b/packages/context-coloring/test/fixtures/defun.el
index a5bd039..10a52f6 100644
--- a/packages/context-coloring/test/fixtures/defun.el
+++ b/packages/context-coloring/test/fixtures/defun.el
@@ -5,3 +5,4 @@
 
 (defun a)
 (defun ())
+(defun b ("a"))
diff --git a/packages/context-coloring/test/fixtures/dolist.el 
b/packages/context-coloring/test/fixtures/dolist.el
new file mode 100644
index 0000000..f103670
--- /dev/null
+++ b/packages/context-coloring/test/fixtures/dolist.el
@@ -0,0 +1,3 @@
+(lambda (list)
+  (dolist (var list result)
+    (lambda () (+ var list result))))
diff --git a/packages/context-coloring/test/fixtures/ignored.el 
b/packages/context-coloring/test/fixtures/ignored.el
index 776a846..1f5fd42 100644
--- a/packages/context-coloring/test/fixtures/ignored.el
+++ b/packages/context-coloring/test/fixtures/ignored.el
@@ -1,2 +1,2 @@
 (defun a ()
-  (+ a 1 +1 -1 1.0 :a t nil (0 . 0)))
+  (+ a 1 +1 -1 1.0 #x0 ,a \a :a t nil (0 . 0)))
diff --git a/packages/context-coloring/test/fixtures/let.el 
b/packages/context-coloring/test/fixtures/let.el
index 11637b1..04fc039 100644
--- a/packages/context-coloring/test/fixtures/let.el
+++ b/packages/context-coloring/test/fixtures/let.el
@@ -6,3 +6,6 @@
                (c free))
            (and a b c free))))
   (and a b c free))
+
+(let ;; comment
+    ("s"))
diff --git a/packages/context-coloring/test/fixtures/quote.el 
b/packages/context-coloring/test/fixtures/quote.el
index 654bc70..5fc126d 100644
--- a/packages/context-coloring/test/fixtures/quote.el
+++ b/packages/context-coloring/test/fixtures/quote.el
@@ -1,4 +1,15 @@
+(quote (lambda () free))
+(let () (backquote (,free)))
+
 (defun a (a)
   (or (eq a 'b)
       (equal a '(a b))
-      (equal a `(,(append () `(a b ,(+ 1 free) ,free b) free) b ,free))))
+      (equal a `(,(append () `(a b ,(+ 1 free) ,free b) free) b ,free
+                 "s" ; c
+                 ))))
+
+(append '("a" ; b
+          "b" ; a
+          ))
+
+(lambda () '((?\" ?\")))
diff --git a/packages/context-coloring/test/fixtures/sexp.el 
b/packages/context-coloring/test/fixtures/sexp.el
new file mode 100644
index 0000000..438dc02
--- /dev/null
+++ b/packages/context-coloring/test/fixtures/sexp.el
@@ -0,0 +1,4 @@
+(let ()
+  `,@"a"
+  `,@'b
+  `,@\c)
diff --git a/packages/context-coloring/test/fixtures/splice.el 
b/packages/context-coloring/test/fixtures/splice.el
new file mode 100644
index 0000000..3a857a7
--- /dev/null
+++ b/packages/context-coloring/test/fixtures/splice.el
@@ -0,0 +1,2 @@
+(lambda ()
+  `(,@(a free) ,free))
diff --git a/packages/context-coloring/test/fixtures/unbalanced-parenthesis.el 
b/packages/context-coloring/test/fixtures/unbalanced-parenthesis.el
new file mode 100644
index 0000000..caaf7e2
--- /dev/null
+++ b/packages/context-coloring/test/fixtures/unbalanced-parenthesis.el
@@ -0,0 +1,2 @@
+(let ())
+(let ()



reply via email to

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